use of at.ac.tuwien.kr.alpha.core.rules.BasicRule 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.core.rules.BasicRule 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.core.rules.BasicRule in project Alpha by alpha-asp.
the class AlphaImplTest method withExternalSubtype.
@Test
public void withExternalSubtype() throws Exception {
SubThingy thingy = new SubThingy();
BasicRule rule = new BasicRule(Heads.newNormalHead(Atoms.newBasicAtom(Predicates.getPredicate("p", 1), Terms.newConstant("x"))), singletonList(Literals.fromAtom(Atoms.newExternalAtom(Predicates.getPredicate("thinger", 1), new MethodPredicateInterpretation(this.getClass().getMethod("thinger", Thingy.class)), singletonList(Terms.newConstant(thingy)), emptyList()), true)));
Alpha system = new AlphaImpl();
InputProgram prog = new InputProgram(singletonList(rule), emptyList(), new InlineDirectivesImpl());
Set<AnswerSet> actual = system.solve(prog).collect(Collectors.toSet());
Set<AnswerSet> expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("p").instance("x").build()));
assertEquals(expected, actual);
}
use of at.ac.tuwien.kr.alpha.core.rules.BasicRule 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();
}
use of at.ac.tuwien.kr.alpha.core.rules.BasicRule 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);
}
Aggregations