use of at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral in project Alpha by alpha-asp.
the class IntervalTermToIntervalAtom method rewriteLiteral.
/**
* Replaces every IntervalTerm by a new variable and returns a mapping of the replaced VariableTerm -> IntervalTerm.
*
* @return the rewritten literal or null if the literal should be dropped from the final rule.
*/
private static Literal rewriteLiteral(Literal lit, Map<VariableTerm, IntervalTerm> intervalReplacement) {
// final rule.
if (lit instanceof ComparisonLiteral && ((ComparisonLiteral) lit).isNormalizedEquality()) {
ComparisonAtom equalityLiteral = (ComparisonAtom) lit.getAtom();
if (equalityLiteral.getTerms().get(0) instanceof VariableTerm && equalityLiteral.getTerms().get(1) instanceof IntervalTerm) {
// Literal is of the form "X = A .. B".
intervalReplacement.put((VariableTerm) equalityLiteral.getTerms().get(0), (IntervalTerm) equalityLiteral.getTerms().get(1));
return null;
}
if (equalityLiteral.getTerms().get(1) instanceof VariableTerm && equalityLiteral.getTerms().get(0) instanceof IntervalTerm) {
// Literal is of the form "A .. B = X".
intervalReplacement.put((VariableTerm) equalityLiteral.getTerms().get(1), (IntervalTerm) equalityLiteral.getTerms().get(0));
return null;
}
}
Atom atom = lit.getAtom();
List<Term> termList = new ArrayList<>(atom.getTerms());
boolean didChange = false;
for (int i = 0; i < termList.size(); i++) {
Term term = termList.get(i);
if (term instanceof IntervalTerm) {
VariableTerm replacementVariable = Terms.newVariable(INTERVAL_VARIABLE_PREFIX + intervalReplacement.size());
intervalReplacement.put(replacementVariable, (IntervalTerm) term);
termList.set(i, replacementVariable);
didChange = true;
}
if (term instanceof FunctionTerm) {
// Rewrite function terms recursively.
FunctionTerm rewrittenFunctionTerm = rewriteFunctionTerm((FunctionTerm) term, intervalReplacement);
termList.set(i, rewrittenFunctionTerm);
didChange = true;
}
}
if (didChange) {
Atom rewrittenAtom = atom.withTerms(termList);
return lit.isNegated() ? rewrittenAtom.toLiteral().negate() : rewrittenAtom.toLiteral();
}
return lit;
}
use of at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral in project Alpha by alpha-asp.
the class AggregateOperatorNormalizationTest method assertAggregateBoundIncremented.
private static void assertAggregateBoundIncremented(Rule<Head> sourceRule, Rule<Head> rewrittenRule) {
AggregateLiteral sourceAggregate = null;
for (Literal lit : sourceRule.getBody()) {
if (lit instanceof AggregateLiteral) {
sourceAggregate = (AggregateLiteral) lit;
}
}
AggregateLiteral rewrittenAggregate = null;
ComparisonLiteral addedComparisonLiteral = null;
for (Literal lit : rewrittenRule.getBody()) {
if (lit instanceof AggregateLiteral) {
rewrittenAggregate = (AggregateLiteral) lit;
} else if (lit instanceof ComparisonLiteral) {
addedComparisonLiteral = (ComparisonLiteral) lit;
}
}
assertNotNull(addedComparisonLiteral);
assertEquals(addedComparisonLiteral.getAtom().getTerms().get(0), rewrittenAggregate.getAtom().getLowerBoundTerm());
Term comparisonRightHandTerm = addedComparisonLiteral.getAtom().getTerms().get(1);
assertTrue(comparisonRightHandTerm instanceof ArithmeticTerm);
ArithmeticTerm incrementTerm = (ArithmeticTerm) comparisonRightHandTerm;
assertEquals(ArithmeticOperator.PLUS, incrementTerm.getOperator());
assertEquals(Terms.newConstant(1), incrementTerm.getRightOperand());
Term sourceBound = sourceAggregate.getAtom().getLowerBoundTerm() != null ? sourceAggregate.getAtom().getLowerBoundTerm() : sourceAggregate.getAtom().getUpperBoundTerm();
assertEquals(sourceBound, incrementTerm.getLeftOperand());
}
use of at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral in project Alpha by alpha-asp.
the class AnalyzeUnjustified method unjustCover.
private Set<LitSet> unjustCover(List<Literal> vB, Set<Unifier> vY, Set<Unifier> vN, Assignment currentAssignment) {
padDepth += 2;
log("Begin UnjustCoverFixed()");
log("Finding unjustified body literals in: {} / {} excluded {}", vB, vY, vN);
Set<LitSet> ret = new LinkedHashSet<>();
if (vB.isEmpty() || vY.isEmpty()) {
log("End unjustCover().");
padDepth -= 2;
return Collections.emptySet();
}
int chosenLiteralPos = 0;
// Find a body literal that is not a ComparisonLiteral, because these do not generate/have atoms assigned.
for (int i = 0; i < vB.size(); i++) {
if (!(vB.get(i) instanceof ComparisonLiteral)) {
// TODO: Should this be FixedInterpretationLiteral instead??
chosenLiteralPos = i;
break;
}
}
Atom b = vB.get(chosenLiteralPos).getAtom();
log("Picked literal from body is: {}", b);
for (Unifier sigmaY : vY) {
Atom bSigmaY = b.substitute(sigmaY);
log("Treating substitution for: {}", bSigmaY);
Set<Unifier> vYp = new LinkedHashSet<>();
log("Checking atoms over predicate: {}", b.getPredicate());
AssignedAtomsIterator assignedAtomsOverPredicate = getAssignedAtomsOverPredicate(b.getPredicate());
atomLoop: while (assignedAtomsOverPredicate.hasNext()) {
Atom atom = assignedAtomsOverPredicate.next();
// Check that atom is justified/true.
log("Checking atom: {}", atom);
if (atomStore.contains(atom)) {
int atomId = atomStore.get(atom);
if (currentAssignment.getTruth(atomId) != ThriceTruth.TRUE) {
log("Atom is not TRUE. Skipping.");
continue;
}
}
// Note: in case the atom is not in the atomStore, it came from a fact and hence is true.
Unifier sigma = Unification.instantiate(b, atom);
if (sigma == null) {
log("Atom does not unify with picked body literal.");
continue;
}
Atom bSigma = b.substitute(sigma);
if (!bSigma.isGround()) {
throw oops("Resulting atom is not ground.");
}
Set<VariableTerm> variablesOccurringInSigma = sigma.getMappedVariables();
if (Unification.instantiate(bSigmaY, bSigma) != null) {
for (Unifier sigmaN : vN) {
ArrayList<Term> occurringVariables = new ArrayList<>(variablesOccurringInSigma);
occurringVariables.addAll(sigmaN.getMappedVariables());
BasicAtom genericAtom = Atoms.newBasicAtom(Predicates.getPredicate("_", occurringVariables.size(), true), occurringVariables);
Atom genericSubstituted = genericAtom.substitute(sigmaN).renameVariables("_analyzeTest");
if (Unification.instantiate(genericSubstituted, genericAtom.substitute(sigma)) != null) {
log("Atom {} is excluded by: {} via {}", genericSubstituted, sigmaN, sigma);
continue atomLoop;
}
}
log("Adding corresponding substitution to Y': {}", sigma);
vYp.add(sigma);
}
}
log("Unjustified body literals: {}", vYp);
Set<Unifier> vYpUN = new LinkedHashSet<>();
vYpUN.addAll(vYp);
vYpUN.addAll(vN);
LitSet toJustify = new LitSet(bSigmaY, vYpUN);
if (!toJustify.coversNothing()) {
log("New litset to do: {}", toJustify);
ret.add(toJustify);
} else {
log("Generated LitSet covers nothing. Ignoring: {}", toJustify);
}
ArrayList<Literal> newB = new ArrayList<>(vB);
newB.remove(chosenLiteralPos);
ret.addAll(unjustCover(newB, vYp, vN, currentAssignment));
log("Literal set(s) to treat: {}", ret);
}
log("End unjustCover().");
padDepth -= 2;
return ret;
}
use of at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral 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.programs.literals.ComparisonLiteral in project Alpha by alpha-asp.
the class VariableEqualityRemoval method findAndReplaceVariableEquality.
private Rule<Head> findAndReplaceVariableEquality(Rule<Head> rule) {
// Collect all equal variables.
HashMap<VariableTerm, HashSet<VariableTerm>> variableToEqualVariables = new LinkedHashMap<>();
HashSet<Literal> equalitiesToRemove = new HashSet<>();
for (Literal bodyElement : rule.getBody()) {
if (!(bodyElement instanceof ComparisonLiteral)) {
continue;
}
ComparisonLiteral comparisonLiteral = (ComparisonLiteral) bodyElement;
if (!comparisonLiteral.isNormalizedEquality()) {
continue;
}
if (comparisonLiteral.getTerms().get(0) instanceof VariableTerm && comparisonLiteral.getTerms().get(1) instanceof VariableTerm) {
VariableTerm leftVariable = (VariableTerm) comparisonLiteral.getTerms().get(0);
VariableTerm rightVariable = (VariableTerm) comparisonLiteral.getTerms().get(1);
HashSet<VariableTerm> leftEqualVariables = variableToEqualVariables.get(leftVariable);
HashSet<VariableTerm> rightEqualVariables = variableToEqualVariables.get(rightVariable);
if (leftEqualVariables == null && rightEqualVariables == null) {
HashSet<VariableTerm> equalVariables = new LinkedHashSet<>(Arrays.asList(leftVariable, rightVariable));
variableToEqualVariables.put(leftVariable, equalVariables);
variableToEqualVariables.put(rightVariable, equalVariables);
}
if (leftEqualVariables == null && rightEqualVariables != null) {
rightEqualVariables.add(leftVariable);
variableToEqualVariables.put(leftVariable, rightEqualVariables);
}
if (leftEqualVariables != null && rightEqualVariables == null) {
leftEqualVariables.add(rightVariable);
variableToEqualVariables.put(rightVariable, leftEqualVariables);
}
if (leftEqualVariables != null && rightEqualVariables != null) {
leftEqualVariables.addAll(rightEqualVariables);
for (VariableTerm rightEqualVariable : rightEqualVariables) {
variableToEqualVariables.put(rightEqualVariable, leftEqualVariables);
}
}
equalitiesToRemove.add(comparisonLiteral);
}
}
if (variableToEqualVariables.isEmpty()) {
// Skip rule if there is no equality between variables.
return rule;
}
List<Literal> rewrittenBody = new ArrayList<>(rule.getBody());
if (!rule.isConstraint() && rule.getHead() instanceof DisjunctiveHead) {
throw new UnsupportedOperationException("VariableEqualityRemoval cannot be applied to rule with DisjunctiveHead, yet.");
}
NormalHead rewrittenHead = rule.isConstraint() ? null : Heads.newNormalHead(((NormalHead) rule.getHead()).getAtom());
// Use substitution for actual replacement.
Unifier replacementSubstitution = new Unifier();
// For each set of equal variables, take the first variable and replace all others by it.
for (Map.Entry<VariableTerm, HashSet<VariableTerm>> variableEqualityEntry : variableToEqualVariables.entrySet()) {
VariableTerm variableToReplace = variableEqualityEntry.getKey();
VariableTerm replacementVariable = variableEqualityEntry.getValue().iterator().next();
if (variableToReplace == replacementVariable) {
continue;
}
replacementSubstitution.put(variableToReplace, replacementVariable);
}
// Replace/Substitute in each literal every term where one of the common variables occurs.
Iterator<Literal> bodyIterator = rewrittenBody.iterator();
while (bodyIterator.hasNext()) {
Literal literal = bodyIterator.next();
if (equalitiesToRemove.contains(literal)) {
bodyIterator.remove();
}
for (int i = 0; i < literal.getTerms().size(); i++) {
Term replaced = literal.getTerms().get(i).substitute(replacementSubstitution);
literal.getTerms().set(i, replaced);
}
}
// Replace variables in head.
if (rewrittenHead != null) {
Atom headAtom = rewrittenHead.getAtom();
for (int i = 0; i < headAtom.getTerms().size(); i++) {
Term replaced = headAtom.getTerms().get(i).substitute(replacementSubstitution);
headAtom.getTerms().set(i, replaced);
}
}
return new BasicRule(rewrittenHead, rewrittenBody);
}
Aggregations