Search in sources :

Example 1 with A4Reporter

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;
}
Also used : PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) Sig(edu.mit.csail.sdg.ast.Sig) SubsetSig(edu.mit.csail.sdg.ast.Sig.SubsetSig) Err(edu.mit.csail.sdg.alloy4.Err) ArrayList(java.util.ArrayList) ErrorWarning(edu.mit.csail.sdg.alloy4.ErrorWarning) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) JoinableList(edu.mit.csail.sdg.alloy4.JoinableList)

Example 2 with A4Reporter

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;
}
Also used : HybridStrategy(kodkod.engine.ucore.HybridStrategy) Instance(kodkod.instance.Instance) Node(kodkod.ast.Node) BinaryFormula(kodkod.ast.BinaryFormula) Formula(kodkod.ast.Formula) Relation(kodkod.ast.Relation) RCEStrategy(kodkod.engine.ucore.RCEStrategy) Solution(kodkod.engine.Solution) A4Reporter(edu.mit.csail.sdg.alloy4.A4Reporter) A4Reporter(edu.mit.csail.sdg.alloy4.A4Reporter) AbstractReporter(kodkod.engine.config.AbstractReporter) Reporter(kodkod.engine.config.Reporter) TranslationRecord(kodkod.engine.fol2sat.TranslationRecord) Decl(kodkod.ast.Decl) Evaluator(kodkod.engine.Evaluator) UniqueNameGenerator(edu.mit.csail.sdg.alloy4.UniqueNameGenerator) Type(edu.mit.csail.sdg.ast.Type) Proof(kodkod.engine.Proof) File(java.io.File) Tuple(kodkod.instance.Tuple)

Example 3 with A4Reporter

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.");
}
Also used : ErrorAPI(edu.mit.csail.sdg.alloy4.ErrorAPI) ErrorFatal(edu.mit.csail.sdg.alloy4.ErrorFatal) Err(edu.mit.csail.sdg.alloy4.Err)

Example 4 with A4Reporter

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");
        }
    }
}
Also used : Field(edu.mit.csail.sdg.ast.Sig.Field) ErrorSyntax(edu.mit.csail.sdg.alloy4.ErrorSyntax) Expr(edu.mit.csail.sdg.ast.Expr) ExprHasName(edu.mit.csail.sdg.ast.ExprHasName) Decl(edu.mit.csail.sdg.ast.Decl)

Example 5 with A4Reporter

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;
}
Also used : Expr(edu.mit.csail.sdg.ast.Expr) Err(edu.mit.csail.sdg.alloy4.Err) Func(edu.mit.csail.sdg.ast.Func) ExprHasName(edu.mit.csail.sdg.ast.ExprHasName) ErrorWarning(edu.mit.csail.sdg.alloy4.ErrorWarning) Decl(edu.mit.csail.sdg.ast.Decl)

Aggregations

Err (edu.mit.csail.sdg.alloy4.Err)9 A4Reporter (edu.mit.csail.sdg.alloy4.A4Reporter)6 ErrorFatal (edu.mit.csail.sdg.alloy4.ErrorFatal)6 Pos (edu.mit.csail.sdg.alloy4.Pos)5 Command (edu.mit.csail.sdg.ast.Command)5 ErrorSyntax (edu.mit.csail.sdg.alloy4.ErrorSyntax)4 Expr (edu.mit.csail.sdg.ast.Expr)4 Sig (edu.mit.csail.sdg.ast.Sig)4 A4Options (edu.mit.csail.sdg.translator.A4Options)4 A4Solution (edu.mit.csail.sdg.translator.A4Solution)4 ArrayList (java.util.ArrayList)4 ErrorType (edu.mit.csail.sdg.alloy4.ErrorType)3 ErrorWarning (edu.mit.csail.sdg.alloy4.ErrorWarning)3 Decl (edu.mit.csail.sdg.ast.Decl)3 ExprHasName (edu.mit.csail.sdg.ast.ExprHasName)3 Module (edu.mit.csail.sdg.ast.Module)3 LinkedHashSet (java.util.LinkedHashSet)3 CapacityExceededException (kodkod.engine.CapacityExceededException)3 ErrorAPI (edu.mit.csail.sdg.alloy4.ErrorAPI)2 Func (edu.mit.csail.sdg.ast.Func)2