use of at.ac.tuwien.kr.alpha.api.terms.VariableTerm 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);
}
use of at.ac.tuwien.kr.alpha.api.terms.VariableTerm in project Alpha by alpha-asp.
the class AggregateRewritingRuleAnalysis method findBindingLiterals.
/**
* Recursively looks for literals in <code>searchScope</code> that bind the variables in the set
* <code>varsToBind</code>, i.e. any literal lit that has any variable var in question in its
* <code>bindingVariables</code> (i.e. lit assigns a value to var). Found binding literals are added to the set
* <code>boundSoFar</code>. If a literal has any of the desired variables as a binding variable, but also has other
* non-binding variables, the literals binding these are added to the set of desired variables for the next recursive
* call. Since {@link AggregateLiteral}s cannot report their non-binding variables by themselves, this method also needs
* a map of all aggregate literals and their global variables within the search scope.
*/
// Note: This algorithm has potentially exponential time complexity. Tuning potential definitely exists, but
// performance optimization seems non-trivial.
private static void findBindingLiterals(Set<VariableTerm> varsToBind, Set<VariableTerm> varsBoundSoFar, Set<Literal> foundSoFar, Set<Literal> searchScope, Map<AggregateLiteral, Set<VariableTerm>> aggregatesWithGlobalVars) {
int newlyBoundVars = 0;
Set<VariableTerm> furtherVarsToBind = new HashSet<>();
for (VariableTerm varToBind : varsToBind) {
for (Literal lit : searchScope) {
Set<VariableTerm> bindingVars = lit.getBindingVariables();
Set<VariableTerm> nonBindingVars = (lit instanceof AggregateLiteral) ? aggregatesWithGlobalVars.get((AggregateLiteral) lit) : lit.getNonBindingVariables();
if (bindingVars.contains(varToBind)) {
varsBoundSoFar.add(varToBind);
foundSoFar.add(lit);
newlyBoundVars++;
for (VariableTerm nonBindingVar : nonBindingVars) {
if (!varsBoundSoFar.contains(nonBindingVar)) {
furtherVarsToBind.add(nonBindingVar);
}
}
}
}
}
if (newlyBoundVars == 0 && !varsToBind.isEmpty()) {
// screaming than producing a stack overflow ;-)
throw new IllegalStateException("Couldn't find any literals binding variables: " + varsToBind + " in search scope " + searchScope);
}
if (!furtherVarsToBind.isEmpty()) {
// As long as we find variables we still need to bind, repeat with the new set of variables to bind.
findBindingLiterals(furtherVarsToBind, varsBoundSoFar, foundSoFar, searchScope, aggregatesWithGlobalVars);
}
}
use of at.ac.tuwien.kr.alpha.api.terms.VariableTerm in project Alpha by alpha-asp.
the class Unification method unifyAtoms.
private static Unifier unifyAtoms(Atom left, Atom right, boolean keepLeftAsIs) {
Set<VariableTerm> leftOccurringVariables = left.getOccurringVariables();
Set<VariableTerm> rightOccurringVaribles = right.getOccurringVariables();
boolean leftSmaller = leftOccurringVariables.size() < rightOccurringVaribles.size();
Set<VariableTerm> smallerSet = leftSmaller ? leftOccurringVariables : rightOccurringVaribles;
Set<VariableTerm> largerSet = leftSmaller ? rightOccurringVaribles : leftOccurringVariables;
for (VariableTerm variableTerm : smallerSet) {
if (largerSet.contains(variableTerm)) {
throw oops("Left and right atom share variables.");
}
}
Unifier mgu = new Unifier();
if (!left.getPredicate().equals(right.getPredicate())) {
return null;
}
for (int i = 0; i < left.getPredicate().getArity(); i++) {
final Term leftTerm = left.getTerms().get(i);
final Term rightTerm = right.getTerms().get(i);
if (!unifyTerms(leftTerm, rightTerm, mgu, keepLeftAsIs)) {
return null;
}
}
return mgu;
}
use of at.ac.tuwien.kr.alpha.api.terms.VariableTerm in project Alpha by alpha-asp.
the class UnifierTest method extendUnifier.
@Test
public void extendUnifier() {
VariableTerm varX = Terms.newVariable("X");
VariableTerm varY = Terms.newVariable("Y");
Unifier sub1 = new Unifier();
sub1.put(varX, varY);
Unifier sub2 = new Unifier();
sub2.put(varY, Terms.newConstant("a"));
sub1.extendWith(sub2);
BasicAtom atom1 = parseAtom("p(X)");
Atom atomSubstituted = atom1.substitute(sub1);
assertEquals(Terms.newConstant("a"), atomSubstituted.getTerms().get(0));
}
use of at.ac.tuwien.kr.alpha.api.terms.VariableTerm in project Alpha by alpha-asp.
the class Substitutions method fromString.
public static Substitution fromString(String str) {
String bare = str.substring(1, str.length() - 1);
String[] assignments = bare.split(",");
BasicSubstitution ret = new BasicSubstitution();
for (String assignment : assignments) {
String[] keyVal = assignment.split("->");
VariableTerm variable = Terms.newVariable(keyVal[0]);
Term assignedTerm = PROGRAM_PART_PARSER.parseTerm(keyVal[1]);
ret.put(variable, assignedTerm);
}
return ret;
}
Aggregations