use of at.ac.tuwien.kr.alpha.api.rules.Rule 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.rules.Rule 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.rules.Rule in project Alpha by alpha-asp.
the class LiteralBindingNonBindingVariablesTest method testPositiveExternalLiteral.
@Test
public void testPositiveExternalLiteral() {
externals.put("ext", new IntPredicateInterpretation(i -> i > 0));
Rule<Head> rule = parser.parse("p(X) :- q(Y), &ext[Y](X).", externals).getRules().get(0);
Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate().getName().equals("ext")).findFirst().get();
assertEquals(false, literal.isNegated());
expectVariables(literal.getBindingVariables(), "X");
expectVariables(literal.getNonBindingVariables(), "Y");
}
use of at.ac.tuwien.kr.alpha.api.rules.Rule in project Alpha by alpha-asp.
the class RuleToStringTest method parseSingleRule.
private Rule<Head> parseSingleRule(String rule) {
ASPCore2Program program = parser.parse(rule);
List<Rule<Head>> rules = program.getRules();
assertEquals(1, rules.size(), "Number of rules");
return rules.get(0);
}
use of at.ac.tuwien.kr.alpha.api.rules.Rule 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();
}
Aggregations