use of kodkod.ast.Expression in project org.alloytools.alloy by AlloyTools.
the class TranslateAlloyToKodkod method isInBinary.
/**
* Helper method that translates the formula "r in (a ?->? b)" into a Kodkod
* formula.
*/
private Formula isInBinary(Expression r, ExprBinary ab) throws Err {
final Expression a = cset(ab.left), b = cset(ab.right);
Decls d = null, d2 = null;
Formula ans1, ans2;
// "R in A ->op B" means for each tuple a in A, there are "op" tuples in
// r that begins with a.
Expression atuple = null, ar = r;
for (int i = a.arity(); i > 0; i--) {
Variable v = Variable.unary("v" + Integer.toString(cnt++));
if (!am) {
if (a.arity() == 1)
d = v.oneOf(a);
else if (d == null)
d = v.oneOf(Expression.UNIV);
else
d = v.oneOf(Expression.UNIV).and(d);
} else {
d = am(a, d, i, v);
}
ar = v.join(ar);
if (atuple == null)
atuple = v;
else
atuple = atuple.product(v);
}
ans1 = isIn(ar, ab.right);
switch(ab.op) {
case ISSEQ_ARROW_LONE:
case ANY_ARROW_LONE:
case SOME_ARROW_LONE:
case ONE_ARROW_LONE:
case LONE_ARROW_LONE:
ans1 = ar.lone().and(ans1);
break;
case ANY_ARROW_ONE:
case SOME_ARROW_ONE:
case ONE_ARROW_ONE:
case LONE_ARROW_ONE:
ans1 = ar.one().and(ans1);
break;
case ANY_ARROW_SOME:
case SOME_ARROW_SOME:
case ONE_ARROW_SOME:
case LONE_ARROW_SOME:
ans1 = ar.some().and(ans1);
break;
}
if (a.arity() > 1) {
Formula tmp = isIn(atuple, ab.left);
if (tmp != Formula.TRUE)
ans1 = tmp.implies(ans1);
}
ans1 = ans1.forAll(d);
// "R in A op-> B" means for each tuple b in B, there are "op" tuples in
// r that end with b.
Expression btuple = null, rb = r;
for (int i = b.arity(); i > 0; i--) {
Variable v = Variable.unary("v" + Integer.toString(cnt++));
if (!am) {
if (b.arity() == 1)
d2 = v.oneOf(b);
else if (d2 == null)
d2 = v.oneOf(Expression.UNIV);
else
d2 = v.oneOf(Expression.UNIV).and(d2);
} else {
d2 = am(b, d2, i, v);
}
rb = rb.join(v);
if (btuple == null)
btuple = v;
else
btuple = v.product(btuple);
}
ans2 = isIn(rb, ab.left);
switch(ab.op) {
case LONE_ARROW_ANY:
case LONE_ARROW_SOME:
case LONE_ARROW_ONE:
case LONE_ARROW_LONE:
ans2 = rb.lone().and(ans2);
break;
case ONE_ARROW_ANY:
case ONE_ARROW_SOME:
case ONE_ARROW_ONE:
case ONE_ARROW_LONE:
ans2 = rb.one().and(ans2);
break;
case SOME_ARROW_ANY:
case SOME_ARROW_SOME:
case SOME_ARROW_ONE:
case SOME_ARROW_LONE:
ans2 = rb.some().and(ans2);
break;
}
if (b.arity() > 1) {
Formula tmp = isIn(btuple, ab.right);
if (tmp != Formula.TRUE)
ans2 = tmp.implies(ans2);
}
ans2 = ans2.forAll(d2);
// Now, put everything together
Formula ans = r.in(a.product(b)).and(ans1).and(ans2);
if (ab.op == ExprBinary.Op.ISSEQ_ARROW_LONE) {
Expression rr = r;
while (rr.arity() > 1) rr = rr.join(Expression.UNIV);
ans = rr.difference(rr.join(A4Solution.KK_NEXT)).in(A4Solution.KK_ZERO).and(ans);
}
return ans;
}
use of kodkod.ast.Expression in project org.alloytools.alloy by AlloyTools.
the class TranslateAlloyToKodkod method visit.
// ==============================================================================================================//
/* ============================ */
/* Evaluates an ExprITE node. */
/* ============================ */
/**
* {@inheritDoc}
*/
@Override
public Object visit(ExprITE x) throws Err {
Formula c = cform(x.cond);
Object l = visitThis(x.left);
if (l instanceof Formula) {
Formula c1 = c.implies((Formula) l);
Formula c2 = c.not().implies(cform(x.right));
return k2pos(c1.and(c2), x);
}
if (l instanceof Expression) {
return c.thenElse((Expression) l, cset(x.right));
}
return c.thenElse((IntExpression) l, cint(x.right));
}
use of kodkod.ast.Expression 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.Expression in project org.alloytools.alloy by AlloyTools.
the class Skolemizer method visit.
/*-------declarations---------*/
/**
* Visits the given decl's expression. Note that we must not visit variables in
* case they are re-used. For example, consider the formula some x: X | all x: Y
* | F(x). Since x bound by the existential quantifier is going to be
* skolemized, if we visited the variable in the enclosed declaration, we would
* get the skolem constant as a return value and a ClassCastException would be
* thrown.
*
* @return { d: Declaration | d.variable = decl.variable && d.multiplicity =
* decl.multiplicity && d.expression = decl.expression.accept(this) }
*/
@Override
public final Decl visit(Decl decl) {
Decl ret = lookup(decl);
if (ret != null)
return ret;
final int oldDepth = skolemDepth;
// can't skolemize inside a decl
skolemDepth = -1;
final Expression expression = decl.expression().accept(this);
skolemDepth = oldDepth;
ret = (expression == decl.expression()) ? decl : decl.variable().declare(decl.multiplicity(), expression);
return cache(decl, ret);
}
use of kodkod.ast.Expression in project org.alloytools.alloy by AlloyTools.
the class Skolemizer method skolemExpr.
/**
* Adds a bound for the given skolem relation to this.bounds, and returns the
* expression that should replace skolemDecl.variable in the final formula.
*
* @requires skolem !in this.bounds.relations
* @requires skolem.arity = nonSkolems.size() + skolemDecl.variable().arity()
* @ensures adds a sound upper bound for the given skolem relation to
* this.bounds
* @return the expression that should replace skolemDecl.variable in the final
* formula
*/
private Expression skolemExpr(Decl skolemDecl, Relation skolem) {
final int depth = nonSkolems.size();
final int arity = depth + skolemDecl.variable().arity();
Expression skolemExpr = skolem;
Environment<BooleanMatrix, Expression> skolemEnv = Environment.empty();
for (DeclInfo info : nonSkolems) {
if (info.upperBound == null) {
info.upperBound = upperBound(info.decl.expression(), skolemEnv);
}
skolemEnv = skolemEnv.extend(info.decl.variable(), info.decl.expression(), info.upperBound);
skolemExpr = info.decl.variable().join(skolemExpr);
}
BooleanMatrix matrixBound = upperBound(skolemDecl.expression(), skolemEnv);
for (int i = depth - 1; i >= 0; i--) {
matrixBound = nonSkolems.get(i).upperBound.cross(matrixBound);
}
final TupleSet skolemBound = bounds.universe().factory().setOf(arity, matrixBound.denseIndices());
bounds.bound(skolem, skolemBound);
return skolemExpr;
}
Aggregations