Search in sources :

Example 1 with RelationPredicate

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);
}
Also used : BooleanFormula(kodkod.engine.bool.BooleanFormula) Formula(kodkod.ast.Formula) AnnotatedNode(kodkod.util.nodes.AnnotatedNode) Node(kodkod.ast.Node) IdentityHashMap(java.util.IdentityHashMap) RelationPredicate(kodkod.ast.RelationPredicate) AbstractReplacer(kodkod.ast.visitor.AbstractReplacer)

Example 2 with RelationPredicate

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;
}
Also used : Variable(kodkod.ast.Variable) UnaryIntExpression(kodkod.ast.UnaryIntExpression) Decls(kodkod.ast.Decls) ConstantExpression(kodkod.ast.ConstantExpression) ComparisonFormula(kodkod.ast.ComparisonFormula) IntComparisonFormula(kodkod.ast.IntComparisonFormula) UnaryExpression(kodkod.ast.UnaryExpression) Function(kodkod.ast.RelationPredicate.Function) Relation(kodkod.ast.Relation) BinaryExpression(kodkod.ast.BinaryExpression) IntConstant(kodkod.ast.IntConstant) NaryIntExpression(kodkod.ast.NaryIntExpression) NotFormula(kodkod.ast.NotFormula) QuantifiedFormula(kodkod.ast.QuantifiedFormula) IfExpression(kodkod.ast.IfExpression) IntToExprCast(kodkod.ast.IntToExprCast) ProjectExpression(kodkod.ast.ProjectExpression) IfIntExpression(kodkod.ast.IfIntExpression) IfIntExpression(kodkod.ast.IfIntExpression) UnaryIntExpression(kodkod.ast.UnaryIntExpression) NaryIntExpression(kodkod.ast.NaryIntExpression) BinaryIntExpression(kodkod.ast.BinaryIntExpression) IntExpression(kodkod.ast.IntExpression) RelationPredicate(kodkod.ast.RelationPredicate) NaryExpression(kodkod.ast.NaryExpression) BinaryIntExpression(kodkod.ast.BinaryIntExpression) Decl(kodkod.ast.Decl) ConstantFormula(kodkod.ast.ConstantFormula) Comprehension(kodkod.ast.Comprehension) NaryFormula(kodkod.ast.NaryFormula) ExprToIntCast(kodkod.ast.ExprToIntCast) MultiplicityFormula(kodkod.ast.MultiplicityFormula) BinaryFormula(kodkod.ast.BinaryFormula) SumExpression(kodkod.ast.SumExpression) FixFormula(kodkod.ast.FixFormula) ReturnVisitor(kodkod.ast.visitor.ReturnVisitor) IntComparisonFormula(kodkod.ast.IntComparisonFormula)

Example 3 with RelationPredicate

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);
}
Also used : BinaryFormula(kodkod.ast.BinaryFormula) MultiplicityFormula(kodkod.ast.MultiplicityFormula) QuantifiedFormula(kodkod.ast.QuantifiedFormula) ConstantFormula(kodkod.ast.ConstantFormula) NotFormula(kodkod.ast.NotFormula) ComparisonFormula(kodkod.ast.ComparisonFormula) NaryFormula(kodkod.ast.NaryFormula) Formula(kodkod.ast.Formula) FixFormula(kodkod.ast.FixFormula) IntComparisonFormula(kodkod.ast.IntComparisonFormula) Relation(kodkod.ast.Relation) ProjectExpression(kodkod.ast.ProjectExpression) BinaryIntExpression(kodkod.ast.BinaryIntExpression) SumExpression(kodkod.ast.SumExpression) IfIntExpression(kodkod.ast.IfIntExpression) BinaryExpression(kodkod.ast.BinaryExpression) ConstantExpression(kodkod.ast.ConstantExpression) UnaryIntExpression(kodkod.ast.UnaryIntExpression) NaryIntExpression(kodkod.ast.NaryIntExpression) IntExpression(kodkod.ast.IntExpression) Expression(kodkod.ast.Expression) UnaryExpression(kodkod.ast.UnaryExpression) NaryExpression(kodkod.ast.NaryExpression) IfExpression(kodkod.ast.IfExpression) RelationPredicate(kodkod.ast.RelationPredicate)

Example 4 with RelationPredicate

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;
}
Also used : Formula(kodkod.ast.Formula) RelationPredicate(kodkod.ast.RelationPredicate) IdentityHashMap(java.util.IdentityHashMap)

Example 5 with RelationPredicate

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);
}
Also used : BooleanFormula(kodkod.engine.bool.BooleanFormula) Formula(kodkod.ast.Formula) RelationPredicate(kodkod.ast.RelationPredicate) AbstractReplacer(kodkod.ast.visitor.AbstractReplacer)

Aggregations

RelationPredicate (kodkod.ast.RelationPredicate)5 Formula (kodkod.ast.Formula)4 IdentityHashMap (java.util.IdentityHashMap)2 BinaryExpression (kodkod.ast.BinaryExpression)2 BinaryFormula (kodkod.ast.BinaryFormula)2 BinaryIntExpression (kodkod.ast.BinaryIntExpression)2 ComparisonFormula (kodkod.ast.ComparisonFormula)2 ConstantExpression (kodkod.ast.ConstantExpression)2 ConstantFormula (kodkod.ast.ConstantFormula)2 FixFormula (kodkod.ast.FixFormula)2 IfExpression (kodkod.ast.IfExpression)2 IfIntExpression (kodkod.ast.IfIntExpression)2 IntComparisonFormula (kodkod.ast.IntComparisonFormula)2 IntExpression (kodkod.ast.IntExpression)2 MultiplicityFormula (kodkod.ast.MultiplicityFormula)2 NaryExpression (kodkod.ast.NaryExpression)2 NaryFormula (kodkod.ast.NaryFormula)2 NaryIntExpression (kodkod.ast.NaryIntExpression)2 NotFormula (kodkod.ast.NotFormula)2 ProjectExpression (kodkod.ast.ProjectExpression)2