Search in sources :

Example 11 with Relation

use of kodkod.ast.Relation in project org.alloytools.alloy by AlloyTools.

the class Bounds method ensureAtomRelations.

/**
 * Creates atom relations for all atoms present in this Bounds for which
 * corresponding atom relations don't already exist.
 */
public void ensureAtomRelations() {
    for (Object atom : universe()) {
        if (getAtomExpr(atom, atom2rel) == null) {
            Relation ar = Relation.atom(atom.toString());
            boundExactly(ar, factory.setOf(atom));
        }
        ;
    }
}
Also used : Relation(kodkod.ast.Relation)

Example 12 with Relation

use of kodkod.ast.Relation 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 13 with Relation

use of kodkod.ast.Relation 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 14 with Relation

use of kodkod.ast.Relation 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;
}
Also used : PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) SubsetSig(edu.mit.csail.sdg.ast.Sig.SubsetSig) Sig(edu.mit.csail.sdg.ast.Sig) TupleSet(kodkod.instance.TupleSet) SubsetSig(edu.mit.csail.sdg.ast.Sig.SubsetSig) Relation(kodkod.ast.Relation) Expression(kodkod.ast.Expression) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Example 15 with Relation

use of kodkod.ast.Relation in project org.alloytools.alloy by AlloyTools.

the class LeafInterpreter method allocateVars.

/**
 * Populates the {@code vars} map with bindings from each relation in
 * {@code rels} to an integer range, which specifies the identifiers of the
 * variables used to encode the contents of that relation. The resulting integer
 * ranges put together form a complete range that starts at {@code minVar}.
 *
 * @requires lowers.universe = uppers.universe
 * @requires all r: rels | lowers.get(r).tuples in uppers.get(r).tuples
 * @ensures vars.map' = vars.map ++ { r: rels, v: IntRange | v.size() =
 *          uppers.get(r).size() - lowers.get(r).size() && v.size() > 0 }
 * @ensures min(vars.map'[rels]) = minVar && max(vars.map'[rels]) = minVar +
 *          (sum r: rels | vars.map'[r].size()) - 1
 * @return sum r: rels | vars.map'[r].size()
 */
private static int allocateVars(int minVar, Map<Relation, IntRange> vars, Set<Relation> rels, Map<Relation, TupleSet> lowers, Map<Relation, TupleSet> uppers) {
    int maxLit = minVar;
    for (Relation r : rels) {
        int rLits = uppers.get(r).size() - lowers.get(r).size();
        if (rLits > 0) {
            vars.put(r, Ints.range(maxLit, maxLit + rLits - 1));
            maxLit += rLits;
        }
    }
    return maxLit - minVar;
}
Also used : Relation(kodkod.ast.Relation)

Aggregations

Relation (kodkod.ast.Relation)87 Bounds (kodkod.instance.Bounds)49 Formula (kodkod.ast.Formula)45 TupleFactory (kodkod.instance.TupleFactory)45 Universe (kodkod.instance.Universe)45 TupleSet (kodkod.instance.TupleSet)43 Solution (kodkod.engine.Solution)30 Expression (kodkod.ast.Expression)26 IntExpression (kodkod.ast.IntExpression)24 Solver (kodkod.engine.Solver)24 ArrayList (java.util.ArrayList)23 Variable (kodkod.ast.Variable)23 Instance (kodkod.instance.Instance)15 Decls (kodkod.ast.Decls)13 Evaluator (kodkod.engine.Evaluator)9 Tuple (kodkod.instance.Tuple)8 IntSet (kodkod.util.ints.IntSet)7 BinaryExpression (kodkod.ast.BinaryExpression)6 Decl (kodkod.ast.Decl)6 LinkedHashSet (java.util.LinkedHashSet)4