Search in sources :

Example 56 with Literal

use of at.ac.tuwien.kr.alpha.api.programs.literals.Literal in project Alpha by alpha-asp.

the class MinMaxEncoder method encodeAggregateResult.

@Override
protected ASPCore2Program encodeAggregateResult(AggregateInfo aggregateToEncode) {
    ST encodingTemplate = null;
    if (this.getAggregateFunctionToEncode() == AggregateFunctionSymbol.MAX) {
        encodingTemplate = new ST(MAX_LITERAL_ENCODING);
    } else if (this.getAggregateFunctionToEncode() == AggregateFunctionSymbol.MIN) {
        encodingTemplate = new ST(MIN_LITERAL_ENCODING);
    } else {
        // Note that this should definitely not happen due to the check in the constructor!
        throw new UnsupportedOperationException("Cannot encode anything other than min/max aggregates!");
    }
    String id = aggregateToEncode.getId();
    String resultName = aggregateToEncode.getOutputAtom().getPredicate().getName();
    AggregateAtom atom = aggregateToEncode.getLiteral().getAtom();
    ComparisonOperator cmpOp = atom.getLowerBoundOperator();
    encodingTemplate.add("id", id);
    encodingTemplate.add("aggregate_result", resultName);
    if (cmpOp.equals(ComparisonOperators.EQ)) {
        // Aggregate to encode binds a variable, use appropriate result rule.
        ST resultRuleTemplate = new ST(BINDING_LITERAL_RESULT_RULE);
        resultRuleTemplate.add("agg_func", atom.getAggregateFunction().toString().toLowerCase());
        resultRuleTemplate.add("id", id);
        resultRuleTemplate.add("aggregate_result", resultName);
        return parser.parse(encodingTemplate.render() + resultRuleTemplate.render());
    } else {
        /*
			 * Aggregate encoding needs to compare aggregate value with another variable.
			 * Note that this should also use a string template for the result rule. However,
			 * since we need to compared to a (user-supplied) variable, we have to use a definitely
			 * non-conflicting variable name for the aggregate value, i.e. something prefixed with "_".
			 * Since the ProgramParser doesn't accept this, we need to build the result rule
			 * programmatically as a workaround.
			 *
			 * Result rule stringtemplate for reference:
			 * $aggregate_result$($args$, $cmp_term$) :-
			 * $cmp_term$ $cmp_op$ AGG_VAL,
			 * $id$_$agg_func$_element_tuple($args$, AGG_VAL),
			 * $dependencies;separator=\", \"$."
			 */
        NormalHead resultRuleHead = Heads.newNormalHead(Atoms.newBasicAtom(Predicates.getPredicate(resultName, 2), aggregateToEncode.getAggregateArguments(), atom.getLowerBoundTerm()));
        List<Literal> resultRuleBody = new ArrayList<>();
        VariableTerm aggregateValue = Terms.newVariable("_AGG_VAL");
        ComparisonLiteral aggregateValueComparison = Literals.fromAtom(Atoms.newComparisonAtom(atom.getLowerBoundTerm(), aggregateValue, cmpOp), true);
        Literal aggregateResult = Atoms.newBasicAtom(Predicates.getPredicate(id + "_" + atom.getAggregateFunction().toString().toLowerCase() + "_element_tuple", 2), aggregateToEncode.getAggregateArguments(), aggregateValue).toLiteral();
        resultRuleBody.add(aggregateResult);
        resultRuleBody.add(aggregateValueComparison);
        resultRuleBody.addAll(aggregateToEncode.getDependencies());
        InputProgram.Builder bld = InputProgram.builder(parser.parse(encodingTemplate.render()));
        BasicRule resultRule = new BasicRule(resultRuleHead, resultRuleBody);
        bld.addRule(resultRule);
        return bld.build();
    }
}
Also used : BasicRule(at.ac.tuwien.kr.alpha.core.rules.BasicRule) ST(org.stringtemplate.v4.ST) ComparisonOperator(at.ac.tuwien.kr.alpha.api.ComparisonOperator) ArrayList(java.util.ArrayList) 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) AggregateAtom(at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom) ComparisonLiteral(at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral) InputProgram(at.ac.tuwien.kr.alpha.core.programs.InputProgram)

Example 57 with Literal

use of at.ac.tuwien.kr.alpha.api.programs.literals.Literal in project Alpha by alpha-asp.

the class ChoiceHeadToNormal method apply.

@Override
public ASPCore2Program apply(ASPCore2Program inputProgram) {
    InputProgram.Builder programBuilder = InputProgram.builder();
    List<Rule<Head>> additionalRules = new ArrayList<>();
    List<Rule<Head>> srcRules = new ArrayList<>(inputProgram.getRules());
    Iterator<Rule<Head>> ruleIterator = srcRules.iterator();
    while (ruleIterator.hasNext()) {
        Rule<Head> rule = ruleIterator.next();
        Head ruleHead = rule.getHead();
        if (!(ruleHead instanceof ChoiceHead)) {
            // Rule is constraint or without choice in the head. Leave as is.
            continue;
        }
        // Remove this rule, as it will be transformed.
        ruleIterator.remove();
        ChoiceHead choiceHead = (ChoiceHead) ruleHead;
        // Choice rules with boundaries are not yet supported.
        if (choiceHead.getLowerBound() != null || choiceHead.getUpperBound() != null) {
            throw new UnsupportedOperationException("Found choice rule with bounds, which are not yet supported. Rule is: " + rule);
        }
        // Only rewrite rules with a choice in their head.
        for (ChoiceElement choiceElement : choiceHead.getChoiceElements()) {
            // Create two guessing rules for each choiceElement.
            // Construct common body to both rules.
            BasicAtom head = choiceElement.getChoiceAtom();
            List<Literal> ruleBody = new ArrayList<>(rule.getBody());
            ruleBody.addAll(choiceElement.getConditionLiterals());
            if (containsIntervalTerms(head)) {
                throw new RuntimeException("Program contains a choice rule with interval terms in its head. This is not supported (yet).");
            }
            // Construct head atom for the choice.
            Predicate headPredicate = head.getPredicate();
            Predicate negPredicate = Predicates.getPredicate(PREDICATE_NEGATION_PREFIX + headPredicate.getName(), headPredicate.getArity() + 1, true);
            List<Term> headTerms = new ArrayList<>(head.getTerms());
            // FIXME: when introducing classical negation, this is 1 for classical positive atoms and 0 for
            headTerms.add(0, Terms.newConstant("1"));
            // classical negative atoms.
            BasicAtom negHead = Atoms.newBasicAtom(negPredicate, headTerms);
            // Construct two guessing rules.
            List<Literal> guessingRuleBodyWithNegHead = new ArrayList<>(ruleBody);
            guessingRuleBodyWithNegHead.add(Atoms.newBasicAtom(head.getPredicate(), head.getTerms()).toLiteral(false));
            additionalRules.add(new BasicRule(Heads.newNormalHead(negHead), guessingRuleBodyWithNegHead));
            List<Literal> guessingRuleBodyWithHead = new ArrayList<>(ruleBody);
            guessingRuleBodyWithHead.add(Atoms.newBasicAtom(negPredicate, headTerms).toLiteral(false));
            additionalRules.add(new BasicRule(Heads.newNormalHead(head), guessingRuleBodyWithHead));
        // TODO: when cardinality constraints are possible, process the boundaries by adding a constraint with a cardinality check.
        }
    }
    return programBuilder.addRules(srcRules).addRules(additionalRules).addFacts(inputProgram.getFacts()).addInlineDirectives(inputProgram.getInlineDirectives()).build();
}
Also used : BasicRule(at.ac.tuwien.kr.alpha.core.rules.BasicRule) ChoiceHead(at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead) Head(at.ac.tuwien.kr.alpha.api.rules.heads.Head) ArrayList(java.util.ArrayList) Term(at.ac.tuwien.kr.alpha.api.terms.Term) IntervalTerm(at.ac.tuwien.kr.alpha.commons.terms.IntervalTerm) Predicate(at.ac.tuwien.kr.alpha.api.programs.Predicate) ChoiceElement(at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead.ChoiceElement) ChoiceHead(at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead) Literal(at.ac.tuwien.kr.alpha.api.programs.literals.Literal) Rule(at.ac.tuwien.kr.alpha.api.rules.Rule) BasicRule(at.ac.tuwien.kr.alpha.core.rules.BasicRule) BasicAtom(at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom) InputProgram(at.ac.tuwien.kr.alpha.core.programs.InputProgram)

Example 58 with Literal

use of at.ac.tuwien.kr.alpha.api.programs.literals.Literal in project Alpha by alpha-asp.

the class ArithmeticTermsRewriting method rewriteRule.

/**
 * Takes a normal rule and rewrites it such that {@link ArithmeticTerm}s only appear inside {@link at.ac.tuwien.kr.alpha.common.atoms.ComparisonLiteral}s.
 *
 * @param inputProgramRule the rule to rewrite.
 * @return the rewritten rule. Note that a new {@link NormalRule} is returned for every call of this method.
 */
private NormalRule rewriteRule(NormalRule inputProgramRule) {
    // Reset number of introduced variables for each rule.
    numArithmeticVariables = 0;
    NormalHead rewrittenHead = null;
    List<Literal> rewrittenBodyLiterals = new ArrayList<>();
    // Rewrite head.
    if (!inputProgramRule.isConstraint()) {
        BasicAtom headAtom = inputProgramRule.getHeadAtom();
        if (containsArithmeticTermsToRewrite(headAtom)) {
            rewrittenHead = Heads.newNormalHead((BasicAtom) rewriteAtom(headAtom, rewrittenBodyLiterals));
        } else {
            rewrittenHead = inputProgramRule.getHead();
        }
    }
    // Rewrite body.
    for (Literal literal : inputProgramRule.getBody()) {
        if (!containsArithmeticTermsToRewrite(literal.getAtom())) {
            // Keep body literal as-is if no ArithmeticTerm occurs.
            rewrittenBodyLiterals.add(literal);
            continue;
        }
        rewrittenBodyLiterals.add(rewriteAtom(literal.getAtom(), rewrittenBodyLiterals).toLiteral(!literal.isNegated()));
    }
    return new NormalRuleImpl(rewrittenHead, rewrittenBodyLiterals);
}
Also used : NormalHead(at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead) Literal(at.ac.tuwien.kr.alpha.api.programs.literals.Literal) ArrayList(java.util.ArrayList) NormalRuleImpl(at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl) BasicAtom(at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom)

Example 59 with Literal

use of at.ac.tuwien.kr.alpha.api.programs.literals.Literal in project Alpha by alpha-asp.

the class EnumerationRewriting method rewriteRules.

private List<Rule<Head>> rewriteRules(List<Rule<Head>> srcRules, Predicate enumPredicate) {
    List<Rule<Head>> rewrittenRules = new ArrayList<>();
    for (Rule<Head> rule : srcRules) {
        if (rule.getHead() != null && !(rule.getHead() instanceof NormalHead)) {
            throw oops("Encountered rule whose head is not normal: " + rule);
        }
        if (rule.getHead() != null && ((NormalHead) rule.getHead()).getAtom().getPredicate().equals(enumPredicate)) {
            throw oops("Atom declared as enumeration atom by directive occurs in head of the rule: " + rule);
        }
        List<Literal> modifiedBodyLiterals = new ArrayList<>(rule.getBody());
        Iterator<Literal> rit = modifiedBodyLiterals.iterator();
        LinkedList<Literal> rewrittenLiterals = new LinkedList<>();
        while (rit.hasNext()) {
            Literal literal = rit.next();
            if (!(literal instanceof BasicLiteral)) {
                continue;
            }
            BasicLiteral basicLiteral = (BasicLiteral) literal;
            if (!basicLiteral.getPredicate().equals(enumPredicate)) {
                continue;
            }
            // basicLiteral is an enumeration literal (i.e. predicate is marked as enum using directive)
            rit.remove();
            Term enumIdTerm = basicLiteral.getAtom().getTerms().get(0);
            Term valueTerm = basicLiteral.getAtom().getTerms().get(1);
            VariableTerm indexTerm = (VariableTerm) basicLiteral.getAtom().getTerms().get(2);
            rewrittenLiterals.add(new EnumerationAtom(enumIdTerm, valueTerm, indexTerm).toLiteral());
        }
        modifiedBodyLiterals.addAll(rewrittenLiterals);
        rewrittenRules.add(new BasicRule(rule.getHead(), modifiedBodyLiterals));
    }
    return rewrittenRules;
}
Also used : BasicRule(at.ac.tuwien.kr.alpha.core.rules.BasicRule) Head(at.ac.tuwien.kr.alpha.api.rules.heads.Head) NormalHead(at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead) ArrayList(java.util.ArrayList) Term(at.ac.tuwien.kr.alpha.api.terms.Term) VariableTerm(at.ac.tuwien.kr.alpha.api.terms.VariableTerm) LinkedList(java.util.LinkedList) BasicLiteral(at.ac.tuwien.kr.alpha.api.programs.literals.BasicLiteral) NormalHead(at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead) Literal(at.ac.tuwien.kr.alpha.api.programs.literals.Literal) BasicLiteral(at.ac.tuwien.kr.alpha.api.programs.literals.BasicLiteral) EnumerationAtom(at.ac.tuwien.kr.alpha.core.atoms.EnumerationAtom) VariableTerm(at.ac.tuwien.kr.alpha.api.terms.VariableTerm) Rule(at.ac.tuwien.kr.alpha.api.rules.Rule) BasicRule(at.ac.tuwien.kr.alpha.core.rules.BasicRule)

Example 60 with Literal

use of at.ac.tuwien.kr.alpha.api.programs.literals.Literal 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)

Aggregations

Literal (at.ac.tuwien.kr.alpha.api.programs.literals.Literal)82 Test (org.junit.jupiter.api.Test)42 VariableTerm (at.ac.tuwien.kr.alpha.api.terms.VariableTerm)20 ArrayList (java.util.ArrayList)20 AggregateLiteral (at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral)17 Atom (at.ac.tuwien.kr.alpha.api.programs.atoms.Atom)16 Substitution (at.ac.tuwien.kr.alpha.api.grounder.Substitution)14 Predicate (at.ac.tuwien.kr.alpha.api.programs.Predicate)14 BasicAtom (at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom)14 BasicSubstitution (at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution)13 Map (java.util.Map)12 Head (at.ac.tuwien.kr.alpha.api.rules.heads.Head)11 CompiledProgram (at.ac.tuwien.kr.alpha.core.programs.CompiledProgram)11 CompiledRule (at.ac.tuwien.kr.alpha.core.rules.CompiledRule)10 HashSet (java.util.HashSet)10 ComparisonLiteral (at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral)9 Instance (at.ac.tuwien.kr.alpha.commons.substitutions.Instance)9 LinkedHashSet (java.util.LinkedHashSet)8 List (java.util.List)8 Term (at.ac.tuwien.kr.alpha.api.terms.Term)7