Search in sources :

Example 56 with Relation

use of kodkod.ast.Relation in project org.alloytools.alloy by AlloyTools.

the class SymmetryBreaker method breakAcyclic.

/**
 * If possible, breaks symmetry on the given acyclic predicate and returns a
 * formula f such that the meaning of acyclic with respect to this.bounds is
 * equivalent to the meaning of f with respect to this.bounds'. If symmetry
 * cannot be broken on the given predicate, returns null.
 * <p>
 * We break symmetry on the relation constrained by the given predicate iff
 * this.bounds.upperBound[acyclic.relation] is the cross product of some
 * partition in this.symmetries with itself. Assuming that this is the case, we
 * then break symmetry on acyclic.relation using one of the methods described in
 * {@linkplain #breakMatrixSymmetries(Map, boolean)}; the method used depends on
 * the value of the "agressive" flag. The partition that formed the upper bound
 * of acylic.relation is removed from this.symmetries.
 * </p>
 *
 * @return null if symmetry cannot be broken on acyclic; otherwise returns a
 *         formula f such that the meaning of acyclic with respect to
 *         this.bounds is equivalent to the meaning of f with respect to
 *         this.bounds'
 * @ensures this.symmetries and this.bounds are modified as described in
 *          {@linkplain #breakMatrixSymmetries(Map, boolean)} iff
 *          this.bounds.upperBound[acyclic.relation] is the cross product of
 *          some partition in this.symmetries with itself
 * @see #breakMatrixSymmetries(Map,boolean)
 */
private final Formula breakAcyclic(RelationPredicate.Acyclic acyclic, boolean aggressive) {
    final IntSet[] colParts = symmetricColumnPartitions(acyclic.relation());
    if (colParts != null) {
        final Relation relation = acyclic.relation();
        final IntSet upper = bounds.upperBound(relation).indexView();
        final IntSet reduced = Ints.bestSet(usize * usize);
        for (IntIterator tuples = upper.iterator(); tuples.hasNext(); ) {
            int tuple = tuples.next();
            int mirror = (tuple / usize) + (tuple % usize) * usize;
            if (tuple != mirror) {
                if (!upper.contains(mirror))
                    return null;
                if (!reduced.contains(mirror))
                    reduced.add(tuple);
            }
        }
        // remove the partition from the set of symmetric partitions
        removePartition(colParts[0].min());
        if (aggressive) {
            bounds.bound(relation, bounds.universe().factory().setOf(2, reduced));
            return Formula.TRUE;
        } else {
            final Relation acyclicConst = Relation.binary("SYM_BREAK_CONST_" + acyclic.relation().name());
            bounds.boundExactly(acyclicConst, bounds.universe().factory().setOf(2, reduced));
            return relation.in(acyclicConst);
        }
    }
    return null;
}
Also used : Relation(kodkod.ast.Relation) IntIterator(kodkod.util.ints.IntIterator) IntSet(kodkod.util.ints.IntSet)

Example 57 with Relation

use of kodkod.ast.Relation in project org.alloytools.alloy by AlloyTools.

the class Translator method toCNF.

/**
 * Translates the given circuit to CNF, adds the clauses to a SATSolver returned
 * by options.solver(), and returns a Translation object constructed from the
 * solver and the provided arguments.
 *
 * @requires SAT(circuit) iff SAT(this.originalFormula, this.originalBounds,
 *           this.options)
 * @requires circuit.factory = interpreter.factory
 * @requires interpreter.universe = this.bounds.universe &&
 *           interpreter.relations = this.bounds.relations() && interpreter.ints
 *           = this.bounds.ints() && interpreter.lbounds =
 *           this.bounds.lowerBound && this.interpreter.ubounds =
 *           bounds.upperBound && interpreter.ibounds = bounds.intBound
 * @requires log.originalFormula = this.originalFormula && log.bounds =
 *           this.bounds
 * @ensures {@link #completeBounds()}
 * @ensures this.options.reporter.translatingToCNF(circuit)
 * @return some t: Translation | t.bounds = completeBounds() && t.originalBounds
 *         = this.originalBounds && t.vars = interpreter.vars &&
 *         t.vars[Relation].int in t.solver.variables && t.solver.solve() iff
 *         SAT(this.formula, this.bounds, this.options)
 */
private Translation toCNF(BooleanFormula circuit, LeafInterpreter interpreter, TranslationLog log) {
    options.reporter().translatingToCNF(circuit);
    final int maxPrimaryVar = interpreter.factory().maxVariable();
    if (incremental) {
        final Bool2CNFTranslator incrementer = Bool2CNFTranslator.translateIncremental(circuit, maxPrimaryVar, options.solver());
        return new Translation.Incremental(completeBounds(), options, SymmetryDetector.partition(originalBounds), interpreter, incrementer);
    } else {
        final Map<Relation, IntSet> varUsage = interpreter.vars();
        // enable gc
        interpreter = null;
        final SATSolver cnf = Bool2CNFTranslator.translate(circuit, maxPrimaryVar, options.solver());
        return new Translation.Whole(completeBounds(), options, cnf, varUsage, maxPrimaryVar, log);
    }
}
Also used : SATSolver(kodkod.engine.satlab.SATSolver) Relation(kodkod.ast.Relation) IntSet(kodkod.util.ints.IntSet)

Example 58 with Relation

use of kodkod.ast.Relation in project org.alloytools.alloy by AlloyTools.

the class Translator method checkIncrementalBounds.

/**
 * Checks that the given {@code inc} bounds are incremental with respect to the
 * given {@code translation}.
 *
 * @requires translation.bounds.universe = inc.universe && no inc.intBound && no
 *           (translation.bounds.relations & inc.relations)
 * @requires all s: translation.symmetries | some p:
 *           {@link SymmetryDetector#partition(Bounds) partition}(inc) |
 *           s.elements in p.elements
 * @throws IllegalArgumentException any of the preconditions are violated
 */
public static void checkIncrementalBounds(Bounds inc, Translation.Incremental translation) {
    final Bounds base = translation.bounds();
    if (!base.universe().equals(inc.universe()))
        incBoundErr(inc.universe(), "universe", "equal to", base.universe());
    if (!inc.intBounds().isEmpty())
        incBoundErr(inc.intBounds(), "intBound", "empty, with integer bounds fully specified by", base.intBounds());
    if (inc.relations().isEmpty())
        return;
    final Set<Relation> baseRels = base.relations();
    for (Relation r : inc.relations()) {
        if (baseRels.contains(r)) {
            incBoundErr(inc.relations(), "relations", "disjoint from", baseRels);
        }
    }
    final Set<IntSet> symmetries = translation.symmetries();
    final Set<IntSet> incSymmetries = SymmetryDetector.partition(inc);
    EQUIV_CHECK: for (IntSet part : symmetries) {
        for (IntSet incPart : incSymmetries) {
            if (incPart.containsAll(part))
                continue EQUIV_CHECK;
        }
        incBoundErr(incSymmetries, "partition", "coarser than", symmetries);
    }
}
Also used : Relation(kodkod.ast.Relation) IntSet(kodkod.util.ints.IntSet) Bounds(kodkod.instance.Bounds)

Example 59 with Relation

use of kodkod.ast.Relation in project org.alloytools.alloy by AlloyTools.

the class Translator method translateIncrementalNonTrivial.

/**
 * @requires checkIncrementalBounds(bounds, transl)
 * @requires checkIncrementalOptions(transl.options)
 * @requires !transl.trivial()
 * @return see {@link #translateIncremental(Formula, Bounds, Options)}
 */
private static Translation.Incremental translateIncrementalNonTrivial(Formula formula, Bounds bounds, Translation.Incremental transl) {
    final Options tOptions = transl.options();
    final Bounds tBounds = transl.bounds();
    // save the set of relations bound in the pre-state
    final Set<Relation> oldRelations = new LinkedHashSet<Relation>(tBounds.relations());
    // skolemization (below) may also cause extra relations to be added.
    for (Relation r : bounds.relations()) {
        tBounds.bound(r, bounds.lowerBound(r), bounds.upperBound(r));
    }
    final AnnotatedNode<Formula> annotated = (transl.options().skolemDepth() < 0) ? annotate(formula) : skolemize(annotate(formula), tBounds, tOptions);
    // extend the interpreter with variable allocations for new relations,
    // either from given bounds
    // or those introduced by skolemization
    final LeafInterpreter interpreter = transl.interpreter();
    interpreter.extend(setDifference(tBounds.relations(), oldRelations), tBounds.lowerBounds(), tBounds.upperBounds());
    final BooleanValue circuit = FOL2BoolTranslator.translate(annotated, interpreter);
    if (circuit == BooleanConstant.FALSE) {
        // release the old solver and state, and return a fresh trivially
        // false incremental translation.
        transl.incrementer().solver().free();
        return new Translation.Incremental(tBounds, tOptions, transl.symmetries(), LeafInterpreter.empty(tBounds.universe(), tOptions), Bool2CNFTranslator.translateIncremental(BooleanConstant.FALSE, tOptions.solver()));
    } else if (circuit == BooleanConstant.TRUE) {
        // must add any newly allocated primary variables to the solver for
        // interpretation to work correctly
        final int maxVar = interpreter.factory().maxVariable();
        final int cnfVar = transl.cnf().numberOfVariables();
        if (maxVar > cnfVar) {
            transl.cnf().addVariables(maxVar - cnfVar);
        }
    } else {
        // circuit is a formula; add its CNF representation to
        // transl.incrementer.solver()
        Bool2CNFTranslator.translateIncremental((BooleanFormula) circuit, interpreter.factory().maxVariable(), transl.incrementer());
    }
    return transl;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Options(kodkod.engine.config.Options) BooleanFormula(kodkod.engine.bool.BooleanFormula) Formula(kodkod.ast.Formula) Relation(kodkod.ast.Relation) Bounds(kodkod.instance.Bounds) BooleanValue(kodkod.engine.bool.BooleanValue) BooleanFormula(kodkod.engine.bool.BooleanFormula)

Example 60 with Relation

use of kodkod.ast.Relation in project org.alloytools.alloy by AlloyTools.

the class Proc method union.

public static Bounds union(Bounds b1, Bounds b2) {
    if (b1 == null)
        return b2;
    if (b2 == null)
        return b1;
    if (b1 == b2)
        return b1;
    if (b1.relations().containsAll(b2.relations()))
        return b1;
    if (b2.relations().containsAll(b1.relations()))
        return b2;
    Bounds ans = b1.clone();
    Set<Relation> diff = new HashSet<Relation>(b2.relations());
    // diff.removeAll(bounds.relations());
    for (Relation r : diff) ans.bound(r, b2.lowerBound(r), b2.upperBound(r));
    return ans;
}
Also used : Relation(kodkod.ast.Relation) Bounds(kodkod.instance.Bounds) HashSet(java.util.HashSet)

Aggregations

Relation (kodkod.ast.Relation)87 Bounds (kodkod.instance.Bounds)49 Formula (kodkod.ast.Formula)45 TupleFactory (kodkod.instance.TupleFactory)45 Universe (kodkod.instance.Universe)45 TupleSet (kodkod.instance.TupleSet)43 Solution (kodkod.engine.Solution)30 Expression (kodkod.ast.Expression)26 IntExpression (kodkod.ast.IntExpression)24 Solver (kodkod.engine.Solver)24 ArrayList (java.util.ArrayList)23 Variable (kodkod.ast.Variable)23 Instance (kodkod.instance.Instance)15 Decls (kodkod.ast.Decls)13 Evaluator (kodkod.engine.Evaluator)9 Tuple (kodkod.instance.Tuple)8 IntSet (kodkod.util.ints.IntSet)7 BinaryExpression (kodkod.ast.BinaryExpression)6 Decl (kodkod.ast.Decl)6 LinkedHashSet (java.util.LinkedHashSet)4