use of kodkod.ast.operator.FormulaOperator in project org.alloytools.alloy by AlloyTools.
the class FOL2BoolTranslator method visit.
/**
* Calls lookup(formula) and returns the cached value, if any. If a translation
* has not been cached, translates the formula, calls cache(...) on it and
* returns it.
*
* @return let t = lookup(formula) | some t => t, cache(formula,
* formula.op(formula.left.accept(this), formula.right.accept(this))
*/
@Override
public final BooleanValue visit(NaryFormula formula) {
final BooleanValue ret = lookup(formula);
if (ret != null)
return ret;
final FormulaOperator op = formula.op();
final Operator.Nary boolOp;
switch(op) {
case AND:
boolOp = Operator.AND;
break;
case OR:
boolOp = Operator.OR;
break;
default:
throw new IllegalArgumentException("Unknown nary operator: " + op);
}
final BooleanAccumulator acc = BooleanAccumulator.treeGate(boolOp);
final BooleanValue shortCircuit = boolOp.shortCircuit();
for (Formula child : formula) {
if (acc.add(child.accept(this)) == shortCircuit)
break;
}
return cache(formula, interpreter.factory().accumulate(acc));
}
use of kodkod.ast.operator.FormulaOperator in project org.alloytools.alloy by AlloyTools.
the class FullNegationPropagator method visit.
/**
* Visits the formula's children with appropriate settings for the negated flag
* if bf has not been visited before.
*
* @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.BinaryFormula)
*/
@Override
public final void visit(BinaryFormula bf) {
if (visited(bf))
return;
final FormulaOperator op = bf.op();
switch(op) {
case AND:
if (!negated) {
// left && right
bf.left().accept(this);
bf.right().accept(this);
} else {
// !(left && right) --> !left || !right
FullNegationPropagator fne1 = new FullNegationPropagator(shared, annotations);
bf.left().not().accept(fne1);
FullNegationPropagator fne2 = new FullNegationPropagator(shared, annotations);
bf.right().not().accept(fne2);
addConjunct(Formula.and(fne1.conjuncts).or(Formula.and(fne2.conjuncts)), false, bf);
hasChanged = true;
}
break;
case OR:
if (!negated) {
// left || right
FullNegationPropagator fne1 = new FullNegationPropagator(shared, annotations);
bf.left().accept(fne1);
FullNegationPropagator fne2 = new FullNegationPropagator(shared, annotations);
bf.right().accept(fne2);
if (!fne1.hasChanged && !fne2.hasChanged) {
addConjunct(bf);
} else {
addConjunct(Formula.and(fne1.conjuncts).or(Formula.and(fne2.conjuncts)), false, bf);
hasChanged = true;
}
} else {
// !(left || right) --> !left && !right
bf.left().accept(this);
bf.right().accept(this);
hasChanged = true;
}
break;
case IMPLIES:
if (!negated) {
// left => right --> !left || right
FullNegationPropagator fne1 = new FullNegationPropagator(shared, annotations);
bf.left().not().accept(fne1);
FullNegationPropagator fne2 = new FullNegationPropagator(shared, annotations);
bf.right().accept(fne2);
addConjunct(Formula.and(fne1.conjuncts).or(Formula.and(fne2.conjuncts)), false, bf);
} else {
// !(left => right) --> left && !right
negated = false;
bf.left().accept(this);
negated = true;
bf.right().accept(this);
}
hasChanged = true;
break;
case IFF:
FullNegationPropagator fne1 = new FullNegationPropagator(shared, annotations);
FullNegationPropagator fne2 = new FullNegationPropagator(shared, annotations);
if (!negated) {
// a <=> b --> (a && b) || (!a && !b)
bf.left().and(bf.right()).accept(fne1);
bf.left().not().and(bf.right().not()).accept(fne2);
} else {
// !(a = b) --> (a && !b) || (!a && b)
Formula orLhs = bf.left().and(bf.right().not());
orLhs.accept(fne1);
Formula orRhs = bf.left().not().and(bf.right());
orRhs.accept(fne2);
}
addConjunct(Formula.and(fne1.conjuncts).or(Formula.and(fne2.conjuncts)), false, bf);
hasChanged = true;
break;
default:
addConjunct(bf);
}
}
use of kodkod.ast.operator.FormulaOperator in project org.alloytools.alloy by AlloyTools.
the class Skolemizer method visit.
/**
* If not cached, visits the formula's children with appropriate settings for
* the negated flag and the skolemDepth parameter.
*
* @see kodkod.ast.visitor.AbstractReplacer#visit(kodkod.ast.BinaryFormula)
*/
@Override
public final Formula visit(BinaryFormula bf) {
Formula ret = lookup(bf);
if (ret != null)
return ret;
final FormulaOperator op = bf.op();
final int oldDepth = skolemDepth;
if (op == IFF || (negated && op == AND) || (!negated && (op == OR || op == IMPLIES))) {
// cannot
// skolemize
// in
// these
// cases
skolemDepth = -1;
}
final Formula left, right;
if (negated && op == IMPLIES) {
// !(a => b) = !(!a || b) = a && !b
negated = !negated;
left = bf.left().accept(this);
negated = !negated;
right = bf.right().accept(this);
} else {
left = bf.left().accept(this);
right = bf.right().accept(this);
}
skolemDepth = oldDepth;
ret = (left == bf.left() && right == bf.right()) ? bf : left.compose(op, right);
return source(cache(bf, ret), bf);
}
use of kodkod.ast.operator.FormulaOperator in project org.alloytools.alloy by AlloyTools.
the class Skolemizer method visit.
/**
* If not cached, visits the formula's children with appropriate settings for
* the negated flag and the skolemDepth parameter.
*
* @see kodkod.ast.visitor.AbstractReplacer#visit(kodkod.ast.NaryFormula)
*/
@Override
public final Formula visit(NaryFormula bf) {
Formula ret = lookup(bf);
if (ret != null)
return ret;
final int oldDepth = skolemDepth;
final FormulaOperator op = bf.op();
switch(op) {
case AND:
if (negated)
skolemDepth = -1;
break;
case OR:
if (!negated)
skolemDepth = -1;
break;
default:
throw new IllegalArgumentException("Unknown nary operator: " + op);
}
final Formula[] visited = new Formula[bf.size()];
boolean allSame = true;
for (int i = 0; i < visited.length; i++) {
final Formula child = bf.child(i);
visited[i] = child.accept(this);
allSame = allSame && (child == visited[i]);
}
ret = allSame ? bf : Formula.compose(op, visited);
skolemDepth = oldDepth;
return source(cache(bf, ret), bf);
}
use of kodkod.ast.operator.FormulaOperator in project org.alloytools.alloy by AlloyTools.
the class FormulaFlattener method visit.
/**
* Visits the formula's children with appropriate settings for the negated flag
* if bf has not been visited before.
*
* @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.BinaryFormula)
*/
@Override
public final void visit(BinaryFormula bf) {
if (visited(bf))
return;
final FormulaOperator op = bf.op();
if (op == IFF || (negated && op == AND) || (!negated && (op == OR || op == IMPLIES))) {
// can't
// break
// down
// further
// in
// these
// cases
addConjunct(bf);
} else {
// will break down further
if (negated && op == IMPLIES) {
// !(a => b) = !(!a || b) = a && !b
negated = !negated;
bf.left().accept(this);
negated = !negated;
bf.right().accept(this);
} else {
bf.left().accept(this);
bf.right().accept(this);
}
}
}
Aggregations