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;
}
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);
}
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;
}
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;
}
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;
}
Aggregations