Search in sources :

Example 1 with IntIterator

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

the class SymmetryBreaker method breakTotalOrder.

/**
 * If possible, breaks symmetry on the given total ordering predicate and
 * returns a formula f such that the meaning of total 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
 * total.first, total.last, and total.ordered have the same upper bound, which,
 * when cross-multiplied with itself gives the upper bound of total.relation.
 * Assuming that this is the case, we then break symmetry on total.relation,
 * total.first, total.last, and total.ordered 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 total.ordered is removed from this.symmetries.
 * </p>
 *
 * @return null if symmetry cannot be broken on total; otherwise returns a
 *         formula f such that the meaning of total 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 desribed in
 *          {@linkplain #breakMatrixSymmetries(Map, boolean)} iff total.first,
 *          total.last, and total.ordered have the same upper bound, which, when
 *          cross-multiplied with itself gives the upper bound of total.relation
 * @see #breakMatrixSymmetries(Map,boolean)
 */
private final Formula breakTotalOrder(RelationPredicate.TotalOrdering total, boolean aggressive) {
    final Relation first = total.first(), last = total.last(), ordered = total.ordered(), relation = total.relation();
    final IntSet domain = bounds.upperBound(ordered).indexView();
    if (symmetricColumnPartitions(ordered) != null && bounds.upperBound(first).indexView().contains(domain.min()) && bounds.upperBound(last).indexView().contains(domain.max())) {
        // construct the natural ordering that corresponds to the ordering
        // of the atoms in the universe
        final IntSet ordering = Ints.bestSet(usize * usize);
        int prev = domain.min();
        for (IntIterator atoms = domain.iterator(prev + 1, usize); atoms.hasNext(); ) {
            int next = atoms.next();
            ordering.add(prev * usize + next);
            prev = next;
        }
        if (ordering.containsAll(bounds.lowerBound(relation).indexView()) && bounds.upperBound(relation).indexView().containsAll(ordering)) {
            // remove the ordered partition from the set of symmetric
            // partitions
            removePartition(domain.min());
            final TupleFactory f = bounds.universe().factory();
            if (aggressive) {
                bounds.boundExactly(first, f.setOf(f.tuple(1, domain.min())));
                bounds.boundExactly(last, f.setOf(f.tuple(1, domain.max())));
                bounds.boundExactly(ordered, bounds.upperBound(total.ordered()));
                bounds.boundExactly(relation, f.setOf(2, ordering));
                return Formula.TRUE;
            } else {
                final Relation firstConst = Relation.unary("SYM_BREAK_CONST_" + first.name());
                final Relation lastConst = Relation.unary("SYM_BREAK_CONST_" + last.name());
                final Relation ordConst = Relation.unary("SYM_BREAK_CONST_" + ordered.name());
                final Relation relConst = Relation.binary("SYM_BREAK_CONST_" + relation.name());
                bounds.boundExactly(firstConst, f.setOf(f.tuple(1, domain.min())));
                bounds.boundExactly(lastConst, f.setOf(f.tuple(1, domain.max())));
                bounds.boundExactly(ordConst, bounds.upperBound(total.ordered()));
                bounds.boundExactly(relConst, f.setOf(2, ordering));
                return Formula.and(first.eq(firstConst), last.eq(lastConst), ordered.eq(ordConst), relation.eq(relConst));
            // return first.eq(firstConst).and(last.eq(lastConst)).and(
            // ordered.eq(ordConst)).and( relation.eq(relConst));
            }
        }
    }
    return null;
}
Also used : Relation(kodkod.ast.Relation) IntIterator(kodkod.util.ints.IntIterator) IntSet(kodkod.util.ints.IntSet) TupleFactory(kodkod.instance.TupleFactory)

Example 2 with IntIterator

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

the class SymmetryBreaker method generateSBP.

/**
 * Generates a lex leader symmetry breaking predicate for this.symmetries (if
 * any), using the specified leaf interpreter and options.symmetryBreaking. It
 * also invokes options.reporter().generatingSBP() if a non-constant predicate
 * is generated.
 *
 * @requires interpreter.relations in this.bounds.relations
 * @ensures options.reporter().generatingSBP() if a non-constant predicate is
 *          generated.
 * @return a symmetry breaking predicate for this.symmetries
 */
public final BooleanValue generateSBP(LeafInterpreter interpreter, Options options) {
    final int predLength = options.symmetryBreaking();
    if (symmetries.isEmpty() || predLength == 0)
        return BooleanConstant.TRUE;
    options.reporter().generatingSBP();
    final List<RelationParts> relParts = relParts();
    final BooleanFactory factory = interpreter.factory();
    final BooleanAccumulator sbp = BooleanAccumulator.treeGate(Operator.AND);
    final List<BooleanValue> original = new ArrayList<BooleanValue>(predLength);
    final List<BooleanValue> permuted = new ArrayList<BooleanValue>(predLength);
    for (IntSet sym : symmetries) {
        IntIterator indeces = sym.iterator();
        for (int prevIndex = indeces.next(); indeces.hasNext(); ) {
            int curIndex = indeces.next();
            for (Iterator<RelationParts> rIter = relParts.iterator(); rIter.hasNext() && original.size() < predLength; ) {
                RelationParts rparts = rIter.next();
                Relation r = rparts.relation;
                if (!rparts.representatives.contains(sym.min()))
                    // r does not range over sym
                    continue;
                BooleanMatrix m = interpreter.interpret(r);
                for (IndexedEntry<BooleanValue> entry : m) {
                    int permIndex = permutation(r.arity(), entry.index(), prevIndex, curIndex);
                    BooleanValue permValue = m.get(permIndex);
                    if (permIndex == entry.index() || atSameIndex(original, permValue, permuted, entry.value()))
                        continue;
                    original.add(entry.value());
                    permuted.add(permValue);
                }
            }
            sbp.add(leq(factory, original, permuted));
            original.clear();
            permuted.clear();
            prevIndex = curIndex;
        }
    }
    // no symmetries left to break (this is
    symmetries.clear();
    // conservative)
    return factory.accumulate(sbp);
}
Also used : IntIterator(kodkod.util.ints.IntIterator) IntSet(kodkod.util.ints.IntSet) ArrayList(java.util.ArrayList) BooleanAccumulator(kodkod.engine.bool.BooleanAccumulator) BooleanMatrix(kodkod.engine.bool.BooleanMatrix) BooleanFactory(kodkod.engine.bool.BooleanFactory) Relation(kodkod.ast.Relation) BooleanValue(kodkod.engine.bool.BooleanValue)

Example 3 with IntIterator

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

the class SymmetryBreaker method symmetricColumnPartitions.

/**
 * If all columns of the upper bound of r are symmetric partitions, those
 * partitions are returned. Otherwise null is returned.
 *
 * @return (all i: [0..r.arity) | some s: symmetries[int] |
 *         bounds.upperBound[r].project(i).indexView() = s) => {colParts:
 *         [0..r.arity)->IntSet | all i: [0..r.arity()) | colParts[i] =
 *         bounds.upperBound[r].project(i).indexView() }, null
 */
private final IntSet[] symmetricColumnPartitions(Relation r) {
    final IntSet upper = bounds.upperBound(r).indexView();
    if (upper.isEmpty())
        return null;
    final IntSet[] colParts = new IntSet[r.arity()];
    for (int i = r.arity() - 1, min = upper.min(); i >= 0; i--, min /= usize) {
        for (IntSet part : symmetries) {
            if (part.contains(min % usize)) {
                colParts[i] = part;
                break;
            }
        }
        if (colParts[i] == null)
            return null;
    }
    for (IntIterator tuples = upper.iterator(); tuples.hasNext(); ) {
        for (int i = r.arity() - 1, tuple = tuples.next(); i >= 0; i--, tuple /= usize) {
            if (!colParts[i].contains(tuple % usize))
                return null;
        }
    }
    return colParts;
}
Also used : IntIterator(kodkod.util.ints.IntIterator) IntSet(kodkod.util.ints.IntSet)

Example 4 with IntIterator

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

the class SymmetryBreaker method relParts.

/**
 * Returns a list of RelationParts that map each non-constant r in
 * this.bounds.relations to the representatives of the sets from this.symmetries
 * contained in the upper bound of r. The entries are sorted by relations'
 * arities and names.
 *
 * @return a list of RelationParts that contains an entry for each non-constant
 *         r in this.bounds.relations and the representatives of sets from
 *         this.symmetries contained in the upper bound of r.
 */
private List<RelationParts> relParts() {
    final List<RelationParts> relParts = new ArrayList<RelationParts>(bounds.relations().size());
    for (Relation r : bounds.relations()) {
        IntSet upper = bounds.upperBound(r).indexView();
        if (upper.size() == bounds.lowerBound(r).size())
            // skip constant relation
            continue;
        IntSet reps = Ints.bestSet(usize);
        for (IntIterator tuples = upper.iterator(); tuples.hasNext(); ) {
            for (int tIndex = tuples.next(), i = r.arity(); i > 0; i--, tIndex /= usize) {
                for (IntSet symm : symmetries) {
                    if (symm.contains(tIndex % usize)) {
                        reps.add(symm.min());
                        break;
                    }
                }
            }
        }
        relParts.add(new RelationParts(r, reps));
    }
    final Comparator<RelationParts> cmp = new Comparator<RelationParts>() {

        @Override
        public int compare(RelationParts o1, RelationParts o2) {
            final int acmp = o1.relation.arity() - o2.relation.arity();
            return acmp != 0 ? acmp : String.valueOf(o1.relation.name()).compareTo(String.valueOf(o2.relation.name()));
        }
    };
    Collections.sort(relParts, cmp);
    return relParts;
}
Also used : Relation(kodkod.ast.Relation) IntIterator(kodkod.util.ints.IntIterator) IntSet(kodkod.util.ints.IntSet) ArrayList(java.util.ArrayList) Comparator(java.util.Comparator)

Example 5 with IntIterator

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

the class Translation method interpret.

public Instance interpret(Bounds bounds) {
    final SATSolver solver = cnf();
    final Instance instance = new Instance(bounds.universe());
    final TupleFactory f = bounds.universe().factory();
    for (IndexedEntry<TupleSet> entry : bounds.intBounds()) {
        instance.add(entry.index(), entry.value());
    }
    for (Relation r : bounds.relations()) {
        // if (bnds != bounds && bnds.findRelByName(r.name()) == null)
        // continue;
        TupleSet lower = bounds.lowerBound(r);
        IntSet indices = Ints.bestSet(lower.capacity());
        indices.addAll(lower.indexView());
        IntSet vars = primaryVariables(r);
        if (!vars.isEmpty()) {
            // System.out.println(r + ": [" + vars.min() + ", " + vars.max()
            // + "]");
            int lit = vars.min();
            for (IntIterator iter = bounds.upperBound(r).indexView().iterator(); iter.hasNext(); ) {
                final int index = iter.next();
                if (!indices.contains(index) && solver.valueOf(lit++))
                    indices.add(index);
            }
        }
        instance.add(r, f.setOf(r.arity(), indices));
    }
    return instance;
}
Also used : SATSolver(kodkod.engine.satlab.SATSolver) TupleSet(kodkod.instance.TupleSet) Relation(kodkod.ast.Relation) IntIterator(kodkod.util.ints.IntIterator) Instance(kodkod.instance.Instance) IntSet(kodkod.util.ints.IntSet) TupleFactory(kodkod.instance.TupleFactory)

Aggregations

IntIterator (kodkod.util.ints.IntIterator)27 IntSet (kodkod.util.ints.IntSet)21 IntBitSet (kodkod.util.ints.IntBitSet)7 Relation (kodkod.ast.Relation)5 Clause (kodkod.engine.satlab.Clause)5 BooleanMatrix (kodkod.engine.bool.BooleanMatrix)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 BooleanFactory (kodkod.engine.bool.BooleanFactory)2 BooleanValue (kodkod.engine.bool.BooleanValue)2 TupleFactory (kodkod.instance.TupleFactory)2 TupleSet (kodkod.instance.TupleSet)2 IntTreeSet (kodkod.util.ints.IntTreeSet)2 Comparator (java.util.Comparator)1 LinkedList (java.util.LinkedList)1 Map (java.util.Map)1 BooleanAccumulator (kodkod.engine.bool.BooleanAccumulator)1 Int (kodkod.engine.bool.Int)1 SATSolver (kodkod.engine.satlab.SATSolver)1 Instance (kodkod.instance.Instance)1