Search in sources :

Example 1 with Type

use of edu.mit.csail.sdg.ast.Type 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 2 with Type

use of edu.mit.csail.sdg.ast.Type 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);
    }
}
Also used : ExprVar(edu.mit.csail.sdg.ast.ExprVar) TupleSet(kodkod.instance.TupleSet) ArrayList(java.util.ArrayList) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) Sig(edu.mit.csail.sdg.ast.Sig) Field(edu.mit.csail.sdg.ast.Sig.Field) Relation(kodkod.ast.Relation) Type(edu.mit.csail.sdg.ast.Type) SafeList(edu.mit.csail.sdg.alloy4.SafeList) List(java.util.List) ArrayList(java.util.ArrayList) ConstList(edu.mit.csail.sdg.alloy4.ConstList) ConstMap(edu.mit.csail.sdg.alloy4.ConstMap) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) Tuple(kodkod.instance.Tuple)

Example 3 with Type

use of edu.mit.csail.sdg.ast.Type in project org.alloytools.alloy by AlloyTools.

the class A4SolutionWriter method writeExpr.

/**
 * Write the given Expr and its Type.
 */
private boolean writeExpr(String prefix, Expr expr) throws Err {
    Type type = expr.type();
    if (!type.hasTuple())
        return false;
    if (sol != null) {
        // Check to see if the tupleset is *really* fully contained inside
        // "type".
        // If not, then grow "type" until the tupleset is fully contained
        // inside "type"
        Expr sum = type.toExpr();
        int lastSize = (-1);
        while (true) {
            A4TupleSet ts = (A4TupleSet) (sol.eval(expr.minus(sum)));
            int n = ts.size();
            if (n <= 0)
                break;
            if (lastSize > 0 && lastSize <= n)
                throw new ErrorFatal("An internal error occurred in the evaluator.");
            lastSize = n;
            Type extra = ts.iterator().next().type();
            type = type.merge(extra);
            sum = sum.plus(extra.toExpr());
        }
        // Now, write out the tupleset
        A4TupleSet ts = (A4TupleSet) (sol.eval(expr));
        for (A4Tuple t : ts) {
            if (prefix.length() > 0) {
                out.print(prefix);
                prefix = "";
            }
            out.print("   <tuple>");
            for (int i = 0; i < t.arity(); i++) Util.encodeXMLs(out, " <atom label=\"", t.atom(i), "\"/>");
            out.print(" </tuple>\n");
        }
    }
    // Now, write out the type
    if (prefix.length() > 0)
        return false;
    for (List<PrimSig> ps : type.fold()) {
        out.print("   <types>");
        for (PrimSig sig : ps) Util.encodeXMLs(out, " <type ID=\"", map(sig), "\"/>");
        out.print(" </types>\n");
    }
    return true;
}
Also used : Type(edu.mit.csail.sdg.ast.Type) ErrorFatal(edu.mit.csail.sdg.alloy4.ErrorFatal) Expr(edu.mit.csail.sdg.ast.Expr) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Example 4 with Type

use of edu.mit.csail.sdg.ast.Type in project org.alloytools.alloy by AlloyTools.

the class TranslateAlloyToKodkod method visit.

/**
 * {@inheritDoc}
 */
@Override
public Object visit(ExprCall x) throws Err {
    final Func f = x.fun;
    final Object candidate = f.count() == 0 ? cacheForConstants.get(f) : null;
    if (candidate != null)
        return candidate;
    final Expr body = f.getBody();
    if (body.type().arity() < 0 || body.type().arity() != f.returnDecl.type().arity())
        throw new ErrorType(body.span(), "Function return value not fully resolved.");
    final int n = f.count();
    int maxRecursion = unrolls;
    for (Func ff : current_function) if (ff == f) {
        if (maxRecursion < 0) {
            throw new ErrorSyntax(x.span(), "" + f + " cannot call itself recursively!");
        }
        if (maxRecursion == 0) {
            Type t = f.returnDecl.type();
            if (t.is_bool)
                return Formula.FALSE;
            if (t.is_int())
                return IntConstant.constant(0);
            int i = t.arity();
            Expression ans = Expression.NONE;
            while (i > 1) {
                ans = ans.product(Expression.NONE);
                i--;
            }
            return ans;
        }
        maxRecursion--;
    }
    Env<ExprVar, Object> newenv = new Env<ExprVar, Object>();
    for (int i = 0; i < n; i++) newenv.put(f.get(i), cset(x.args.get(i)));
    Env<ExprVar, Object> oldenv = env;
    env = newenv;
    current_function.add(f);
    Object ans = visitThis(body);
    env = oldenv;
    current_function.remove(current_function.size() - 1);
    if (ans instanceof Formula)
        k2pos((Formula) ans, x);
    if (f.count() == 0)
        cacheForConstants.put(f, ans);
    return ans;
}
Also used : ExprVar(edu.mit.csail.sdg.ast.ExprVar) QuantifiedFormula(kodkod.ast.QuantifiedFormula) Formula(kodkod.ast.Formula) ErrorSyntax(edu.mit.csail.sdg.alloy4.ErrorSyntax) Type(edu.mit.csail.sdg.ast.Type) ErrorType(edu.mit.csail.sdg.alloy4.ErrorType) Expr(edu.mit.csail.sdg.ast.Expr) ErrorType(edu.mit.csail.sdg.alloy4.ErrorType) Func(edu.mit.csail.sdg.ast.Func) Expression(kodkod.ast.Expression) BinaryExpression(kodkod.ast.BinaryExpression) IntExpression(kodkod.ast.IntExpression) Env(edu.mit.csail.sdg.alloy4.Env)

Example 5 with Type

use of edu.mit.csail.sdg.ast.Type in project org.alloytools.alloy by AlloyTools.

the class A4Tuple method type.

/**
 * Returns the type constructed by taking the product for each sig in this
 * tuple.
 */
public Type type() {
    Type ans = null;
    for (int i = 0; i < tuple.arity(); i++) if (ans == null)
        ans = sig(0).type();
    else
        ans = ans.product(sig(i).type());
    return ans;
}
Also used : Type(edu.mit.csail.sdg.ast.Type)

Aggregations

Type (edu.mit.csail.sdg.ast.Type)5 Expr (edu.mit.csail.sdg.ast.Expr)2 ExprVar (edu.mit.csail.sdg.ast.ExprVar)2 PrimSig (edu.mit.csail.sdg.ast.Sig.PrimSig)2 Formula (kodkod.ast.Formula)2 Relation (kodkod.ast.Relation)2 Tuple (kodkod.instance.Tuple)2 A4Reporter (edu.mit.csail.sdg.alloy4.A4Reporter)1 ConstList (edu.mit.csail.sdg.alloy4.ConstList)1 ConstMap (edu.mit.csail.sdg.alloy4.ConstMap)1 Env (edu.mit.csail.sdg.alloy4.Env)1 ErrorFatal (edu.mit.csail.sdg.alloy4.ErrorFatal)1 ErrorSyntax (edu.mit.csail.sdg.alloy4.ErrorSyntax)1 ErrorType (edu.mit.csail.sdg.alloy4.ErrorType)1 SafeList (edu.mit.csail.sdg.alloy4.SafeList)1 UniqueNameGenerator (edu.mit.csail.sdg.alloy4.UniqueNameGenerator)1 Func (edu.mit.csail.sdg.ast.Func)1 Sig (edu.mit.csail.sdg.ast.Sig)1 Field (edu.mit.csail.sdg.ast.Sig.Field)1 File (java.io.File)1