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);
}
}
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);
}
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);
}
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();
}
}
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);
}
Aggregations