Search in sources :

Example 16 with Unifier

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);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) BasicRule(at.ac.tuwien.kr.alpha.core.rules.BasicRule) ArrayList(java.util.ArrayList) DisjunctiveHead(at.ac.tuwien.kr.alpha.api.rules.heads.DisjunctiveHead) Term(at.ac.tuwien.kr.alpha.api.terms.Term) VariableTerm(at.ac.tuwien.kr.alpha.api.terms.VariableTerm) Atom(at.ac.tuwien.kr.alpha.api.programs.atoms.Atom) LinkedHashMap(java.util.LinkedHashMap) NormalHead(at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead) Literal(at.ac.tuwien.kr.alpha.api.programs.literals.Literal) ComparisonLiteral(at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral) VariableTerm(at.ac.tuwien.kr.alpha.api.terms.VariableTerm) ComparisonLiteral(at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) Unifier(at.ac.tuwien.kr.alpha.commons.substitutions.Unifier) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 17 with Unifier

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;
}
Also used : HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) Literal(at.ac.tuwien.kr.alpha.api.programs.literals.Literal) ComparisonLiteral(at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral) ArrayList(java.util.ArrayList) List(java.util.List) BasicAtom(at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom) Atom(at.ac.tuwien.kr.alpha.api.programs.atoms.Atom) Unifier(at.ac.tuwien.kr.alpha.commons.substitutions.Unifier)

Example 18 with Unifier

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;
}
Also used : Instance(at.ac.tuwien.kr.alpha.commons.substitutions.Instance) ArrayList(java.util.ArrayList) BasicAtom(at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom) Atom(at.ac.tuwien.kr.alpha.api.programs.atoms.Atom) Predicate(at.ac.tuwien.kr.alpha.api.programs.Predicate) CompiledRule(at.ac.tuwien.kr.alpha.core.rules.CompiledRule) Literal(at.ac.tuwien.kr.alpha.api.programs.literals.Literal) ComparisonLiteral(at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral) Unifier(at.ac.tuwien.kr.alpha.commons.substitutions.Unifier)

Example 19 with Unifier

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;
}
Also used : VariableTerm(at.ac.tuwien.kr.alpha.api.terms.VariableTerm) VariableTerm(at.ac.tuwien.kr.alpha.api.terms.VariableTerm) Term(at.ac.tuwien.kr.alpha.api.terms.Term) ArithmeticTerm(at.ac.tuwien.kr.alpha.api.terms.ArithmeticTerm) FunctionTerm(at.ac.tuwien.kr.alpha.api.terms.FunctionTerm) Unifier(at.ac.tuwien.kr.alpha.commons.substitutions.Unifier)

Example 20 with Unifier

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));
}
Also used : VariableTerm(at.ac.tuwien.kr.alpha.api.terms.VariableTerm) BasicAtom(at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom) Unifier(at.ac.tuwien.kr.alpha.commons.substitutions.Unifier) BasicAtom(at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom) Atom(at.ac.tuwien.kr.alpha.api.programs.atoms.Atom) Test(org.junit.jupiter.api.Test)

Aggregations

Unifier (at.ac.tuwien.kr.alpha.commons.substitutions.Unifier)20 Atom (at.ac.tuwien.kr.alpha.api.programs.atoms.Atom)15 Test (org.junit.jupiter.api.Test)11 VariableTerm (at.ac.tuwien.kr.alpha.api.terms.VariableTerm)6 BasicAtom (at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom)5 Literal (at.ac.tuwien.kr.alpha.api.programs.literals.Literal)5 ArrayList (java.util.ArrayList)5 ComparisonLiteral (at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral)4 LinkedHashSet (java.util.LinkedHashSet)4 Term (at.ac.tuwien.kr.alpha.api.terms.Term)3 HashSet (java.util.HashSet)3 Set (java.util.Set)2 Predicate (at.ac.tuwien.kr.alpha.api.programs.Predicate)1 VariableNormalizableAtom (at.ac.tuwien.kr.alpha.api.programs.VariableNormalizableAtom)1 AggregateLiteral (at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral)1 DisjunctiveHead (at.ac.tuwien.kr.alpha.api.rules.heads.DisjunctiveHead)1 NormalHead (at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead)1 ArithmeticTerm (at.ac.tuwien.kr.alpha.api.terms.ArithmeticTerm)1 FunctionTerm (at.ac.tuwien.kr.alpha.api.terms.FunctionTerm)1 Instance (at.ac.tuwien.kr.alpha.commons.substitutions.Instance)1