use of kodkod.instance.Tuple in project org.alloytools.alloy by AlloyTools.
the class BenchmarkSymmStats method toNauty.
private static void toNauty(Bounds bounds, PrintStream stream) {
int size = bounds.universe().size() + bounds.ints().size();
for (Relation r : bounds.relations()) {
final int upsize = bounds.upperBound(r).size(), lowsize = bounds.lowerBound(r).size();
size += (upsize == lowsize ? upsize : upsize + lowsize) * r.arity();
}
stream.println("n=" + size + " $0 *=13 k = 0 " + size + " +d -a -m g");
int v = bounds.universe().size();
final IntVector vec = new ArrayIntVector();
vec.add(v);
for (Relation r : bounds.relations()) {
final int arity = r.arity();
final TupleSet up = bounds.upperBound(r), down = bounds.lowerBound(r);
final TupleSet[] sets = up.size() == down.size() || down.size() == 0 ? new TupleSet[] { up } : new TupleSet[] { down, up };
for (TupleSet s : sets) {
for (Tuple t : s) {
for (int i = 0, max = arity - 1; i < max; i++) {
stream.println(v + " : " + (v + 1) + " " + t.atomIndex(i) + ";");
v++;
}
stream.println(v + " : " + t.atomIndex(arity - 1) + ";");
v++;
}
vec.add(v);
}
}
for (TupleSet s : bounds.intBounds().values()) {
stream.println(v + " : " + s.iterator().next().atomIndex(0) + ";");
v++;
vec.add(v);
}
// stream.println(".");
stream.print("f = [ 0:" + (vec.get(0) - 1));
for (int i = 1; i < vec.size(); i++) {
stream.print(" | " + vec.get(i - 1) + ":" + (vec.get(i) - 1));
}
stream.println(" ]");
stream.println("x");
// stream.println("o");
stream.println("q");
}
use of kodkod.instance.Tuple in project org.alloytools.alloy by AlloyTools.
the class A4Solution method solve.
// ===================================================================================================//
/**
* Solve for the solution if not solved already; if cmd==null, we will simply
* use the lowerbound of each relation as its value.
*/
A4Solution solve(final A4Reporter rep, Command cmd, Simplifier simp, boolean tryBookExamples) throws Err, IOException {
// If already solved, then return this object as is
if (solved)
return this;
// the lower bound of each relation
if (cmd == null) {
Instance inst = new Instance(bounds.universe());
for (int max = max(), i = min(); i <= max; i++) {
Tuple it = factory.tuple("" + i);
inst.add(i, factory.range(it, it));
}
for (Relation r : bounds.relations()) inst.add(r, bounds.lowerBound(r));
eval = new Evaluator(inst, solver.options());
rename(this, null, null, new UniqueNameGenerator());
solved();
return this;
}
// Otherwise, prepare to do the solve...
final A4Options opt = originalOptions;
long time = System.currentTimeMillis();
rep.debug("Simplifying the bounds...\n");
if (opt.inferPartialInstance && simp != null && formulas.size() > 0 && !simp.simplify(rep, this, formulas))
addFormula(Formula.FALSE, Pos.UNKNOWN);
rep.translate(opt.solver.id(), bitwidth, maxseq, solver.options().skolemDepth(), solver.options().symmetryBreaking());
Formula fgoal = Formula.and(formulas);
rep.debug("Generating the solution...\n");
kEnumerator = null;
Solution sol = null;
final Reporter oldReporter = solver.options().reporter();
final boolean[] solved = new boolean[] { true };
solver.options().setReporter(new // Set up a
AbstractReporter() {
// reporter to
// catch the
// type+pos of
// skolems
@Override
public void skolemizing(Decl decl, Relation skolem, List<Decl> predecl) {
try {
Type t = kv2typepos(decl.variable()).a;
if (t == Type.EMPTY)
return;
for (int i = (predecl == null ? -1 : predecl.size() - 1); i >= 0; i--) {
Type pp = kv2typepos(predecl.get(i).variable()).a;
if (pp == Type.EMPTY)
return;
t = pp.product(t);
}
kr2type(skolem, t);
}// Exception here is not fatal
catch (Throwable ex) {
}
}
@Override
public void solvingCNF(int primaryVars, int vars, int clauses) {
if (solved[0])
return;
else
// initially solved[0] is true, so we
solved[0] = true;
// won't report the # of vars/clauses
if (rep != null)
rep.solve(primaryVars, vars, clauses);
}
});
if (!opt.solver.equals(SatSolver.CNF) && !opt.solver.equals(SatSolver.KK) && tryBookExamples) {
// try
// book
// examples
A4Reporter r = AlloyCore.isDebug() ? rep : null;
try {
sol = BookExamples.trial(r, this, fgoal, solver, cmd.check);
} catch (Throwable ex) {
sol = null;
}
}
// this allows the reporter to report the # of
solved[0] = false;
// vars/clauses
for (Relation r : bounds.relations()) {
formulas.add(r.eq(r));
}
// Without this, kodkod refuses to grow unmentioned relations
fgoal = Formula.and(formulas);
// Now pick the solver and solve it!
if (opt.solver.equals(SatSolver.KK)) {
File tmpCNF = File.createTempFile("tmp", ".java", new File(opt.tempDirectory));
String out = tmpCNF.getAbsolutePath();
Util.writeAll(out, debugExtractKInput());
rep.resultCNF(out);
return null;
}
if (opt.solver.equals(SatSolver.CNF)) {
File tmpCNF = File.createTempFile("tmp", ".cnf", new File(opt.tempDirectory));
String out = tmpCNF.getAbsolutePath();
solver.options().setSolver(WriteCNF.factory(out));
try {
sol = solver.solve(fgoal, bounds);
} catch (WriteCNF.WriteCNFCompleted ex) {
rep.resultCNF(out);
return null;
}
// The formula is trivial (otherwise, it would have thrown an
// exception)
// Since the user wants it in CNF format, we manually generate a
// trivially satisfiable (or unsatisfiable) CNF file.
Util.writeAll(out, sol.instance() != null ? "p cnf 1 1\n1 0\n" : "p cnf 1 2\n1 0\n-1 0\n");
rep.resultCNF(out);
return null;
}
if (!solver.options().solver().incremental()) /*
* || solver.options().solver()==SATFactory. ZChaffMincost
*/
{
if (sol == null)
sol = solver.solve(fgoal, bounds);
} else {
kEnumerator = new Peeker<Solution>(solver.solveAll(fgoal, bounds));
if (sol == null)
sol = kEnumerator.next();
}
if (!solved[0])
rep.solve(0, 0, 0);
final Instance inst = sol.instance();
// To ensure no more output during SolutionEnumeration
solver.options().setReporter(oldReporter);
// If unsatisfiable, then retreive the unsat core if desired
if (inst == null && solver.options().solver() == SATFactory.MiniSatProver) {
try {
lCore = new LinkedHashSet<Node>();
Proof p = sol.proof();
if (sol.outcome() == UNSATISFIABLE) {
// only perform the minimization if it was UNSATISFIABLE,
// rather than TRIVIALLY_UNSATISFIABLE
int i = p.highLevelCore().size();
rep.minimizing(cmd, i);
if (opt.coreMinimization == 0)
try {
p.minimize(new RCEStrategy(p.log()));
} catch (Throwable ex) {
}
if (opt.coreMinimization == 1)
try {
p.minimize(new HybridStrategy(p.log()));
} catch (Throwable ex) {
}
rep.minimized(cmd, i, p.highLevelCore().size());
}
for (Iterator<TranslationRecord> it = p.core(); it.hasNext(); ) {
Object n = it.next().node();
if (n instanceof Formula)
lCore.add((Formula) n);
}
Map<Formula, Node> map = p.highLevelCore();
hCore = new LinkedHashSet<Node>(map.keySet());
hCore.addAll(map.values());
} catch (Throwable ex) {
lCore = hCore = null;
}
}
// If satisfiable, then add/rename the atoms and skolems
if (inst != null) {
eval = new Evaluator(inst, solver.options());
rename(this, null, null, new UniqueNameGenerator());
}
// report the result
solved();
time = System.currentTimeMillis() - time;
if (inst != null)
rep.resultSAT(cmd, time, this);
else
rep.resultUNSAT(cmd, time, this);
return this;
}
use of kodkod.instance.Tuple in project org.alloytools.alloy by AlloyTools.
the class A4Solution method rename.
/**
* Helper method that chooses a name for each atom based on its most specific
* sig; (external caller should call this method with s==null and nexts==null)
*/
private static void rename(A4Solution frame, PrimSig s, Map<Sig, List<Tuple>> nexts, UniqueNameGenerator un) throws Err {
if (s == null) {
for (ExprVar sk : frame.skolems) un.seen(sk.label);
// Store up the skolems
List<Object> skolems = new ArrayList<Object>();
for (Map.Entry<Relation, Type> e : frame.rel2type.entrySet()) {
Relation r = e.getKey();
if (!frame.eval.instance().contains(r))
continue;
Type t = e.getValue();
if (t.arity() > r.arity())
// Something is wrong; let's skip it
continue;
while (t.arity() < r.arity()) t = UNIV.type().product(t);
String n = Util.tail(r.name());
while (n.length() > 0 && n.charAt(0) == '$') n = n.substring(1);
skolems.add(n);
skolems.add(t);
skolems.add(r);
}
// Find all suitable "next" or "prev" relations
nexts = new LinkedHashMap<Sig, List<Tuple>>();
for (Sig sig : frame.sigs) for (Field f : sig.getFields()) if (f.label.compareToIgnoreCase("next") == 0) {
List<List<PrimSig>> fold = f.type().fold();
if (fold.size() == 1) {
List<PrimSig> t = fold.get(0);
if (t.size() == 3 && t.get(0).isOne != null && t.get(1) == t.get(2) && !nexts.containsKey(t.get(1))) {
TupleSet set = frame.eval.evaluate(frame.a2k(t.get(1)));
if (set.size() <= 1)
continue;
TupleSet next = frame.eval.evaluate(frame.a2k(t.get(0)).join(frame.a2k(f)));
List<Tuple> test = isOrder(next, set);
if (test != null)
nexts.put(t.get(1), test);
} else if (t.size() == 2 && t.get(0) == t.get(1) && !nexts.containsKey(t.get(0))) {
TupleSet set = frame.eval.evaluate(frame.a2k(t.get(0)));
if (set.size() <= 1)
continue;
TupleSet next = frame.eval.evaluate(frame.a2k(f));
List<Tuple> test = isOrder(next, set);
if (test != null)
nexts.put(t.get(1), test);
}
}
}
for (Sig sig : frame.sigs) for (Field f : sig.getFields()) if (f.label.compareToIgnoreCase("prev") == 0) {
List<List<PrimSig>> fold = f.type().fold();
if (fold.size() == 1) {
List<PrimSig> t = fold.get(0);
if (t.size() == 3 && t.get(0).isOne != null && t.get(1) == t.get(2) && !nexts.containsKey(t.get(1))) {
TupleSet set = frame.eval.evaluate(frame.a2k(t.get(1)));
if (set.size() <= 1)
continue;
TupleSet next = frame.eval.evaluate(frame.a2k(t.get(0)).join(frame.a2k(f)).transpose());
List<Tuple> test = isOrder(next, set);
if (test != null)
nexts.put(t.get(1), test);
} else if (t.size() == 2 && t.get(0) == t.get(1) && !nexts.containsKey(t.get(0))) {
TupleSet set = frame.eval.evaluate(frame.a2k(t.get(0)));
if (set.size() <= 1)
continue;
TupleSet next = frame.eval.evaluate(frame.a2k(f).transpose());
List<Tuple> test = isOrder(next, set);
if (test != null)
nexts.put(t.get(1), test);
}
}
}
// Assign atom->name and atom->MostSignificantSig
for (Tuple t : frame.eval.evaluate(Expression.INTS)) {
frame.atom2sig.put(t.atom(0), SIGINT);
}
for (Tuple t : frame.eval.evaluate(KK_SEQIDX)) {
frame.atom2sig.put(t.atom(0), SEQIDX);
}
for (Tuple t : frame.eval.evaluate(KK_STRING)) {
frame.atom2sig.put(t.atom(0), STRING);
}
for (Sig sig : frame.sigs) if (sig instanceof PrimSig && !sig.builtin && ((PrimSig) sig).isTopLevel())
rename(frame, (PrimSig) sig, nexts, un);
// These are redundant atoms that were not chosen to be in the final
// instance
int unused = 0;
for (Tuple tuple : frame.eval.evaluate(Expression.UNIV)) {
Object atom = tuple.atom(0);
if (!frame.atom2sig.containsKey(atom)) {
frame.atom2name.put(atom, "unused" + unused);
unused++;
}
}
// Add the skolems
for (int num = skolems.size(), i = 0; i < num - 2; i = i + 3) {
String n = (String) skolems.get(i);
while (n.length() > 0 && n.charAt(0) == '$') n = n.substring(1);
Type t = (Type) skolems.get(i + 1);
Relation r = (Relation) skolems.get(i + 2);
frame.addSkolem(un.make("$" + n), t, r);
}
return;
}
for (PrimSig c : s.children()) rename(frame, c, nexts, un);
String signame = un.make(s.label.startsWith("this/") ? s.label.substring(5) : s.label);
List<Tuple> list = new ArrayList<Tuple>();
for (Tuple t : frame.eval.evaluate(frame.a2k(s))) list.add(t);
List<Tuple> order = nexts.get(s);
if (order != null && order.size() == list.size() && order.containsAll(list)) {
list = order;
}
int i = 0;
for (Tuple t : list) {
if (frame.atom2sig.containsKey(t.atom(0)))
// This means one of the subsig has already claimed
continue;
// this atom.
String x = signame + "$" + i;
i++;
frame.atom2sig.put(t.atom(0), s);
frame.atom2name.put(t.atom(0), x);
ExprVar v = ExprVar.make(null, x, s.type());
TupleSet ts = t.universe().factory().range(t, t);
Relation r = Relation.unary(x);
frame.eval.instance().add(r, ts);
frame.a2k.put(v, r);
frame.atoms.add(v);
}
}
use of kodkod.instance.Tuple in project org.alloytools.alloy by AlloyTools.
the class A4Solution method isOrder.
// ===================================================================================================//
/**
* Helper method to determine if a given binary relation is a total order over a
* given unary relation.
*/
private static List<Tuple> isOrder(TupleSet b, TupleSet u) {
// Size check
final int n = u.size();
final List<Tuple> list = new ArrayList<Tuple>(n);
if (b.size() == 0 && n <= 1)
return list;
if (b.size() != n - 1)
return null;
// Find the starting element
Tuple head = null;
TupleSet right = b.project(1);
for (Tuple x : u) if (!right.contains(x)) {
head = x;
break;
}
if (head == null)
return null;
final TupleFactory f = head.universe().factory();
// Form the list
list.add(head);
while (true) {
// Find head.next
Tuple headnext = null;
for (Tuple x : b) if (x.atom(0) == head.atom(0)) {
headnext = f.tuple(x.atom(1));
break;
}
// exactly n elements (and all are in u), we're done
if (headnext == null)
return list.size() == n ? list : null;
// element not in u, then we declare failure
if (list.size() == n || !u.contains(headnext))
return null;
// Move on to the next step
head = headnext;
list.add(head);
}
}
use of kodkod.instance.Tuple in project org.alloytools.alloy by AlloyTools.
the class BoundsComputer method computeLowerBound.
// ==============================================================================================================//
/**
* Computes the lowerbound from bottom-up; it will also set a suitable initial
* value for each sig's upperbound. Precondition: sig is not a builtin sig
*/
private TupleSet computeLowerBound(List<Tuple> atoms, final PrimSig sig) throws Err {
int n = sc.sig2scope(sig);
TupleSet lower = factory.noneOf(1);
for (PrimSig c : sig.children()) lower.addAll(computeLowerBound(atoms, c));
TupleSet upper = lower.clone();
boolean isExact = sc.isExact(sig);
if (isExact || sig.isTopLevel())
for (n = n - upper.size(); n > 0; n--) {
Tuple atom = atoms.remove(atoms.size() - 1);
// atoms to the UPPERBOUND.
if (isExact)
lower.add(atom);
upper.add(atom);
}
lb.put(sig, lower);
ub.put(sig, upper);
return lower;
}
Aggregations