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