Search in sources :

Example 1 with NormalHead

use of at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead in project Alpha by alpha-asp.

the class AggregateRewritingRuleAnalysis method findGlobalVariablesPerAggregate.

private void findGlobalVariablesPerAggregate() {
    // First, compute all global variables, that is all variables occurring in a rule except those occurring
    // inside aggregate elements.
    Set<VariableTerm> globalVariables = new HashSet<>();
    if (!rule.isConstraint()) {
        // Head must be normal at this point.
        NormalHead head = (NormalHead) rule.getHead();
        globalVariables.addAll(head.getAtom().getOccurringVariables());
    }
    for (Literal literal : rule.getBody()) {
        if (literal instanceof AggregateLiteral) {
            aggregatesInRule.add((AggregateLiteral) literal);
            AggregateAtom aggregateAtom = (AggregateAtom) literal.getAtom();
            // All variables in the bounds of an aggregate are also global variables.
            // Note that at this point, only lower bounds appear in aggregates.
            globalVariables.addAll(aggregateAtom.getLowerBoundTerm().getOccurringVariables());
        } else {
            globalVariables.addAll(literal.getOccurringVariables());
        }
    }
    // Second, compute for each aggregate those of its variables that are global.
    for (AggregateLiteral aggregateLiteral : aggregatesInRule) {
        Set<VariableTerm> globalVariablesInAggregate = new HashSet<>();
        for (VariableTerm aggregateVariable : aggregateLiteral.getAtom().getAggregateVariables()) {
            if (globalVariables.contains(aggregateVariable)) {
                globalVariablesInAggregate.add(aggregateVariable);
            }
        }
        globalVariablesPerAggregate.put(aggregateLiteral, globalVariablesInAggregate);
    }
}
Also used : NormalHead(at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead) AggregateLiteral(at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral) Literal(at.ac.tuwien.kr.alpha.api.programs.literals.Literal) AggregateLiteral(at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral) VariableTerm(at.ac.tuwien.kr.alpha.api.terms.VariableTerm) AggregateAtom(at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom) HashSet(java.util.HashSet)

Example 2 with NormalHead

use of at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead in project Alpha by alpha-asp.

the class IntervalTermToIntervalAtom method rewriteIntervalSpecifications.

/**
 * Rewrites intervals into a new variable and special IntervalAtom.
 *
 * @return true if some interval occurs in the rule.
 */
private static NormalRule rewriteIntervalSpecifications(NormalRule rule) {
    // Collect all intervals and replace them with variables.
    Map<VariableTerm, IntervalTerm> intervalReplacements = new LinkedHashMap<>();
    List<Literal> rewrittenBody = new ArrayList<>();
    for (Literal literal : rule.getBody()) {
        Literal rewrittenLiteral = rewriteLiteral(literal, intervalReplacements);
        if (rewrittenLiteral != null) {
            rewrittenBody.add(rewrittenLiteral);
        }
    }
    // Note that this cast is safe: NormalHead can only have a BasicAtom, so literalizing and getting back the Atom destroys type information,
    // but should never yield anything other than a BasicAtom
    NormalHead rewrittenHead = rule.isConstraint() ? null : Heads.newNormalHead((BasicAtom) rewriteLiteral(rule.getHead().getAtom().toLiteral(), intervalReplacements).getAtom());
    // If intervalReplacements is empty, no IntervalTerms have been found, keep rule as is.
    if (intervalReplacements.isEmpty()) {
        return rule;
    }
    // Add new IntervalAtoms representing the interval specifications.
    for (Map.Entry<VariableTerm, IntervalTerm> interval : intervalReplacements.entrySet()) {
        rewrittenBody.add(new IntervalAtom(interval.getValue(), interval.getKey()).toLiteral());
    }
    return new NormalRuleImpl(rewrittenHead, rewrittenBody);
}
Also used : IntervalAtom(at.ac.tuwien.kr.alpha.core.atoms.IntervalAtom) IntervalTerm(at.ac.tuwien.kr.alpha.commons.terms.IntervalTerm) ArrayList(java.util.ArrayList) NormalRuleImpl(at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl) 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) BasicAtom(at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 3 with NormalHead

use of at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead in project Alpha by alpha-asp.

the class PredicateInternalizer method makePrefixedPredicatesInternal.

public static Rule<Head> makePrefixedPredicatesInternal(Rule<Head> rule, String prefix) {
    Head newHead = null;
    if (rule.getHead() != null) {
        if (!(rule.getHead() instanceof NormalHead)) {
            throw new UnsupportedOperationException("Cannot make predicates in rules internal whose head is not normal.");
        }
        NormalHead head = (NormalHead) rule.getHead();
        if (head.getAtom().getPredicate().getName().startsWith(prefix)) {
            newHead = Heads.newNormalHead(makePredicateInternal(head.getAtom()));
        } else {
            newHead = head;
        }
    }
    List<Literal> newBody = new ArrayList<>();
    for (Literal bodyElement : rule.getBody()) {
        // Only rewrite BasicAtoms.
        if (bodyElement instanceof BasicLiteral) {
            if (bodyElement.getAtom().getPredicate().getName().startsWith(prefix)) {
                newBody.add(makePredicateInternal((BasicAtom) bodyElement.getAtom()).toLiteral(!bodyElement.isNegated()));
            } else {
                newBody.add(bodyElement);
            }
        } else {
            // Keep other body element as is.
            newBody.add(bodyElement);
        }
    }
    return new BasicRule(newHead, newBody);
}
Also used : BasicRule(at.ac.tuwien.kr.alpha.core.rules.BasicRule) BasicLiteral(at.ac.tuwien.kr.alpha.api.programs.literals.BasicLiteral) Head(at.ac.tuwien.kr.alpha.api.rules.heads.Head) NormalHead(at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead) 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) ArrayList(java.util.ArrayList)

Example 4 with NormalHead

use of at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead 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 5 with NormalHead

use of at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead 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)

Aggregations

Literal (at.ac.tuwien.kr.alpha.api.programs.literals.Literal)7 NormalHead (at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead)7 ArrayList (java.util.ArrayList)6 VariableTerm (at.ac.tuwien.kr.alpha.api.terms.VariableTerm)5 BasicRule (at.ac.tuwien.kr.alpha.core.rules.BasicRule)4 ComparisonLiteral (at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral)3 AggregateAtom (at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom)2 BasicAtom (at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom)2 BasicLiteral (at.ac.tuwien.kr.alpha.api.programs.literals.BasicLiteral)2 Head (at.ac.tuwien.kr.alpha.api.rules.heads.Head)2 Term (at.ac.tuwien.kr.alpha.api.terms.Term)2 NormalRuleImpl (at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl)2 HashSet (java.util.HashSet)2 LinkedHashMap (java.util.LinkedHashMap)2 Map (java.util.Map)2 ComparisonOperator (at.ac.tuwien.kr.alpha.api.ComparisonOperator)1 Atom (at.ac.tuwien.kr.alpha.api.programs.atoms.Atom)1 AggregateLiteral (at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral)1 Rule (at.ac.tuwien.kr.alpha.api.rules.Rule)1 DisjunctiveHead (at.ac.tuwien.kr.alpha.api.rules.heads.DisjunctiveHead)1