Skip to content

Commit

Permalink
Evolog Modules: Draft implementation of ModuleLinker, which construct…
Browse files Browse the repository at this point in the history
…s interpretations for module literals by wrapping calls to the ASP solver.
  • Loading branch information
madmike200590 committed Jul 25, 2024
1 parent f338eeb commit d410ad1
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation;
import at.ac.tuwien.kr.alpha.api.programs.VariableNormalizableAtom;
import at.ac.tuwien.kr.alpha.api.programs.literals.ExternalLiteral;
import at.ac.tuwien.kr.alpha.api.programs.terms.Term;

/**
Expand All @@ -21,4 +22,12 @@ public interface ExternalAtom extends Atom, VariableNormalizableAtom {

PredicateInterpretation getInterpretation();

@Override
default ExternalLiteral toLiteral() {
return toLiteral(true);
}

@Override
ExternalLiteral toLiteral(boolean positive);

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution;

import java.util.*;
import java.util.function.Predicate;

/**
* Contains a potentially negated {@link ExternalAtom}.
Expand Down Expand Up @@ -128,10 +129,12 @@ public List<Substitution> getSatisfyingSubstitutions(Substitution partialSubstit
substitutes.add(t.substitute(partialSubstitution));
}
Set<List<Term>> results = getAtom().getInterpretation().evaluate(substitutes);
// TODO verify all results are ground
if (results == null) {
throw new NullPointerException("Predicate " + getPredicate().getName() + " returned null. It must return a Set.");
}
if (results.stream().anyMatch(trms -> trms.stream().anyMatch(Predicate.not(Term::isGround)))) {
throw new IllegalStateException("Predicate " + getPredicate().getName() + " returned non-ground term.");
}

if (this.isNegated()) {
return this.isNegatedLiteralSatisfied(results) ? Collections.singletonList(partialSubstitution) : Collections.emptyList();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
package at.ac.tuwien.kr.alpha.core.programs.transformation;

import at.ac.tuwien.kr.alpha.api.Alpha;
import at.ac.tuwien.kr.alpha.api.AnswerSet;
import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation;
import at.ac.tuwien.kr.alpha.api.programs.Predicate;
import at.ac.tuwien.kr.alpha.api.programs.NormalProgram;
import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom;
import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom;
import at.ac.tuwien.kr.alpha.api.programs.atoms.ExternalAtom;
import at.ac.tuwien.kr.alpha.api.programs.atoms.ModuleAtom;
import at.ac.tuwien.kr.alpha.api.programs.literals.Literal;
import at.ac.tuwien.kr.alpha.api.programs.literals.ModuleLiteral;
import at.ac.tuwien.kr.alpha.api.programs.modules.Module;
import at.ac.tuwien.kr.alpha.api.programs.rules.NormalRule;
import at.ac.tuwien.kr.alpha.api.programs.rules.Rule;
import at.ac.tuwien.kr.alpha.api.programs.rules.heads.NormalHead;
import at.ac.tuwien.kr.alpha.api.programs.terms.Term;
import at.ac.tuwien.kr.alpha.commons.programs.Programs;
import at.ac.tuwien.kr.alpha.commons.programs.atoms.Atoms;
import at.ac.tuwien.kr.alpha.commons.programs.rules.Rules;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.SetUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* Program transformation that translates {@link at.ac.tuwien.kr.alpha.api.programs.literals.ModuleLiteral}s into
Expand Down Expand Up @@ -57,17 +70,57 @@ private NormalRule linkModuleAtoms(NormalRule rule, Map<String, Module> moduleTa
return Rules.newNormalRule(newHead, newBody);
}

private ExternalAtom translateModuleAtom(ModuleAtom moduleAtom, Map<String, Module> moduleTable) {
if (!moduleTable.containsKey(moduleAtom.getModuleName())) {
throw new IllegalArgumentException("Module " + moduleAtom.getModuleName() + " not found in module table.");
private ExternalAtom translateModuleAtom(ModuleAtom atom, Map<String, Module> moduleTable) {
if (!moduleTable.containsKey(atom.getModuleName())) {
throw new IllegalArgumentException("Module " + atom.getModuleName() + " not found in module table.");
}
Module implementationModule = moduleTable.get(moduleAtom.getModuleName());
//implementationModule.
return null;
Module definition = moduleTable.get(atom.getModuleName());
// verify inputs
Predicate inputSpec = definition.getInputSpec();
if (atom.getInput().size() != inputSpec.getArity()) {
throw new IllegalArgumentException("Module " + atom.getModuleName() + " expects " + inputSpec.getArity() + " inputs, but " + atom.getInput().size() + " were given.");
}
NormalProgram normalizedImplementation = moduleRunner.normalizeProgram(definition.getImplementation());
// verify outputs
Set<Predicate> outputSpec = definition.getOutputSpec();
int expectedOutputTerms;
if (outputSpec.isEmpty()) {
expectedOutputTerms = calculateOutputPredicates(normalizedImplementation).size();
} else {
expectedOutputTerms = outputSpec.size();
}
if (atom.getOutput().size() != expectedOutputTerms) {
throw new IllegalArgumentException("Module " + atom.getModuleName() + " expects " + outputSpec.size() + " outputs, but " + atom.getOutput().size() + " were given.");
}
// create the actual interpretation
PredicateInterpretation interpretation = terms -> {
BasicAtom inputAtom = Atoms.newBasicAtom(inputSpec, terms);
NormalProgram program = Programs.newNormalProgram(normalizedImplementation.getRules(),
ListUtils.union(List.of(inputAtom), normalizedImplementation.getFacts()), normalizedImplementation.getInlineDirectives());
java.util.function.Predicate<Predicate> filter = outputSpec.isEmpty() ? p -> true : outputSpec::contains;
Stream<AnswerSet> answerSets = moduleRunner.solve(program, filter);
if (atom.getInstantiationMode().requestedAnswerSets().isPresent()) {
answerSets = answerSets.limit(atom.getInstantiationMode().requestedAnswerSets().get());
}
return answerSets.map(ModuleLinker::answerSetToTerms).collect(Collectors.toSet());
};
return Atoms.newExternalAtom(atom.getPredicate(), interpretation, atom.getInput(), atom.getOutput());
}

private static boolean containsModuleAtom(NormalRule rule) {
return rule.getBody().stream().anyMatch(literal -> literal instanceof ModuleLiteral);
}

private static Set<Predicate> calculateOutputPredicates(NormalProgram program) {
return SetUtils.union(program.getFacts().stream().map(Atom::getPredicate).collect(Collectors.toSet()),
program.getRules().stream()
.filter(java.util.function.Predicate.not(Rule::isConstraint))
.map(Rule::getHead).map(NormalHead::getAtom).map(Atom::getPredicate)
.collect(Collectors.toSet()));
}

private static List<Term> answerSetToTerms(AnswerSet answerSet) {
return Collections.emptyList(); // TODO
}

}

0 comments on commit d410ad1

Please sign in to comment.