use of at.ac.tuwien.kr.alpha.api.terms.VariableTerm in project Alpha by alpha-asp.
the class NaiveGrounder method getRulesWithUniqueHead.
private Set<CompiledRule> getRulesWithUniqueHead() {
// FIXME: below optimisation (adding support nogoods if there is only one rule instantiation per unique atom over the interpretation) could
// be done as a transformation (adding a non-ground constraint corresponding to the nogood that is generated by the grounder).
// Record all unique rule heads.
final Set<CompiledRule> uniqueGroundRulePerGroundHead = new HashSet<>();
for (Map.Entry<Predicate, LinkedHashSet<CompiledRule>> headDefiningRules : program.getPredicateDefiningRules().entrySet()) {
if (headDefiningRules.getValue().size() != 1) {
continue;
}
CompiledRule nonGroundRule = headDefiningRules.getValue().iterator().next();
// Check that all variables of the body also occur in the head (otherwise grounding is not unique).
Atom headAtom = nonGroundRule.getHeadAtom();
// Rule is not guaranteed unique if there are facts for it.
HashSet<Instance> potentialFacts = factsFromProgram.get(headAtom.getPredicate());
if (potentialFacts != null && !potentialFacts.isEmpty()) {
continue;
}
// Collect head and body variables.
HashSet<VariableTerm> occurringVariablesHead = new HashSet<>(headAtom.toLiteral().getBindingVariables());
HashSet<VariableTerm> occurringVariablesBody = new HashSet<>();
for (Literal lit : nonGroundRule.getPositiveBody()) {
occurringVariablesBody.addAll(lit.getBindingVariables());
}
occurringVariablesBody.removeAll(occurringVariablesHead);
// Check if ever body variables occurs in the head.
if (occurringVariablesBody.isEmpty()) {
uniqueGroundRulePerGroundHead.add(nonGroundRule);
}
}
return uniqueGroundRulePerGroundHead;
}
use of at.ac.tuwien.kr.alpha.api.terms.VariableTerm in project Alpha by alpha-asp.
the class RuleGroundingInfoImpl method computeGroundingOrder.
private void computeGroundingOrder(Literal startingLiteral) {
Set<Literal> bodyLiterals = internalRule.getBody();
HashSet<VariableTerm> boundVariables = new HashSet<>();
boundVariables.addAll(startingLiteral.getBindingVariables());
LinkedHashSet<Literal> remainingLiterals = new LinkedHashSet<>(bodyLiterals);
remainingLiterals.remove(startingLiteral);
ArrayList<Literal> literalsOrder;
if (fixedGroundingInstantiation) {
literalsOrder = new ArrayList<>(bodyLiterals.size());
literalsOrder.add(startingLiteral);
} else {
literalsOrder = new ArrayList<>(bodyLiterals.size() - 1);
}
int position = 0;
int positionLastVarBound = -1;
while (!remainingLiterals.isEmpty()) {
Literal nextGroundingLiteral = selectNextGroundingLiteral(remainingLiterals, boundVariables);
if (nextGroundingLiteral == null) {
throw new RuntimeException("Could not find a grounding order for rule " + internalRule + " with starting literal: " + startingLiteral + ". Rule is not safe.");
}
remainingLiterals.remove(nextGroundingLiteral);
boolean boundNewVars = boundVariables.addAll(nextGroundingLiteral.getBindingVariables());
if (boundNewVars) {
positionLastVarBound = position;
}
literalsOrder.add(nextGroundingLiteral);
position++;
}
if (fixedGroundingInstantiation) {
fixedGroundingOrder = new RuleGroundingOrderImpl(null, literalsOrder, positionLastVarBound, internalRule.isGround());
}
groundingOrders.put(startingLiteral, new RuleGroundingOrderImpl(startingLiteral, literalsOrder, positionLastVarBound, internalRule.isGround()));
}
use of at.ac.tuwien.kr.alpha.api.terms.VariableTerm in project Alpha by alpha-asp.
the class ExternalLiteralImpl method getNonBindingVariables.
@Override
public Set<VariableTerm> getNonBindingVariables() {
List<Term> input = getAtom().getInput();
List<Term> output = getAtom().getOutput();
// External atoms have their input always non-binding, since they cannot
// be queried without some concrete input.
Set<VariableTerm> nonbindingVariables = new HashSet<>();
for (Term term : input) {
nonbindingVariables.addAll(term.getOccurringVariables());
}
// non-binding.
if (this.isNegated()) {
for (Term out : output) {
if (out instanceof VariableTerm) {
nonbindingVariables.add((VariableTerm) out);
}
}
}
return nonbindingVariables;
}
use of at.ac.tuwien.kr.alpha.api.terms.VariableTerm in project Alpha by alpha-asp.
the class ExternalLiteralImpl method buildSubstitutionsForOutputs.
private List<Substitution> buildSubstitutionsForOutputs(Substitution partialSubstitution, Set<List<ConstantTerm<?>>> outputs) {
List<Substitution> retVal = new ArrayList<>();
List<Term> externalAtomOutputTerms = this.getAtom().getOutput();
for (List<ConstantTerm<?>> bindings : outputs) {
if (bindings.size() < externalAtomOutputTerms.size()) {
throw new RuntimeException("Predicate " + getPredicate().getName() + " returned " + bindings.size() + " terms when at least " + externalAtomOutputTerms.size() + " were expected.");
}
BasicSubstitution ith = new BasicSubstitution(partialSubstitution);
boolean skip = false;
for (int i = 0; i < externalAtomOutputTerms.size(); i++) {
Term out = externalAtomOutputTerms.get(i);
if (out instanceof VariableTerm) {
ith.put((VariableTerm) out, bindings.get(i));
} else {
if (!bindings.get(i).equals(out)) {
skip = true;
break;
}
}
}
if (!skip) {
retVal.add(ith);
}
}
return retVal;
}
use of at.ac.tuwien.kr.alpha.api.terms.VariableTerm in project Alpha by alpha-asp.
the class Unifier method mergeIntoLeft.
/**
* Merge substitution right into left as used in the AnalyzeUnjustified.
* Left mappings are seen as equalities, i.e.,
* if left has {@literal A -> B} and right has {@literal A -> t} then the result will have {@literal A -> t} and {@literal B -> t}.
* If both substitutions are inconsistent, i.e., {@literal A -> t1} in left and {@literal A -> t2} in right, then null is returned.
* @param left
* @param right
* @return
*/
public static Unifier mergeIntoLeft(Unifier left, Unifier right) {
// Note: we assume both substitutions are free of chains, i.e., no A->B, B->C but A->C, B->C.
Unifier ret = new Unifier(left);
for (Map.Entry<VariableTerm, Term> mapping : right.substitution.entrySet()) {
VariableTerm variable = mapping.getKey();
Term term = mapping.getValue();
// If variable is unset, simply add.
if (!ret.isVariableSet(variable)) {
ret.put(variable, term);
continue;
}
// Variable is already set.
Term setTerm = ret.eval(variable);
if (setTerm instanceof VariableTerm) {
// Variable maps to another variable in left.
// Add a new mapping of the setTerm variable into our right-assigned term.
ret.put((VariableTerm) setTerm, term);
// Note: Unifier.put takes care of resolving the chain variable->setTerm->term.
continue;
}
// Check for inconsistency.
if (setTerm != term) {
return null;
}
// Now setTerm equals term, no action needed.
}
return ret;
}
Aggregations