use of at.ac.tuwien.kr.alpha.commons.substitutions.Unifier in project Alpha by alpha-asp.
the class VariableEqualityRemoval method findAndReplaceVariableEquality.
private Rule<Head> findAndReplaceVariableEquality(Rule<Head> rule) {
// Collect all equal variables.
HashMap<VariableTerm, HashSet<VariableTerm>> variableToEqualVariables = new LinkedHashMap<>();
HashSet<Literal> equalitiesToRemove = new HashSet<>();
for (Literal bodyElement : rule.getBody()) {
if (!(bodyElement instanceof ComparisonLiteral)) {
continue;
}
ComparisonLiteral comparisonLiteral = (ComparisonLiteral) bodyElement;
if (!comparisonLiteral.isNormalizedEquality()) {
continue;
}
if (comparisonLiteral.getTerms().get(0) instanceof VariableTerm && comparisonLiteral.getTerms().get(1) instanceof VariableTerm) {
VariableTerm leftVariable = (VariableTerm) comparisonLiteral.getTerms().get(0);
VariableTerm rightVariable = (VariableTerm) comparisonLiteral.getTerms().get(1);
HashSet<VariableTerm> leftEqualVariables = variableToEqualVariables.get(leftVariable);
HashSet<VariableTerm> rightEqualVariables = variableToEqualVariables.get(rightVariable);
if (leftEqualVariables == null && rightEqualVariables == null) {
HashSet<VariableTerm> equalVariables = new LinkedHashSet<>(Arrays.asList(leftVariable, rightVariable));
variableToEqualVariables.put(leftVariable, equalVariables);
variableToEqualVariables.put(rightVariable, equalVariables);
}
if (leftEqualVariables == null && rightEqualVariables != null) {
rightEqualVariables.add(leftVariable);
variableToEqualVariables.put(leftVariable, rightEqualVariables);
}
if (leftEqualVariables != null && rightEqualVariables == null) {
leftEqualVariables.add(rightVariable);
variableToEqualVariables.put(rightVariable, leftEqualVariables);
}
if (leftEqualVariables != null && rightEqualVariables != null) {
leftEqualVariables.addAll(rightEqualVariables);
for (VariableTerm rightEqualVariable : rightEqualVariables) {
variableToEqualVariables.put(rightEqualVariable, leftEqualVariables);
}
}
equalitiesToRemove.add(comparisonLiteral);
}
}
if (variableToEqualVariables.isEmpty()) {
// Skip rule if there is no equality between variables.
return rule;
}
List<Literal> rewrittenBody = new ArrayList<>(rule.getBody());
if (!rule.isConstraint() && rule.getHead() instanceof DisjunctiveHead) {
throw new UnsupportedOperationException("VariableEqualityRemoval cannot be applied to rule with DisjunctiveHead, yet.");
}
NormalHead rewrittenHead = rule.isConstraint() ? null : Heads.newNormalHead(((NormalHead) rule.getHead()).getAtom());
// Use substitution for actual replacement.
Unifier replacementSubstitution = new Unifier();
// For each set of equal variables, take the first variable and replace all others by it.
for (Map.Entry<VariableTerm, HashSet<VariableTerm>> variableEqualityEntry : variableToEqualVariables.entrySet()) {
VariableTerm variableToReplace = variableEqualityEntry.getKey();
VariableTerm replacementVariable = variableEqualityEntry.getValue().iterator().next();
if (variableToReplace == replacementVariable) {
continue;
}
replacementSubstitution.put(variableToReplace, replacementVariable);
}
// Replace/Substitute in each literal every term where one of the common variables occurs.
Iterator<Literal> bodyIterator = rewrittenBody.iterator();
while (bodyIterator.hasNext()) {
Literal literal = bodyIterator.next();
if (equalitiesToRemove.contains(literal)) {
bodyIterator.remove();
}
for (int i = 0; i < literal.getTerms().size(); i++) {
Term replaced = literal.getTerms().get(i).substitute(replacementSubstitution);
literal.getTerms().set(i, replaced);
}
}
// Replace variables in head.
if (rewrittenHead != null) {
Atom headAtom = rewrittenHead.getAtom();
for (int i = 0; i < headAtom.getTerms().size(); i++) {
Term replaced = headAtom.getTerms().get(i).substitute(replacementSubstitution);
headAtom.getTerms().set(i, replaced);
}
}
return new BasicRule(rewrittenHead, rewrittenBody);
}
use of at.ac.tuwien.kr.alpha.commons.substitutions.Unifier in project Alpha by alpha-asp.
the class AnalyzeUnjustified method explainUnjust.
private ReturnExplainUnjust explainUnjust(LitSet x, Assignment currentAssignment) {
padDepth += 2;
log("Begin explainUnjust(): {}", x);
Atom p = x.getAtom();
ReturnExplainUnjust ret = new ReturnExplainUnjust();
// Construct set of all 'rules' such that head unifies with p.
List<RuleAndUnifier> rulesUnifyingWithP = rulesHeadUnifyingWith(p);
log("Rules unifying with {} are {}", p, rulesUnifyingWithP);
rulesLoop: for (RuleAndUnifier ruleUnifier : rulesUnifyingWithP) {
Unifier sigma = ruleUnifier.unifier;
Set<Literal> bodyR = ruleUnifier.ruleBody;
Atom sigmaHr = ruleUnifier.originalHead.substitute(sigma);
log("Considering now: {}", ruleUnifier);
Set<Unifier> vN = new LinkedHashSet<>(x.getComplementSubstitutions());
for (Unifier sigmaN : vN) {
if (Unification.instantiate(p.substitute(sigmaN), sigmaHr) != null) {
log("Unifier is excluded by: {}", sigmaN);
continue rulesLoop;
}
}
Set<Unifier> vNp = new LinkedHashSet<>();
for (Unifier substitution : vN) {
Unifier merged = Unifier.mergeIntoLeft(substitution, sigma);
// Ignore inconsistent merges.
if (merged == null) {
continue;
}
vNp.add(merged);
}
log("Adapting N to N'. Original N is {}", vN);
log("Adapted N' is {}", vNp);
log("Searching for falsified negated literals in the body: {}", bodyR);
for (Literal lit : bodyR) {
if (!lit.isNegated()) {
continue;
}
Atom lb = lit.getAtom().substitute(sigma);
log("Found: {}, searching falsifying ground instances of {} (with unifier from the head) now.", lit, lb);
AssignedAtomsIterator assignedAtomsOverPredicate = getAssignedAtomsOverPredicate(lb.getPredicate());
while (assignedAtomsOverPredicate.hasNext()) {
Atom lg = assignedAtomsOverPredicate.next();
log("Considering: {}", lg);
if (atomStore.contains(lg)) {
int atomId = atomStore.get(lg);
if (!currentAssignment.getTruth(atomId).toBoolean()) {
log("{} is not assigned TRUE or MBT. Skipping.", lg);
continue;
}
}
// Note: in case the atom is not in the atomStore, it came from a fact and hence is true.
log("{} is TRUE or MBT.", lg);
Unifier sigmagb = Unification.unifyAtoms(lg, lb);
if (sigmagb == null) {
log("{} does not unify with {}", lg, lb);
continue;
}
log("Checking if {} is already covered.", lb);
boolean isCovered = false;
for (Unifier sigmaN : vN) {
if (Unification.instantiate(p.substitute(sigmaN), sigmaHr.substitute(sigmagb)) != null) {
log("{} is already covered by {}", lb, sigmaN);
isCovered = true;
break;
}
}
if (!isCovered) {
Unifier sigmacirc = new Unifier(sigma).extendWith(sigmagb);
vNp.add(sigmacirc);
log("Literal {} is not excluded and falsifies body literal {}", lg, lit);
ret.vL.add(lg.toLiteral());
log("Reasons extended by: {}", lg);
}
}
}
List<Literal> bodyPos = new ArrayList<>();
for (Literal literal : bodyR) {
if (!literal.isNegated()) {
bodyPos.add(literal);
}
}
log("Calling UnjustCover() for positive body.");
ret.vToDo.addAll(unjustCover(bodyPos, Collections.singleton(sigma), vNp, currentAssignment));
}
log("End explainUnjust().");
padDepth -= 2;
return ret;
}
use of at.ac.tuwien.kr.alpha.commons.substitutions.Unifier in project Alpha by alpha-asp.
the class AnalyzeUnjustified method rulesHeadUnifyingWith.
private List<RuleAndUnifier> rulesHeadUnifyingWith(Atom p) {
List<RuleAndUnifier> rulesWithUnifier = new ArrayList<>();
Predicate predicate = p.getPredicate();
ArrayList<FactOrNonGroundRule> definingRulesAndFacts = new ArrayList<>();
// Get facts over the same predicate.
LinkedHashSet<Instance> factInstances = factsFromProgram.get(predicate);
if (factInstances != null) {
for (Instance factInstance : factInstances) {
definingRulesAndFacts.add(new FactOrNonGroundRule(factInstance));
}
}
HashSet<CompiledRule> rulesDefiningPredicate = programAnalysis.getPredicateDefiningRules().get(predicate);
if (rulesDefiningPredicate != null) {
for (CompiledRule nonGroundRule : rulesDefiningPredicate) {
definingRulesAndFacts.add(new FactOrNonGroundRule(nonGroundRule));
}
}
for (FactOrNonGroundRule factOrNonGroundRule : definingRulesAndFacts) {
boolean isNonGroundRule = factOrNonGroundRule.nonGroundRule != null;
Set<Literal> renamedBody;
Atom headAtom;
if (isNonGroundRule) {
// First rename all variables in the rule.
CompiledRule rule = factOrNonGroundRule.nonGroundRule.renameVariables("_" + renamingCounter++);
renamedBody = rule.getBody();
headAtom = rule.getHeadAtom();
} else {
// Create atom and empty rule body out of instance.
headAtom = Atoms.newBasicAtom(p.getPredicate(), factOrNonGroundRule.factInstance.terms);
renamedBody = Collections.emptySet();
}
// Unify rule head with literal to justify.
Unifier unifier = Unification.unifyAtoms(p, headAtom);
// Skip if unification failed.
if (unifier == null) {
continue;
}
rulesWithUnifier.add(new RuleAndUnifier(renamedBody, unifier, headAtom));
}
return rulesWithUnifier;
}
use of at.ac.tuwien.kr.alpha.commons.substitutions.Unifier in project Alpha by alpha-asp.
the class Unification method unifyAtoms.
private static Unifier unifyAtoms(Atom left, Atom right, boolean keepLeftAsIs) {
Set<VariableTerm> leftOccurringVariables = left.getOccurringVariables();
Set<VariableTerm> rightOccurringVaribles = right.getOccurringVariables();
boolean leftSmaller = leftOccurringVariables.size() < rightOccurringVaribles.size();
Set<VariableTerm> smallerSet = leftSmaller ? leftOccurringVariables : rightOccurringVaribles;
Set<VariableTerm> largerSet = leftSmaller ? rightOccurringVaribles : leftOccurringVariables;
for (VariableTerm variableTerm : smallerSet) {
if (largerSet.contains(variableTerm)) {
throw oops("Left and right atom share variables.");
}
}
Unifier mgu = new Unifier();
if (!left.getPredicate().equals(right.getPredicate())) {
return null;
}
for (int i = 0; i < left.getPredicate().getArity(); i++) {
final Term leftTerm = left.getTerms().get(i);
final Term rightTerm = right.getTerms().get(i);
if (!unifyTerms(leftTerm, rightTerm, mgu, keepLeftAsIs)) {
return null;
}
}
return mgu;
}
use of at.ac.tuwien.kr.alpha.commons.substitutions.Unifier in project Alpha by alpha-asp.
the class UnifierTest method extendUnifier.
@Test
public void extendUnifier() {
VariableTerm varX = Terms.newVariable("X");
VariableTerm varY = Terms.newVariable("Y");
Unifier sub1 = new Unifier();
sub1.put(varX, varY);
Unifier sub2 = new Unifier();
sub2.put(varY, Terms.newConstant("a"));
sub1.extendWith(sub2);
BasicAtom atom1 = parseAtom("p(X)");
Atom atomSubstituted = atom1.substitute(sub1);
assertEquals(Terms.newConstant("a"), atomSubstituted.getTerms().get(0));
}
Aggregations