use of kodkod.instance.TupleSet in project org.alloytools.alloy by AlloyTools.
the class DNACuts method bounds.
/**
* Returns the bounds for n links.
*
* @return bounds for n links.
*/
public Bounds bounds(int n) {
assert n >= 0;
final List<String> atoms = new ArrayList<String>(n + 4);
atoms.add("A");
atoms.add("T");
atoms.add("G");
atoms.add("C");
for (int i = 0; i < n; i++) {
atoms.add("Link" + i);
}
final Universe u = new Universe(atoms);
final TupleFactory f = u.factory();
final Bounds b = new Bounds(u);
final TupleSet bases = f.range(f.tuple("A"), f.tuple("C"));
final TupleSet links = f.range(f.tuple("Link0"), f.tuple("Link" + (n - 1)));
b.boundExactly(Base, bases);
b.boundExactly(Link, links);
b.bound(CutLink, links);
b.bound(JoinLink, links);
final TupleSet randomSequence = f.noneOf(2);
final Random r = new Random();
for (int i = 0; i < n; i++) {
randomSequence.add(f.tuple("Link" + i, u.atom(r.nextInt(4))));
}
b.boundExactly(base, randomSequence);
final TupleSet partners = f.noneOf(2);
partners.add(f.tuple("A", "T"));
partners.add(f.tuple("T", "A"));
partners.add(f.tuple("G", "C"));
partners.add(f.tuple("C", "G"));
b.boundExactly(partner, partners);
final TupleSet linkOrd = f.noneOf(2);
for (int i = 1; i < n; i++) {
linkOrd.add(f.tuple("Link" + (i - 1), "Link" + i));
}
b.boundExactly(next, linkOrd);
return b;
}
use of kodkod.instance.TupleSet in project org.alloytools.alloy by AlloyTools.
the class A4Solution method shrink.
/**
* Shrink the bounds for the given relation; throws an exception if the new
* bounds is not sameAs/subsetOf the old bounds.
*/
void shrink(Relation relation, TupleSet lowerBound, TupleSet upperBound) throws Err {
if (solved)
throw new ErrorFatal("Cannot shrink a Kodkod relation since solve() has completed.");
TupleSet oldL = bounds.lowerBound(relation);
TupleSet oldU = bounds.upperBound(relation);
if (oldU.containsAll(upperBound) && upperBound.containsAll(lowerBound) && lowerBound.containsAll(oldL)) {
bounds.bound(relation, lowerBound, upperBound);
} else {
throw new ErrorAPI("Inconsistent bounds shrinking on relation: " + relation);
}
}
use of kodkod.instance.TupleSet 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.TupleSet 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.TupleSet in project org.alloytools.alloy by AlloyTools.
the class A4TupleSet method plus.
/**
* Construct a new tupleset as the union of this and that; this and that must be
* come from the same solution. Note: if that==null, then the method returns
* this A4TupleSet as-is.
*/
public A4TupleSet plus(A4TupleSet that) throws ErrorAPI {
if (that == null)
return this;
if (sol != that.sol)
throw new ErrorAPI("A4TupleSet.plus() requires 2 tuplesets from the same A4Solution.");
if (arity() != that.arity())
throw new ErrorAPI("A4TupleSet.plus() requires 2 tuplesets with the same arity.");
if (this == that || tuples.size() == 0)
return that;
else if (that.tuples.size() == 0)
// special short cut
return this;
TupleSet ts = tuples.clone();
ts.addAll(that.tuples);
if (tuples.size() == ts.size())
return this;
if (that.tuples.size() == ts.size())
return that;
return new A4TupleSet(ts, sol);
}
Aggregations