use of at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral in project Alpha by alpha-asp.
the class ParserTest method cardinalityAggregate.
@Test
public void cardinalityAggregate() {
ASPCore2Program parsedProgram = parser.parse("num(K) :- K <= #count {X,Y,Z : p(X,Y,Z) }, dom(K).");
Optional<Literal> optionalBodyElement = parsedProgram.getRules().get(0).getBody().stream().filter((lit) -> lit instanceof AggregateLiteral).findFirst();
assertTrue(optionalBodyElement.isPresent());
Literal bodyElement = optionalBodyElement.get();
AggregateLiteral parsedAggregate = (AggregateLiteral) bodyElement;
VariableTerm x = Terms.newVariable("X");
VariableTerm y = Terms.newVariable("Y");
VariableTerm z = Terms.newVariable("Z");
List<Term> basicTerms = Arrays.asList(x, y, z);
AggregateAtom.AggregateElement aggregateElement = Atoms.newAggregateElement(basicTerms, Collections.singletonList(Atoms.newBasicAtom(Predicates.getPredicate("p", 3), x, y, z).toLiteral()));
AggregateAtom expectedAggregate = Atoms.newAggregateAtom(ComparisonOperators.LE, Terms.newVariable("K"), null, null, AggregateAtom.AggregateFunctionSymbol.COUNT, Collections.singletonList(aggregateElement));
assertEquals(expectedAggregate, parsedAggregate.getAtom());
}
use of at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral in project Alpha by alpha-asp.
the class AggregateOperatorNormalization method rewriteAggregateOperator.
private static List<Literal> rewriteAggregateOperator(AggregateLiteral lit) {
AggregateAtom atom = lit.getAtom();
if (atom.getLowerBoundOperator() == null && atom.getUpperBoundOperator() != null) {
return rewriteAggregateOperator(convertToLeftHandComparison(lit));
}
if (lit.getAtom().getAggregateFunction() == AggregateFunctionSymbol.MIN || lit.getAtom().getAggregateFunction() == AggregateFunctionSymbol.MAX) {
// No operator normalization needed for #min/#max aggregates.
return Collections.singletonList(lit);
}
if (atom.getLowerBoundOperator().equals(ComparisonOperators.EQ) || atom.getLowerBoundOperator().equals(ComparisonOperators.LE)) {
// Nothing to do for operator "=" or "<=".
return Collections.singletonList(lit);
} else {
List<Literal> retVal = new ArrayList<>();
VariableTerm decrementedBound;
ComparisonOperator lowerBoundOp = atom.getLowerBoundOperator();
if (lowerBoundOp.equals(ComparisonOperators.LT)) {
decrementedBound = Terms.newAnonymousVariable();
retVal.add(createLowerBoundedAggregateLiteral(ComparisonOperators.LE, decrementedBound, atom, !lit.isNegated()));
retVal.add(createPlusOneTerm(atom.getLowerBoundTerm(), decrementedBound));
} else if (lowerBoundOp.equals(ComparisonOperators.NE)) {
retVal.add(createLowerBoundedAggregateLiteral(ComparisonOperators.EQ, atom.getLowerBoundTerm(), atom, lit.isNegated()));
} else if (lowerBoundOp.equals(ComparisonOperators.GT)) {
retVal.add(createLowerBoundedAggregateLiteral(ComparisonOperators.LE, atom.getLowerBoundTerm(), atom, lit.isNegated()));
} else if (lowerBoundOp.equals(ComparisonOperators.GE)) {
decrementedBound = Terms.newAnonymousVariable();
retVal.add(createLowerBoundedAggregateLiteral(ComparisonOperators.LE, decrementedBound, atom, lit.isNegated()));
retVal.add(createPlusOneTerm(atom.getLowerBoundTerm(), decrementedBound));
} else {
throw new IllegalStateException("No operator rewriting logic available for literal: " + lit);
}
return retVal;
}
}
use of at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral in project Alpha by alpha-asp.
the class AggregateLiteralSplitting method splitAggregatesInRule.
private static List<Rule<Head>> splitAggregatesInRule(Rule<Head> sourceRule) {
// Rule contains some aggregates that need splitting.
// Aggregates may require splitting in two literals, or in two rules.
List<Literal> commonBodyLiterals = new ArrayList<>();
List<Literal> twoLiteralsSplitAggregates = new ArrayList<>();
List<ImmutablePair<Literal, Literal>> twoRulesSplitAggregates = new ArrayList<>();
// First, sort literals of the rule and also compute splitting.
for (Literal literal : sourceRule.getBody()) {
if (literal instanceof AggregateLiteral && shouldRewrite((AggregateLiteral) literal)) {
splitCombinedAggregateLiteral(literal, twoLiteralsSplitAggregates, twoRulesSplitAggregates);
} else {
// Literal is no aggregate that needs splitting.
commonBodyLiterals.add(literal);
}
}
// Second, compute rule bodies of splitting result.
List<Literal> commonBody = new ArrayList<>(commonBodyLiterals);
commonBody.addAll(twoLiteralsSplitAggregates);
List<List<Literal>> rewrittenBodies = new ArrayList<>();
// Initialize list of rules with the common body.
rewrittenBodies.add(commonBody);
// for each of the n pairs in twoRulesSplitAggregates we duplicate the list of rewritten bodies.
for (ImmutablePair<Literal, Literal> ruleSplitAggregate : twoRulesSplitAggregates) {
int numBodiesBeforeDuplication = rewrittenBodies.size();
for (int i = 0; i < numBodiesBeforeDuplication; i++) {
List<Literal> originalBody = rewrittenBodies.get(i);
List<Literal> duplicatedBody = new ArrayList<>(originalBody);
// Extend bodies of original and duplicate with splitting results.
originalBody.add(ruleSplitAggregate.left);
duplicatedBody.add(ruleSplitAggregate.right);
rewrittenBodies.add(duplicatedBody);
}
}
// Third, turn computed bodies into rules again.
List<Rule<Head>> rewrittenRules = new ArrayList<>();
for (List<Literal> rewrittenBody : rewrittenBodies) {
rewrittenRules.add(new BasicRule(sourceRule.getHead(), rewrittenBody));
}
return rewrittenRules;
}
use of at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral in project Alpha by alpha-asp.
the class AggregateRewriting method rewriteRulesWithAggregates.
/**
* Transforms (restricted) aggregate literals of format "VAR OP #AGG_FN{...}" into literals of format
* "<result_predicate>(ARGS, VAR)" where ARGS is a function term wrapping the aggregate's global variables.
*
* @param ctx the {@link AggregateRewritingContext} containing information about all aggregates.
* @return for each rule, its rewritten version where aggregates are replaced with output atoms of the encoding.
*/
private static List<Rule<Head>> rewriteRulesWithAggregates(AggregateRewritingContext ctx) {
List<Rule<Head>> rewrittenRules = new ArrayList<>();
for (Rule<Head> rule : ctx.getRulesWithAggregates()) {
List<Literal> rewrittenBody = new ArrayList<>();
for (Literal lit : rule.getBody()) {
if (lit instanceof AggregateLiteral) {
AggregateInfo aggregateInfo = ctx.getAggregateInfo((AggregateLiteral) lit);
rewrittenBody.add(Literals.fromAtom(aggregateInfo.getOutputAtom(), !lit.isNegated()));
} else {
rewrittenBody.add(lit);
}
}
rewrittenRules.add(new BasicRule(rule.getHead(), rewrittenBody));
}
return rewrittenRules;
}
use of at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral 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);
}
}
Aggregations