Search in sources :

Example 26 with IntSet

use of kodkod.util.ints.IntSet in project org.alloytools.alloy by AlloyTools.

the class SymmetryDetector method computePartitions.

/**
 * Partitions this.bounds.universe into sets of equivalent atoms.
 *
 * @ensures all disj s, q: this.parts'[int] | some s.ints && some q.ints && (no
 *          s.ints & q.ints) && this.parts'[int].ints =
 *          [0..this.bounds.universe.size()) && (all ts:
 *          this.bounds.lowerBound[Relation] + this.bounds.upperBound[Relation]
 *          | all s: this.parts'[int] | all a1, a2:
 *          this.bounds.universe.atoms[s.ints] | all t1, t2: ts.tuples |
 *          t1.atoms[0] = a1 && t2.atoms[0] = a2 => t1.atoms[1..ts.arity) =
 *          t1.atoms[1..ts.arity) || t1.atoms[1..ts.arity) = a1 &&
 *          t1.atoms[1..ts.arity) = a2)
 */
private final void computePartitions() {
    if (usize == 1)
        // nothing more to do
        return;
    final Map<IntSet, IntSet> range2domain = new HashMap<IntSet, IntSet>((usize * 2) / 3);
    // refine the partitions based on the bounds for each integer
    for (IntIterator iter = bounds.ints().iterator(); iter.hasNext(); ) {
        TupleSet exact = bounds.exactBound(iter.next());
        refinePartitions(exact.indexView(), 1, range2domain);
    }
    // relation
    for (TupleSet s : sort(bounds)) {
        if (parts.size() == usize)
            return;
        refinePartitions(s.indexView(), s.arity(), range2domain);
    }
}
Also used : TupleSet(kodkod.instance.TupleSet) IntIterator(kodkod.util.ints.IntIterator) HashMap(java.util.HashMap) IntSet(kodkod.util.ints.IntSet)

Example 27 with IntSet

use of kodkod.util.ints.IntSet in project org.alloytools.alloy by AlloyTools.

the class SymmetryDetector method refinePartitions.

/**
 * Refines the atomic partitions this.parts based on the contents of the given
 * set.
 *
 * @requires all disj s, q: this.parts[int] | some s.ints && some q.ints && (no
 *           s.ints & q.ints) && this.parts[int].ints =
 *           [0..this.bounds.universe.size())
 * @ensures all disj s, q: this.parts'[int] | some s.ints && some q.ints && (no
 *          s.ints & q.ints) && this.parts'[int].ints =
 *          [0..this.bounds.universe.size()) && (all i: [0..this.parts'.size())
 *          | this.parts'[i].ints in set.ints || no this.parts'[i].ints &
 *          set.ints)
 */
private void refinePartitions(IntSet set) {
    for (ListIterator<IntSet> partsIter = parts.listIterator(); partsIter.hasNext(); ) {
        IntSet part = partsIter.next();
        IntSet intersection = Ints.bestSet(part.min(), part.max());
        intersection.addAll(part);
        intersection.retainAll(set);
        if (!intersection.isEmpty() && intersection.size() < part.size()) {
            part.removeAll(intersection);
            partsIter.add(intersection);
        }
    }
}
Also used : IntSet(kodkod.util.ints.IntSet)

Example 28 with IntSet

use of kodkod.util.ints.IntSet 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 29 with IntSet

use of kodkod.util.ints.IntSet 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 30 with IntSet

use of kodkod.util.ints.IntSet 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)

Aggregations

IntSet (kodkod.util.ints.IntSet)45 IntIterator (kodkod.util.ints.IntIterator)21 IntBitSet (kodkod.util.ints.IntBitSet)9 IntTreeSet (kodkod.util.ints.IntTreeSet)8 Relation (kodkod.ast.Relation)7 Clause (kodkod.engine.satlab.Clause)6 TupleSet (kodkod.instance.TupleSet)6 BooleanMatrix (kodkod.engine.bool.BooleanMatrix)5 Map (java.util.Map)4 Set (java.util.Set)4 LinkedHashMap (java.util.LinkedHashMap)3 LinkedHashSet (java.util.LinkedHashSet)3 Formula (kodkod.ast.Formula)3 Node (kodkod.ast.Node)3 BooleanFactory (kodkod.engine.bool.BooleanFactory)3 RecordFilter (kodkod.engine.fol2sat.RecordFilter)3 TranslationRecord (kodkod.engine.fol2sat.TranslationRecord)3 Bounds (kodkod.instance.Bounds)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2