use of edu.mit.csail.sdg.ast.Sig in project org.alloytools.alloy by AlloyTools.
the class SimInstance method validate.
/**
* Checks whether this instance satisfies every fact defined in the given model.
*
* @param world - this must be the root of the Alloy model
* @return an empty String if yes, nonempty String if no
*/
public String validate(Module world) {
try {
for (Sig s : world.getAllReachableSigs()) if (!s.builtin) {
if (s.isLone != null && !(visit(s).longsize() <= 1))
return "There can be at most one " + s;
if (s.isOne != null && !(visit(s).longsize() == 1))
return "There must be exactly one " + s;
if (s.isSome != null && !(visit(s).longsize() >= 1))
return "There must be at least one " + s;
if (s instanceof SubsetSig) {
SubsetSig p = (SubsetSig) s;
Expr sum = null;
for (Sig par : p.parents) sum = par.plus(sum);
if (p.exact) {
if (!equal(s, sum))
return "Sig " + s + " must be equal to the union of its parents " + p.parents;
} else {
if (!isIn(s, sum))
return "Sig " + s + " must be equal or subset of its parents " + p.parents;
}
} else if (s != Sig.UNIV && s != Sig.NONE) {
PrimSig p = (PrimSig) s;
if (!isIn(s, p.parent))
return "Sig " + s + " must be equal or subset of its parent " + p.parent;
}
if (s.isAbstract != null) {
Expr sum = null;
for (Sig x : ((PrimSig) s).children()) sum = x.plus(sum);
if (sum != null && !equal(s, sum))
return "Abstract sig " + s + " must be equal to the union of its subsigs";
}
for (Decl d : s.getFieldDecls()) for (ExprHasName f : d.names) if (!((Field) f).defined) {
if (!cform(s.decl.get().join(f).in(d.expr).forAll(s.decl))) {
return "Field " + f + " violated its bound: " + visit((Field) f) + "\n" + d.expr;
}
SimTupleset setS = visit(s);
SimTupleset setF = visit((Field) f);
for (SimAtom x : setF.getAllAtoms(0)) if (!setS.has(x))
return "Field " + f + " first column has extra atom: " + setF + " not in " + setS;
}
for (Decl d : s.getFieldDecls()) {
if (d.disjoint != null && d.names.size() > 0) {
if (!cform(ExprList.makeDISJOINT(null, null, d.names)))
return "Fields must be disjoint.";
}
if (d.disjoint2 != null)
for (ExprHasName f : d.names) {
Decl that = s.oneOf("that");
Expr formula = s.decl.get().equal(that.get()).not().implies(s.decl.get().join(f).intersect(that.get().join(f)).no());
if (!cform(formula.forAll(that).forAll(s.decl)))
return "Fields must be disjoint.";
}
}
for (Expr f : s.getFacts()) {
if (!cform(f.forAll(s.decl))) {
f = f.deNOP();
if (f instanceof ExprUnary) {
ExprUnary u = (ExprUnary) f;
f = u.sub.deNOP();
if (f instanceof ExprBinary) {
ExprBinary b = (ExprBinary) f;
if (b.op == ExprBinary.Op.JOIN && b.left.isSame(s.decl.get()) && b.right.deNOP() instanceof Field) {
String n = ((Field) (b.right.deNOP())).label;
if (u.op == ExprUnary.Op.SOME)
return "The " + n + " cannot be empty.";
if (u.op == ExprUnary.Op.LONE)
return "The " + n + " cannot have more than one value.";
if (u.op == ExprUnary.Op.ONE)
return "The " + n + " must have exactly one value.";
if (u.op == ExprUnary.Op.NO)
return "The " + n + " must be empty.";
}
}
}
return "Cannot violate a consistency constraint";
}
}
}
for (Module m : world.getAllReachableModules()) for (Pair<String, Expr> f : m.getAllFacts()) if (!cform(f.b)) {
String err = f.a;
if (err.matches("^fact\\$[0-9][0-9]*"))
err = f.b.toString();
if (err.length() >= 2 && err.startsWith("\"") && err.endsWith("\""))
err = err.substring(1, err.length() - 1);
return "Violation: " + err;
}
return "";
} catch (Err ex) {
return "An internal error has occured:\n" + ex.dump();
}
}
use of edu.mit.csail.sdg.ast.Sig 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 edu.mit.csail.sdg.ast.Sig in project org.alloytools.alloy by AlloyTools.
the class CompModule method getRawQS.
/**
* Lookup a fully-qualified Sig/Func/Assertion from the current module; it skips
* PARAMs.
*/
private List<Object> getRawQS(final int r, String name) {
// (r&1)!=0 => Sig, (r&2) != 0 => assertion, (r&4)!=0 => Func
List<Object> ans = new ArrayList<Object>();
CompModule u = this;
if (name.startsWith("this/"))
name = name.substring(5);
for (int level = 0; ; level++) {
int i = name.indexOf('/');
if (i < 0) {
if ((r & 1) != 0) {
Sig x = u.sigs.get(name);
if (x != null)
if (level == 0 || x.isPrivate == null)
ans.add(x);
}
if ((r & 2) != 0) {
Expr x = u.asserts.get(name);
if (x != null)
ans.add(x);
}
if ((r & 4) != 0) {
ArrayList<Func> x = u.funcs.get(name);
if (x != null)
for (Func y : x) if (level == 0 || y.isPrivate == null)
ans.add(y);
}
if (ans.size() == 0)
// If nothing at this
return u.getRawNQS(this, r, name);
// from this module
return ans;
}
String alias = name.substring(0, i);
Open uu = u.opens.get(alias);
if (uu == null || uu.realModule == null)
// may happen during the initial "module"
return ans;
if (level > 0 && uu.isPrivate)
// that means the module is imported privately
return ans;
u = uu.realModule;
name = name.substring(i + 1);
}
}
use of edu.mit.csail.sdg.ast.Sig in project org.alloytools.alloy by AlloyTools.
the class CompModule method resolveMeta.
// ============================================================================================================================//
private static void resolveMeta(final CompModule root) throws Err {
// Now, add the meta sigs and fields if needed
Map<Sig, PrimSig> sig2meta = new LinkedHashMap<Sig, PrimSig>();
Map<Field, PrimSig> field2meta = new LinkedHashMap<Field, PrimSig>();
boolean hasMetaSig = false, hasMetaField = false;
root.new2old.put(root.metaSig, root.metaSig);
root.sigs.put(base(root.metaSig), root.metaSig);
root.new2old.put(root.metaField, root.metaField);
root.sigs.put(base(root.metaField), root.metaField);
for (CompModule m : root.allModules) for (Sig s : new ArrayList<Sig>(m.sigs.values())) if (m != root || (s != root.metaSig && s != root.metaField)) {
PrimSig ka = new PrimSig(s.label + "$", root.metaSig, Attr.ONE, PRIVATE.makenull(s.isPrivate), Attr.META);
sig2meta.put(s, ka);
ka.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "value", s);
m.new2old.put(ka, ka);
m.sigs.put(base(ka), ka);
hasMetaSig = true;
Expr allfields = ExprConstant.EMPTYNESS;
for (Field field : s.getFields()) {
Pos priv = field.isPrivate;
if (priv == null)
priv = s.isPrivate;
PrimSig kb = new PrimSig(s.label + "$" + field.label, root.metaField, Attr.ONE, PRIVATE.makenull(priv), Attr.META);
field2meta.put(field, kb);
m.new2old.put(kb, kb);
m.sigs.put(base(kb), kb);
hasMetaField = true;
kb.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "value", field);
if (allfields == ExprConstant.EMPTYNESS)
allfields = kb;
else
allfields = allfields.plus(kb);
}
ka.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "fields", allfields);
}
for (Map.Entry<Sig, PrimSig> e : sig2meta.entrySet()) {
Expr expr = null;
if ((e.getKey()) instanceof PrimSig) {
PrimSig a = (PrimSig) (e.getKey());
if (a.parent != null && a.parent != UNIV)
expr = sig2meta.get(a.parent);
}
e.getValue().addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "parent", (expr == null ? ExprConstant.EMPTYNESS : expr));
}
for (Map.Entry<Sig, PrimSig> e : sig2meta.entrySet()) {
Sig s = e.getKey();
PrimSig s2 = e.getValue();
Expr allfields = ExprConstant.EMPTYNESS;
for (Field f : s.getFields()) {
PrimSig metaF = field2meta.get(f);
if (allfields == ExprConstant.EMPTYNESS)
allfields = metaF;
else
allfields = allfields.plus(metaF);
}
if (s instanceof PrimSig)
for (Sig c : (((PrimSig) s).descendents())) for (Field f : c.getFields()) {
PrimSig metaF = field2meta.get(f);
if (allfields == ExprConstant.EMPTYNESS)
allfields = metaF;
else
allfields = allfields.plus(metaF);
}
s2.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "subfields", allfields);
}
if (hasMetaSig == false)
root.facts.add(new Pair<String, Expr>("sig$fact", root.metaSig.no().and(root.metaField.no())));
else if (hasMetaField == false)
root.facts.add(new Pair<String, Expr>("sig$fact", root.metaField.no()));
}
use of edu.mit.csail.sdg.ast.Sig in project org.alloytools.alloy by AlloyTools.
the class BoundsComputer method allocateSubsetSig.
// ==============================================================================================================//
/**
* Allocate relations for SubsetSig top-down.
*/
private Expression allocateSubsetSig(SubsetSig sig) throws Err {
// We must not visit the same SubsetSig more than once, so if we've been
// here already, then return the old value right away
Expression sum = sol.a2k(sig);
if (sum != null && sum != Expression.NONE)
return sum;
// Recursively form the union of all parent expressions
TupleSet ts = factory.noneOf(1);
for (Sig parent : sig.parents) {
Expression p = (parent instanceof PrimSig) ? sol.a2k(parent) : allocateSubsetSig((SubsetSig) parent);
ts.addAll(sol.query(true, p, false));
if (sum == null)
sum = p;
else
sum = sum.union(p);
}
// If subset is exact, then just use the "sum" as is
if (sig.exact) {
sol.addSig(sig, sum);
return sum;
}
// Allocate a relation for this subset sig, then bound it
rep.bound("Sig " + sig + " in " + ts + "\n");
Relation r = sol.addRel(sig.label, null, ts);
sol.addSig(sig, r);
// Add a constraint that it is INDEED a subset of the union of its
// parents
sol.addFormula(r.in(sum), sig.isSubset);
return r;
}
Aggregations