use of kodkod.ast.operator.Multiplicity 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.operator.Multiplicity in project org.alloytools.alloy by AlloyTools.
the class FOL2BoolTranslator method visit.
/**
* Calls lookup(multFormula) 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(multFormula) | some t => t, let op =
* (multFormula.mult).(NO->none + SOME->some + ONE->one + LONE->lone) |
* cache(multFormula, op(multFormula.expression.accept(this)))
*/
@Override
public final BooleanValue visit(MultiplicityFormula multFormula) {
BooleanValue ret = lookup(multFormula);
if (ret != null)
return ret;
final BooleanMatrix child = multFormula.expression().accept(this);
final Multiplicity mult = multFormula.multiplicity();
switch(mult) {
case NO:
ret = child.none(env);
break;
case SOME:
ret = child.some(env);
break;
case ONE:
ret = child.one(env);
break;
case LONE:
ret = child.lone(env);
break;
default:
throw new IllegalArgumentException("Unknown multiplicity: " + mult);
}
return cache(multFormula, ret);
}
Aggregations