use of edu.mit.csail.sdg.alloy4.A4Reporter in project org.alloytools.alloy by AlloyTools.
the class CompModule method resolveAll.
// ============================================================================================================================//
/**
* This method resolves the entire world; NOTE: if it throws an exception, it
* may leave the world in an inconsistent state!
*/
static CompModule resolveAll(final A4Reporter rep, final CompModule root) throws Err {
final List<ErrorWarning> warns = new ArrayList<ErrorWarning>();
for (CompModule m : root.getAllReachableModules()) root.allModules.add(m);
resolveParams(rep, root.allModules);
resolveModules(rep, root.allModules);
for (CompModule m : root.allModules) for (Sig s : m.sigs.values()) root.sig2module.put(s, m);
// Resolves SigAST -> Sig, and topologically sort the sigs into the
// "sorted" array
root.new2old.put(UNIV, UNIV);
root.new2old.put(SIGINT, SIGINT);
root.new2old.put(SEQIDX, SEQIDX);
root.new2old.put(STRING, STRING);
root.new2old.put(NONE, NONE);
HashSet<Object> topo = new HashSet<Object>();
for (CompModule m : root.allModules) for (Sig s : m.sigs.values()) resolveSig(root, topo, s);
// (since fields in subsigs are allowed to refer to parent's fields)
for (Sig oldS : root.new2old.keySet()) resolveFieldDecl(root, rep, oldS, warns, false);
// Typecheck the function declarations
JoinableList<Err> errors = new JoinableList<Err>();
for (CompModule x : root.allModules) errors = x.resolveFuncDecls(rep, errors, warns);
if (!errors.isEmpty())
throw errors.pick();
// Typecheck the defined fields
for (Sig oldS : root.new2old.keySet()) resolveFieldDecl(root, rep, oldS, warns, true);
if (Version.experimental && root.seenDollar)
resolveMeta(root);
// Reject name clash
rejectNameClash(root.allModules);
// to function declarations)
for (CompModule x : root.allModules) {
errors = x.resolveFuncBody(rep, errors, warns);
errors = x.resolveAssertions(rep, errors, warns);
errors = x.resolveFacts(root, rep, errors, warns);
// root module's list of exact sigs
for (String n : x.exactParams) {
Sig sig = x.params.get(n);
if (sig != null)
root.exactSigs.add(sig);
}
}
if (!errors.isEmpty())
throw errors.pick();
// Typecheck the run/check commands (which can refer to function bodies
// and assertions)
root.resolveCommands(root.getAllReachableFacts());
if (!errors.isEmpty())
throw errors.pick();
for (ErrorWarning w : warns) rep.warning(w);
for (Sig s : root.exactSigs) rep.debug("Forced to be exact: " + s + "\n");
return root;
}
use of edu.mit.csail.sdg.alloy4.A4Reporter 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 edu.mit.csail.sdg.alloy4.A4Reporter in project org.alloytools.alloy by AlloyTools.
the class A4SolutionWriter method writeInstance.
/**
* If this solution is a satisfiable solution, this method will write it out in
* XML format.
*/
static void writeInstance(A4Reporter rep, A4Solution sol, PrintWriter out, Iterable<Func> extraSkolems, Map<String, String> sources) throws Err {
if (!sol.satisfiable())
throw new ErrorAPI("This solution is unsatisfiable.");
try {
Util.encodeXMLs(out, "<alloy builddate=\"", Version.buildDate(), "\">\n\n");
new A4SolutionWriter(rep, sol, sol.getAllReachableSigs(), sol.getBitwidth(), sol.getMaxSeq(), sol.getOriginalCommand(), sol.getOriginalFilename(), out, extraSkolems);
if (sources != null)
for (Map.Entry<String, String> e : sources.entrySet()) {
Util.encodeXMLs(out, "\n<source filename=\"", e.getKey(), "\" content=\"", e.getValue(), "\"/>\n");
}
out.print("\n</alloy>\n");
} catch (Throwable ex) {
if (ex instanceof Err)
throw (Err) ex;
else
throw new ErrorFatal("Error writing the solution XML file.", ex);
}
if (out.checkError())
throw new ErrorFatal("Error writing the solution XML file.");
}
use of edu.mit.csail.sdg.alloy4.A4Reporter in project org.alloytools.alloy by AlloyTools.
the class CompModule method resolveFieldDecl.
// ============================================================================================================================//
private static void resolveFieldDecl(CompModule res, final A4Reporter rep, final Sig s, final List<ErrorWarning> warns, boolean defined) throws Err {
// When typechecking each field:
// * it is allowed to refer to earlier fields in the same SIG or in any
// visible ancestor sig
// * it is allowed to refer to visible sigs
// * it is NOT allowed to refer to any predicate or function
// For example, if A.als opens B.als, and B/SIGX extends A/SIGY,
// then B/SIGX's fields cannot refer to A/SIGY, nor any fields in
// A/SIGY)
final List<Decl> oldDecls = res.old2fields.get(res.new2old.get(s));
if (oldDecls == null)
return;
final CompModule m = res.sig2module.get(s);
final Context cx = new Context(m, warns);
final ExprHasName dup = Decl.findDuplicateName(oldDecls);
if (dup != null)
throw new ErrorSyntax(dup.span(), "sig \"" + s + "\" cannot have 2 fields named \"" + dup.label + "\"");
for (final Decl d : oldDecls) {
if (d.expr.mult() != ExprUnary.Op.EXACTLYOF) {
if (defined)
continue;
} else {
if (!defined)
continue;
}
// The name "this" does matter, since the parser and the typechecker
// both refer to it as "this"
cx.rootfield = d;
cx.rootsig = s;
cx.put("this", s.decl.get());
Expr bound = cx.check(d.expr).resolve_as_set(warns);
cx.remove("this");
String[] names = new String[d.names.size()];
for (int i = 0; i < names.length; i++) names[i] = d.names.get(i).label;
Field[] fields = s.addTrickyField(d.span(), d.isPrivate, d.disjoint, d.disjoint2, null, names, bound);
for (Field f : fields) {
rep.typecheck("Sig " + s + ", Field " + f.label + ": " + f.type() + "\n");
}
}
}
use of edu.mit.csail.sdg.alloy4.A4Reporter in project org.alloytools.alloy by AlloyTools.
the class CompModule method resolveFuncBody.
/**
* Each Func's body will now be typechecked Expr object.
*/
private JoinableList<Err> resolveFuncBody(A4Reporter rep, JoinableList<Err> errors, List<ErrorWarning> warns) throws Err {
for (ArrayList<Func> entry : funcs.values()) for (Func ff : entry) {
Context cx = new Context(this, warns);
cx.rootfunbody = ff;
for (Decl d : ff.decls) for (ExprHasName n : d.names) cx.put(n.label, n);
Expr newBody = cx.check(ff.getBody());
if (ff.isPred)
newBody = newBody.resolve_as_formula(warns);
else
newBody = newBody.resolve_as_set(warns);
errors = errors.make(newBody.errors);
if (!newBody.errors.isEmpty())
continue;
try {
ff.setBody(newBody);
} catch (Err er) {
errors = errors.make(er);
continue;
}
if (warns != null && ff.returnDecl.type().hasTuple() && newBody.type().hasTuple() && !newBody.type().intersects(ff.returnDecl.type()))
warns.add(new ErrorWarning(newBody.span(), "Function return value is disjoint from its return type.\n" + "Function body has type " + newBody.type() + "\n" + "but the return type is " + ff.returnDecl.type()));
// else if (warns!=null && Version.experimental &&
// !newBody.type.isSubtypeOf(ff.returnDecl.type))
// warns.add(new ErrorWarning(newBody.span(),
// "Function may return a tuple not in its declared return
// type.\n"
// +"The Alloy Analyzer's analysis may be unsound\n"
// +"if it returns a tuple outside its declared return type.\n"
// +"Function body has type "+newBody.type+"\nbut the return
// type is "+ff.returnDecl.type));
rep.typecheck(ff.toString() + ", BODY:" + newBody.type() + "\n");
}
return errors;
}
Aggregations