use of at.ac.tuwien.kr.alpha.api.ComparisonOperator in project Alpha by alpha-asp.
the class ParseTreeVisitor method visitChoice.
@Override
public Head visitChoice(ASPCore2Parser.ChoiceContext ctx) {
// choice : (lt=term lop=binop)? CURLY_OPEN choice_elements? CURLY_CLOSE (uop=binop ut=term)?;
Term lt = null;
ComparisonOperator lop = null;
Term ut = null;
ComparisonOperator uop = null;
if (ctx.lt != null) {
lt = (Term) visit(ctx.lt);
lop = visitBinop(ctx.lop);
}
if (ctx.ut != null) {
ut = (Term) visit(ctx.ut);
uop = visitBinop(ctx.uop);
}
return Heads.newChoiceHead(visitChoice_elements(ctx.choice_elements()), lt, lop, ut, uop);
}
use of at.ac.tuwien.kr.alpha.api.ComparisonOperator in project Alpha by alpha-asp.
the class AggregateRewritingContextTest method minEqAggregateNoGlobalVars.
@Test
public void minEqAggregateNoGlobalVars() {
AggregateRewritingContext ctx = rewritingContextForAspString(CTX_TEST_MIN_EQ_ASP);
Map<ImmutablePair<AggregateFunctionSymbol, ComparisonOperator>, Set<AggregateInfo>> functionsToRewrite = ctx.getAggregateFunctionsToRewrite();
assertEquals(1, functionsToRewrite.size());
ImmutablePair<AggregateFunctionSymbol, ComparisonOperator> minEq = new ImmutablePair<>(AggregateFunctionSymbol.MIN, ComparisonOperators.EQ);
assertTrue(functionsToRewrite.containsKey(minEq));
Set<AggregateInfo> minEqAggregateInfos = functionsToRewrite.get(minEq);
assertEquals(1, minEqAggregateInfos.size());
AggregateInfo info = minEqAggregateInfos.iterator().next();
assertTrue(info.getGlobalVariables().isEmpty());
}
use of at.ac.tuwien.kr.alpha.api.ComparisonOperator in project Alpha by alpha-asp.
the class AggregateRewriting method apply.
/**
* Rewrites all {@link AggregateLiteral}s in the given program.
* The transformation workflow is split into a preprocessing- and an encoding phase.
* During preprocessing, all aggregate literals with two comparison operators are split into two aggregate literals with
* only a "lower bound" term and operator. After literal splitting, operators are normalized, i.e. all "count" and "sum"
* literals are rewritten to use either "<=" or "=" as comparison operator.
*
* Rules containing {@link AggregateLiteral}s are registered in an {@link AggregateRewritingContext} during
* preprocessing. After preprocessing, for each rule in the context, aggregate literals in the rule body are substituted
* with normal literals of form "$id$_aggregate_result(...)". For each literal substituted this way, a set of rules
* deriving the result literal is added that is semantically equivalent to the replaced aggregate literal.
*/
@Override
public ASPCore2Program apply(ASPCore2Program inputProgram) {
AggregateRewritingContext ctx = new AggregateRewritingContext();
List<Rule<Head>> outputRules = new ArrayList<>();
for (Rule<Head> inputRule : inputProgram.getRules()) {
// Split literals with two operators.
for (Rule<Head> splitRule : AggregateLiteralSplitting.split(inputRule)) {
// Normalize operators on aggregate literals after splitting.
Rule<Head> operatorNormalizedRule = AggregateOperatorNormalization.normalize(splitRule);
boolean hasAggregate = ctx.registerRule(operatorNormalizedRule);
// Only keep rules without aggregates. The ones with aggregates are registered in the context and taken care of later.
if (!hasAggregate) {
outputRules.add(operatorNormalizedRule);
}
}
}
// Substitute AggregateLiterals with generated result literals.
outputRules.addAll(rewriteRulesWithAggregates(ctx));
InputProgram.Builder resultBuilder = InputProgram.builder().addRules(outputRules).addFacts(inputProgram.getFacts()).addInlineDirectives(inputProgram.getInlineDirectives());
// Add sub-programs deriving respective aggregate literals.
for (Map.Entry<ImmutablePair<AggregateFunctionSymbol, ComparisonOperator>, Set<AggregateInfo>> aggToRewrite : ctx.getAggregateFunctionsToRewrite().entrySet()) {
ImmutablePair<AggregateFunctionSymbol, ComparisonOperator> func = aggToRewrite.getKey();
AbstractAggregateEncoder encoder = getEncoderForAggregateFunction(func.left, func.right);
resultBuilder.accumulate(encoder.encodeAggregateLiterals(aggToRewrite.getValue()));
}
return resultBuilder.build();
}
use of at.ac.tuwien.kr.alpha.api.ComparisonOperator 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();
}
}
Aggregations