use of kodkod.ast.RelationPredicate in project org.alloytools.alloy by AlloyTools.
the class Translator method inlinePredicates.
/**
* Returns an annotated formula f such that f.node is equivalent to
* annotated.node with its <tt>simplified</tt> predicates replaced with their
* corresponding Formulas and the remaining predicates replaced with equivalent
* constraints. The annotated formula f will contain transitive source
* information for each of the subformulas of f.node. Specifically, let t be a
* subformula of f.node, and s be a descdendent of annotated.node from which t
* was derived. Then, f.source[t] = annotated.source[s].
* </p>
*
* @requires simplified.keySet() in
* annotated.predicates()[RelationPredicate.NAME]
* @requires no disj p, p': simplified.keySet() | simplified.get(p) =
* simplifed.get(p') // this must hold in order to maintain the
* invariant that each subformula of the returned formula has exactly
* one source
* @requires for each p in simplified.keySet(), the formulas "p and
* [[this.bounds]]" and "simplified.get(p) and [[this.bounds]]" are
* equisatisfiable
* @return an annotated formula f such that f.node is equivalent to
* annotated.node with its <tt>simplified</tt> predicates replaced with
* their corresponding Formulas and the remaining predicates replaced
* with equivalent constraints.
*/
private AnnotatedNode<Formula> inlinePredicates(final AnnotatedNode<Formula> annotated, final Map<RelationPredicate, Formula> simplified) {
final Map<Node, Node> sources = new IdentityHashMap<Node, Node>();
final AbstractReplacer inliner = new AbstractReplacer(annotated.sharedNodes()) {
private RelationPredicate source = null;
@Override
protected <N extends Node> N cache(N node, N replacement) {
if (replacement instanceof Formula) {
if (source == null) {
final Node nsource = annotated.sourceOf(node);
if (replacement != nsource)
sources.put(replacement, nsource);
} else {
sources.put(replacement, source);
}
}
return super.cache(node, replacement);
}
@Override
public Formula visit(RelationPredicate pred) {
Formula ret = lookup(pred);
if (ret != null)
return ret;
source = pred;
if (simplified.containsKey(pred)) {
ret = simplified.get(pred).accept(this);
} else {
ret = pred.toConstraints().accept(this);
}
source = null;
return cache(pred, ret);
}
};
return annotate(annotated.node().accept(inliner), sources);
}
use of kodkod.ast.RelationPredicate in project org.alloytools.alloy by AlloyTools.
the class TranslateKodkodToJava method countHeight.
/**
* Count the height of the given Kodkod AST tree.
*/
public static int countHeight(Node node) {
ReturnVisitor<Integer, Integer, Integer, Integer> vis = new ReturnVisitor<Integer, Integer, Integer, Integer>() {
private int max(int a, int b) {
return (a >= b) ? a : b;
}
private int max(int a, int b, int c) {
return (a >= b) ? (a >= c ? a : c) : (b >= c ? b : c);
}
@Override
public Integer visit(Relation x) {
return 1;
}
@Override
public Integer visit(IntConstant x) {
return 1;
}
@Override
public Integer visit(ConstantFormula x) {
return 1;
}
@Override
public Integer visit(Variable x) {
return 1;
}
@Override
public Integer visit(ConstantExpression x) {
return 1;
}
@Override
public Integer visit(NotFormula x) {
return 1 + x.formula().accept(this);
}
@Override
public Integer visit(IntToExprCast x) {
return 1 + x.intExpr().accept(this);
}
@Override
public Integer visit(Decl x) {
return 1 + x.expression().accept(this);
}
@Override
public Integer visit(ExprToIntCast x) {
return 1 + x.expression().accept(this);
}
@Override
public Integer visit(UnaryExpression x) {
return 1 + x.expression().accept(this);
}
@Override
public Integer visit(UnaryIntExpression x) {
return 1 + x.intExpr().accept(this);
}
@Override
public Integer visit(MultiplicityFormula x) {
return 1 + x.expression().accept(this);
}
@Override
public Integer visit(BinaryExpression x) {
return 1 + max(x.left().accept(this), x.right().accept(this));
}
@Override
public Integer visit(ComparisonFormula x) {
return 1 + max(x.left().accept(this), x.right().accept(this));
}
@Override
public Integer visit(BinaryFormula x) {
return 1 + max(x.left().accept(this), x.right().accept(this));
}
@Override
public Integer visit(BinaryIntExpression x) {
return 1 + max(x.left().accept(this), x.right().accept(this));
}
@Override
public Integer visit(IntComparisonFormula x) {
return 1 + max(x.left().accept(this), x.right().accept(this));
}
@Override
public Integer visit(IfExpression x) {
return 1 + max(x.condition().accept(this), x.thenExpr().accept(this), x.elseExpr().accept(this));
}
@Override
public Integer visit(IfIntExpression x) {
return 1 + max(x.condition().accept(this), x.thenExpr().accept(this), x.elseExpr().accept(this));
}
@Override
public Integer visit(SumExpression x) {
return 1 + max(x.decls().accept(this), x.intExpr().accept(this));
}
@Override
public Integer visit(QuantifiedFormula x) {
return 1 + max(x.decls().accept(this), x.formula().accept(this));
}
@Override
public Integer visit(FixFormula x) {
return 1 + max(x.condition().accept(this), x.formula().accept(this));
}
@Override
public Integer visit(Comprehension x) {
return 1 + max(x.decls().accept(this), x.formula().accept(this));
}
@Override
public Integer visit(Decls x) {
int max = 0, n = x.size();
for (int i = 0; i < n; i++) max = max(max, x.get(i).accept(this));
return max;
}
@Override
public Integer visit(ProjectExpression x) {
int max = x.expression().accept(this);
for (Iterator<IntExpression> t = x.columns(); t.hasNext(); ) {
max = max(max, t.next().accept(this));
}
return max;
}
@Override
public Integer visit(RelationPredicate x) {
if (x instanceof Function) {
Function f = ((Function) x);
return max(f.domain().accept(this), f.range().accept(this));
}
return 1;
}
@Override
public Integer visit(NaryExpression x) {
int max = 0;
for (int m = 0, n = x.size(), i = 0; i < n; i++) {
m = x.child(i).accept(this);
if (i == 0 || max < m)
max = m;
}
return max + 1;
}
@Override
public Integer visit(NaryIntExpression x) {
int max = 0;
for (int m = 0, n = x.size(), i = 0; i < n; i++) {
m = x.child(i).accept(this);
if (i == 0 || max < m)
max = m;
}
return max + 1;
}
@Override
public Integer visit(NaryFormula x) {
int max = 0;
for (int m = 0, n = x.size(), i = 0; i < n; i++) {
m = x.child(i).accept(this);
if (i == 0 || max < m)
max = m;
}
return max + 1;
}
};
Object ans = node.accept(vis);
if (ans instanceof Integer)
return ((Integer) ans).intValue();
else
return 0;
}
use of kodkod.ast.RelationPredicate in project org.alloytools.alloy by AlloyTools.
the class AbstractReplacer method visit.
/**
* Calls lookup(pred) and returns the cached value, if any. If a replacement has
* not been cached, visits the formula's children. If nothing changes, the
* argument is cached and returned, otherwise a replacement formula is cached
* and returned.
*
* @return { p: RelationPredicate | p.name = pred.name && p.relation =
* pred.relation.accept(delegate) && p.name = FUNCTION => p.targetMult =
* pred.targetMult && p.domain = pred.domain.accept(delegate) && p.range
* = pred.range.accept(delegate), p.name = TOTAL_ORDERING => p.ordered =
* pred.ordered.accept(delegate) && p.first =
* pred.first.accept(delegate) && p.last = pred.last.accept(delegate) }
*/
@Override
public Formula visit(RelationPredicate pred) {
Formula ret = lookup(pred);
if (ret != null)
return ret;
final Relation r = (Relation) pred.relation().accept(delegate);
switch(pred.name()) {
case ACYCLIC:
ret = (r == pred.relation()) ? pred : r.acyclic();
break;
case FUNCTION:
final RelationPredicate.Function fp = (RelationPredicate.Function) pred;
final Expression domain = fp.domain().accept(delegate);
final Expression range = fp.range().accept(delegate);
ret = (r == fp.relation() && domain == fp.domain() && range == fp.range()) ? fp : (fp.targetMult() == Multiplicity.ONE ? r.function(domain, range) : r.partialFunction(domain, range));
break;
case TOTAL_ORDERING:
final RelationPredicate.TotalOrdering tp = (RelationPredicate.TotalOrdering) pred;
final Relation ordered = (Relation) tp.ordered().accept(delegate);
final Relation first = (Relation) tp.first().accept(delegate);
final Relation last = (Relation) tp.last().accept(delegate);
ret = (r == tp.relation() && ordered == tp.ordered() && first == tp.first() && last == tp.last()) ? tp : r.totalOrder(ordered, first, last);
break;
default:
throw new IllegalArgumentException("unknown relation predicate: " + pred.name());
}
return cache(pred, ret);
}
use of kodkod.ast.RelationPredicate in project org.alloytools.alloy by AlloyTools.
the class SymmetryBreaker method breakMatrixSymmetries.
/**
* Breaks matrix symmetries on the relations in this.bounds that are constrained
* by the total ordering and acyclic predicates, drawn from preds.values(), that
* make up the keyset of the returned map. After this method returns, the
* following constraint holds. Let m be the map returned by the method, and
* m.keySet() be the subset of preds.values() used for symmetry breaking. Then,
* if we let [[b]] denote the set of constraints specified by a Bounds object b,
* the formulas "p and [[this.bounds]]" and "m.get(p) and [[this.bounds']]" are
* equisatisfiable for all p in m.keySet().
* <p>
* The value of the "aggressive" flag determines how the symmetries are broken.
* In particular, if the aggressive flag is true, then the symmetries are broken
* efficiently, at the cost of losing the information needed to determine
* whether a predicate in m.keySet() belongs to an unsatisfiable core or not. If
* the aggressive flag is false, then a less efficient algorithm is applied,
* which preserves the information necessary for unsatisfiable core extraction.
* </p>
* <p>
* The aggressive symmetry breaking algorithm works as follows. Let t1...tn and
* c1...ck be the total ordering and acyclic predicates in m.keySet(). For each
* t in {t1...tn}, this.bounds is modified so that the bounds for t.first,
* t.last, t.ordered and t.relation are the following constants: t.first is the
* first atom in the upper bound of t.ordered, t.last is the last atom in the
* upper bound of t.ordered, t.ordered's lower bound is changed to be equal to
* its upper bound, and t.relation imposes a total ordering on t.ordered that
* corresponds to the ordering of the atoms in this.bounds.universe. Then, m is
* updated with a binding from t to the constant formula TRUE. For each c in
* {c1...ck}, this.bounds is modified so that the upper bound for c.relation is
* a tupleset whose equivalent matrix has FALSE in the entries on or below the
* main diagonal. Then, m is updated with a binding from c to the constant
* formula TRUE.
* </p>
* <p>
* The lossless symmetry breaking algorithm works as follows. Let t1...tn and
* c1...ck be the total ordering and acyclic predicates in m.keySet(). For each
* t in {t1...tn}, three fresh relations are added to this.bounds-- t_first,
* t_last, t_ordered, and t_order--and constrained as follows: t_first is the
* first atom in the upper bound of t.ordered, t_last is the last atom in the
* upper bound of t.ordered, t_ordered is the upper bound of t.ordered, and
* t_order imposes a total ordering on t.ordered that corresponds to the
* ordering of the atoms in this.bounds.universe. Then, m is updated with a
* binding from t to the formula "t.first = t_first and t.last = t_last and
* t.ordered = t_ordered and t.relation = t.order." For each c in {c1...ck}, a
* fresh relation c_acyclic is added to this.bounds and constrained to be a
* constant whose equivalent matrix has no entries on or below the main
* diagonal. The map m is then updated with a binding from c to the constraint
* "c in c_acyclic".
* </p>
*
* @ensures this.bounds' is modified as described above
* @ensures this.symmetries' is modified to no longer contain the partitions
* that made up the bounds of the relations on which symmetries have
* been broken
* @return a map m such that m.keySet() in preds.values(), and for all
* predicates p in m.keySet(), the formulas "p and [[this.bounds]]" and
* "m.get(p) and [[this.bounds']]" are equisatisfiable
*/
public Map<RelationPredicate, Formula> breakMatrixSymmetries(Map<Name, Set<RelationPredicate>> preds, boolean aggressive) {
final Set<RelationPredicate> totals = preds.get(TOTAL_ORDERING);
final Set<RelationPredicate> acyclics = preds.get(ACYCLIC);
final Map<RelationPredicate, Formula> broken = new IdentityHashMap<RelationPredicate, Formula>();
for (RelationPredicate.TotalOrdering pred : sort(totals.toArray(new RelationPredicate.TotalOrdering[totals.size()]))) {
Formula replacement = breakTotalOrder(pred, aggressive);
if (replacement != null)
broken.put(pred, replacement);
}
for (RelationPredicate.Acyclic pred : sort(acyclics.toArray(new RelationPredicate.Acyclic[acyclics.size()]))) {
Formula replacement = breakAcyclic(pred, aggressive);
if (replacement != null)
broken.put(pred, replacement);
}
return broken;
}
use of kodkod.ast.RelationPredicate in project org.alloytools.alloy by AlloyTools.
the class Translator method inlinePredicates.
/**
* Returns an annotated formula f such that f.node is equivalent to
* annotated.node with its <tt>truePreds</tt> replaced with the constant formula
* TRUE and the remaining predicates replaced with equivalent constraints.
*
* @requires truePreds in annotated.predicates()[RelationnPredicate.NAME]
* @requires truePreds are trivially true with respect to this.bounds
* @return an annotated formula f such that f.node is equivalent to
* annotated.node with its <tt>truePreds</tt> replaced with the constant
* formula TRUE and the remaining predicates replaced with equivalent
* constraints.
*/
private AnnotatedNode<Formula> inlinePredicates(final AnnotatedNode<Formula> annotated, final Set<RelationPredicate> truePreds) {
final AbstractReplacer inliner = new AbstractReplacer(annotated.sharedNodes()) {
@Override
public Formula visit(RelationPredicate pred) {
Formula ret = lookup(pred);
if (ret != null)
return ret;
return truePreds.contains(pred) ? cache(pred, Formula.TRUE) : cache(pred, pred.toConstraints());
}
};
Formula x = annotated.node().accept(inliner);
return annotate(x);
}
Aggregations