use of kodkod.ast.Formula in project org.alloytools.alloy by AlloyTools.
the class PrenexNFConverter method visit.
@Override
public Formula visit(BinaryFormula bf) {
Formula ans;
switch(bf.op()) {
case AND:
case OR:
Formula left = bf.left().accept(this);
Formula right = bf.right().accept(this);
Pair p = new Pair(left, right);
if (p.hasNoQuant() && left == bf.left() && right == bf.right())
ans = bf;
else
ans = p.compose(bf.op());
break;
case IMPLIES:
ans = bf.left().not().or(bf.right()).accept(this);
break;
case IFF:
ans = bf.left().and(bf.right()).or(bf.left().not().and(bf.right().not())).accept(this);
break;
default:
throw new IllegalStateException("Unknown BinaryFormula operator: " + bf.op());
}
return saveMapping(ans, bf);
}
use of kodkod.ast.Formula 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.Formula in project org.alloytools.alloy by AlloyTools.
the class Skolemizer method visit.
/**
* Skolemizes the given formula, if possible, otherwise returns the result of
* replacing its free variables according to the current replacement
* environment.
*
* @see kodkod.ast.visitor.AbstractReplacer#visit(kodkod.ast.QuantifiedFormula)
*/
@Override
public final Formula visit(QuantifiedFormula qf) {
Formula ret = lookup(qf);
if (ret != null)
return ret;
final Environment<Expression, Expression> oldRepEnv = repEnv;
final Quantifier quant = qf.quantifier();
final Decls decls = qf.decls();
if (skolemDepth >= 0 && (negated && quant == ALL || !negated && quant == SOME)) {
// skolemizable
// formula
final List<Formula> rangeConstraints = new LinkedList<Formula>();
final List<Formula> domConstraints = new LinkedList<Formula>();
for (Decl decl : decls) {
final Decl skolemDecl = visit(decl);
Variable skVar = skolemDecl.variable();
final Relation skolem = Relation.skolem("$" + skVar.name(), nonSkolems.size() + skVar.arity(), skVar, skolemDecl, quant);
reporter.skolemizing(decl, skolem, nonSkolemsView);
final Expression skolemExpr = skolemExpr(skolemDecl, skolem);
final Multiplicity mult = decl.multiplicity();
rangeConstraints.add(source(skolemExpr.in(skolemDecl.expression()), decl));
if (mult != Multiplicity.SET) {
rangeConstraints.add(source(skolemExpr.apply(mult), decl));
}
if (!nonSkolems.isEmpty())
domConstraints.add(source(domainConstraint(skolemDecl, skolem), decl));
repEnv = repEnv.extend(decl.variable(), decl.expression(), skolemExpr);
}
ret = source(Formula.and(rangeConstraints), decls).compose(negated ? IMPLIES : AND, qf.formula().accept(this));
if (!domConstraints.isEmpty())
topSkolemConstraints.add(source(Formula.and(domConstraints), decls));
} else {
// non-skolemizable formula
final Decls newDecls = visit(qf.decls());
if (skolemDepth >= nonSkolems.size() + newDecls.size()) {
// below
for (Decl d : newDecls) {
nonSkolems.add(new DeclInfo(d));
}
final Formula domain = qf.domain().accept(this);
final Formula body = qf.body().accept(this);
ret = ((newDecls == decls && domain == qf.domain() && body == qf.body()) ? qf : body.quantify(quant, newDecls, domain));
for (int i = newDecls.size(); i > 0; i--) {
nonSkolems.remove(nonSkolems.size() - 1);
}
} else {
// can't skolemize below
final int oldDepth = skolemDepth;
skolemDepth = -1;
final Formula domain = qf.domain().accept(this);
final Formula body = qf.body().accept(this);
ret = ((newDecls == decls && domain == qf.domain() && body == qf.body()) ? qf : body.quantify(quant, newDecls, domain));
skolemDepth = oldDepth;
}
}
repEnv = oldRepEnv;
if (repEnv.isEmpty() && !topSkolemConstraints.isEmpty()) {
ret = source(Formula.and(topSkolemConstraints), qf).compose(negated ? IMPLIES : AND, ret);
}
return source(cache(qf, ret), qf);
}
use of kodkod.ast.Formula in project org.alloytools.alloy by AlloyTools.
the class Skolemizer method visit.
/**
* Calls not.formula.accept(this) after flipping the negation flag and returns
* the result.
*
* @see kodkod.ast.visitor.AbstractReplacer#visit(kodkod.ast.NotFormula)
*/
@Override
public final Formula visit(NotFormula not) {
Formula ret = lookup(not);
if (ret != null)
return ret;
// flip the negation flag
negated = !negated;
final Formula retChild = not.formula().accept(this);
negated = !negated;
return retChild == not.formula() ? cache(not, not) : source(cache(not, retChild.not()), not);
}
use of kodkod.ast.Formula in project org.alloytools.alloy by AlloyTools.
the class Skolemizer method visit.
/**
* Calls super.visit(cf) after disabling skolemization and returns the result.
*
* @return super.visit(cf)
*/
@Override
public final Formula visit(ComparisonFormula cf) {
final int oldDepth = skolemDepth;
// cannot skolemize inside a comparison formula
skolemDepth = -1;
final Formula ret = super.visit(cf);
skolemDepth = oldDepth;
return source(ret, cf);
}
Aggregations