From 55ac98d3fc4f7a90af25f9d63024069232b3b2cb Mon Sep 17 00:00:00 2001 From: Sebastian Krings <sebastian@krin.gs> Date: Mon, 17 Aug 2015 14:16:21 +0200 Subject: [PATCH] introduce new solver factory with timeout, drop minisat option for now --- .../de/stups/probkodkod/KodkodAnalysis.java | 3 +- .../de/stups/probkodkod/KodkodSession.java | 8 +- .../de/stups/probkodkod/SolverChecker.java | 8 +- .../probkodkod/sat/SAT4JWithTimeout.java | 80 +++++++++++++++++++ .../sat/SAT4JWithTimeoutFactory.java | 25 ++++++ src/main/resources/problem.grammar | 2 +- src/test/resources/problems/functions.kodkod | 2 +- .../resources/problems/integercast.kodkod | 2 +- src/test/resources/problems/integers.kodkod | 2 +- src/test/resources/problems/intrange.kodkod | 2 +- src/test/resources/problems/intvar.kodkod | 2 +- src/test/resources/problems/loop.kodkod | 2 +- src/test/resources/problems/negative.kodkod | 2 +- src/test/resources/problems/projection.kodkod | 2 +- src/test/resources/problems/relquant.kodkod | 2 +- src/test/resources/problems/returnzero.kodkod | 2 +- .../resources/problems/sendmoremoney.kodkod | 4 +- .../resources/problems/simpletwovars.kodkod | 2 +- 18 files changed, 132 insertions(+), 20 deletions(-) create mode 100644 src/main/java/de/stups/probkodkod/sat/SAT4JWithTimeout.java create mode 100644 src/main/java/de/stups/probkodkod/sat/SAT4JWithTimeoutFactory.java diff --git a/src/main/java/de/stups/probkodkod/KodkodAnalysis.java b/src/main/java/de/stups/probkodkod/KodkodAnalysis.java index cfb7185..0652142 100644 --- a/src/main/java/de/stups/probkodkod/KodkodAnalysis.java +++ b/src/main/java/de/stups/probkodkod/KodkodAnalysis.java @@ -253,7 +253,8 @@ public class KodkodAnalysis extends DepthFirstAdapter { node.getFormula().apply(this); problem.setFormula(formulaStack.pop()); - session.addProblem(problem.createImmutable()); + long timeout = Long.parseLong(node.getTimeout().getText()); + session.addProblem(problem.createImmutable(), timeout); } private void registerTypes(final Collection<PType> types) { diff --git a/src/main/java/de/stups/probkodkod/KodkodSession.java b/src/main/java/de/stups/probkodkod/KodkodSession.java index f618ec9..324dc0b 100644 --- a/src/main/java/de/stups/probkodkod/KodkodSession.java +++ b/src/main/java/de/stups/probkodkod/KodkodSession.java @@ -6,9 +6,9 @@ import java.util.logging.Level; import java.util.logging.Logger; import kodkod.engine.Solver; -import kodkod.engine.satlab.SATFactory; import kodkod.instance.TupleSet; import de.prob.prolog.output.IPrologTermOutput; +import de.stups.probkodkod.sat.SAT4JWithTimeoutFactory; /** * The session contains all the information that is needed during an interaction @@ -21,7 +21,7 @@ import de.prob.prolog.output.IPrologTermOutput; * */ public class KodkodSession { - private final SATFactory SOLVER = SolverChecker.determineSatFactory(); + // private final SATFactory SOLVER = SolverChecker.determineSatFactory(); private final Logger logger = Logger.getLogger(KodkodSession.class .getName()); @@ -30,12 +30,12 @@ public class KodkodSession { private final Map<ImmutableProblem, Request> currentRequests = new HashMap<ImmutableProblem, Request>(); private boolean stopped = false; - public void addProblem(final ImmutableProblem problem) { + public void addProblem(final ImmutableProblem problem, long timeout) { String id = problem.getId(); problems.put(id, problem); final Solver solver = new Solver(); - solver.options().setSolver(SOLVER); + solver.options().setSolver(new SAT4JWithTimeoutFactory(timeout)); solver.options().setSymmetryBreaking(0); final Integer bitwidth = problem.getBitwidth(); if (bitwidth != null) { diff --git a/src/main/java/de/stups/probkodkod/SolverChecker.java b/src/main/java/de/stups/probkodkod/SolverChecker.java index c5c06e8..77f0184 100644 --- a/src/main/java/de/stups/probkodkod/SolverChecker.java +++ b/src/main/java/de/stups/probkodkod/SolverChecker.java @@ -15,6 +15,7 @@ import kodkod.engine.Solver; import kodkod.engine.satlab.SATFactory; import kodkod.instance.Bounds; import kodkod.instance.Universe; +import de.stups.probkodkod.sat.SAT4JWithTimeoutFactory; /** * Here we determine if we use Minisat or SAT4J as back-end. We do this by @@ -25,8 +26,11 @@ import kodkod.instance.Universe; public class SolverChecker { private static final Logger LOGGER = Logger .getLogger("de.stups.probkodkod"); - private static final SATFactory[] FACTORIES = { SATFactory.MiniSat, - SATFactory.DefaultSAT4J }; + private static final SATFactory[] FACTORIES = { new SAT4JWithTimeoutFactory() }; + + // private static final SATFactory[] FACTORIES = { + // new SAT4JWithTimeoutFactory(), SATFactory.MiniSat, + // SATFactory.DefaultSAT4J }; public static SATFactory determineSatFactory() { Map<String, Throwable> throwables = new HashMap<String, Throwable>(); diff --git a/src/main/java/de/stups/probkodkod/sat/SAT4JWithTimeout.java b/src/main/java/de/stups/probkodkod/sat/SAT4JWithTimeout.java new file mode 100644 index 0000000..a37dc2d --- /dev/null +++ b/src/main/java/de/stups/probkodkod/sat/SAT4JWithTimeout.java @@ -0,0 +1,80 @@ +package de.stups.probkodkod.sat; + +import kodkod.engine.satlab.SATSolver; + +import org.sat4j.core.VecInt; +import org.sat4j.minisat.SolverFactory; +import org.sat4j.specs.ContradictionException; +import org.sat4j.specs.ISolver; + +final class SAT4JWithTimeout implements SATSolver { + private ISolver solver; + private boolean sat = true; + private int vars, clauses; + private long timeout; + + SAT4JWithTimeout(long ms) { + this.solver = SolverFactory.instance().defaultSolver(); + this.solver.setTimeoutMs(ms); + this.timeout = ms; + this.vars = 0; + this.clauses = 0; + } + + public int numberOfVariables() { + return vars; + } + + public int numberOfClauses() { + return clauses; + } + + public void addVariables(int numVars) { + if (numVars < 0) + throw new IllegalArgumentException("numVars < 0: " + numVars); + else if (numVars > 0) { + vars += numVars; + solver.newVar(vars); + } + } + + public boolean addClause(int[] lits) { + try { + if (sat) { + clauses++; + solver.addClause(new VecInt(lits)); + return true; + } + } catch (ContradictionException e) { + sat = false; + } + return false; + } + + public boolean solve() { + try { + if (sat) + sat = solver.isSatisfiable(); + return sat; + } catch (org.sat4j.specs.TimeoutException e) { + throw new RuntimeException("timed out"); + } + } + + public final boolean valueOf(int variable) { + if (!sat) + throw new IllegalStateException(); + if (variable < 1 || variable > vars) + throw new IllegalArgumentException(variable + " !in [1.." + vars + + "]"); + return solver.model(variable); + } + + public synchronized final void free() { + solver = null; + } + + public String toString() { + return "SAT4JWithTimeout Solver using " + timeout + " ms timeout"; + } +} \ No newline at end of file diff --git a/src/main/java/de/stups/probkodkod/sat/SAT4JWithTimeoutFactory.java b/src/main/java/de/stups/probkodkod/sat/SAT4JWithTimeoutFactory.java new file mode 100644 index 0000000..c5bd727 --- /dev/null +++ b/src/main/java/de/stups/probkodkod/sat/SAT4JWithTimeoutFactory.java @@ -0,0 +1,25 @@ +package de.stups.probkodkod.sat; + +import kodkod.engine.satlab.SATFactory; +import kodkod.engine.satlab.SATSolver; + +public class SAT4JWithTimeoutFactory extends SATFactory { + private long timeout; + + public SAT4JWithTimeoutFactory() { + this(1500); + } + + public SAT4JWithTimeoutFactory(long ms) { + this.timeout = ms; + } + + @Override + public SATSolver instance() { + return new SAT4JWithTimeout(timeout); + } + + public String toString() { + return "SAT4J with timeout of " + timeout + " ms"; + } +} diff --git a/src/main/resources/problem.grammar b/src/main/resources/problem.grammar index 5ef71b9..1d559d1 100644 --- a/src/main/resources/problem.grammar +++ b/src/main/resources/problem.grammar @@ -99,7 +99,7 @@ Productions | {reset} reset | {none}; - problem = keyword_problem [id]:identifier + problem = keyword_problem [id]:identifier [timeout]:number [tpl]:parenl [types]:type* [tpr]:parenr [rpl]:parenl [relations]:relation* [rpr]:parenr formula; diff --git a/src/test/resources/problems/functions.kodkod b/src/test/resources/problems/functions.kodkod index 91eceac..6e1d089 100644 --- a/src/test/resources/problems/functions.kodkod +++ b/src/test/resources/problems/functions.kodkod @@ -1,4 +1,4 @@ -problem functions +problem functions 3500 ((d 2) (r 2)) diff --git a/src/test/resources/problems/integercast.kodkod b/src/test/resources/problems/integercast.kodkod index 75b2a27..2469596 100644 --- a/src/test/resources/problems/integercast.kodkod +++ b/src/test/resources/problems/integercast.kodkod @@ -1,4 +1,4 @@ -problem integercast +problem integercast 3500 ((inttype (si 0 7) (ai 0 9))) diff --git a/src/test/resources/problems/integers.kodkod b/src/test/resources/problems/integers.kodkod index 4e005ff..c060001 100644 --- a/src/test/resources/problems/integers.kodkod +++ b/src/test/resources/problems/integers.kodkod @@ -1,4 +1,4 @@ -problem integers +problem integers 3500 ((inttype (si 0 2)) (w 2)) diff --git a/src/test/resources/problems/intrange.kodkod b/src/test/resources/problems/intrange.kodkod index 95c0dbf..9c6e37d 100644 --- a/src/test/resources/problems/intrange.kodkod +++ b/src/test/resources/problems/intrange.kodkod @@ -1,4 +1,4 @@ -problem intrange +problem intrange 3500 ((inttype (p2i 0 8) (is 0 8))) diff --git a/src/test/resources/problems/intvar.kodkod b/src/test/resources/problems/intvar.kodkod index 9df5b14..b9c72b5 100644 --- a/src/test/resources/problems/intvar.kodkod +++ b/src/test/resources/problems/intvar.kodkod @@ -1,4 +1,4 @@ -problem intvar +problem intvar 3500 ((inttype (si 0 7))) diff --git a/src/test/resources/problems/loop.kodkod b/src/test/resources/problems/loop.kodkod index e106b9f..1725fe9 100644 --- a/src/test/resources/problems/loop.kodkod +++ b/src/test/resources/problems/loop.kodkod @@ -1,4 +1,4 @@ -problem loop +problem loop 3500 ((Blocks 8)) diff --git a/src/test/resources/problems/negative.kodkod b/src/test/resources/problems/negative.kodkod index f663ba4..c0c873d 100644 --- a/src/test/resources/problems/negative.kodkod +++ b/src/test/resources/problems/negative.kodkod @@ -1,4 +1,4 @@ -problem negative +problem negative 3500 ((inttype (p2i -15 15))) diff --git a/src/test/resources/problems/projection.kodkod b/src/test/resources/problems/projection.kodkod index 404c20a..05adb8a 100644 --- a/src/test/resources/problems/projection.kodkod +++ b/src/test/resources/problems/projection.kodkod @@ -1,4 +1,4 @@ -problem projection +problem projection 3500 ((world 2)) diff --git a/src/test/resources/problems/relquant.kodkod b/src/test/resources/problems/relquant.kodkod index a2e3140..7448a38 100644 --- a/src/test/resources/problems/relquant.kodkod +++ b/src/test/resources/problems/relquant.kodkod @@ -1,4 +1,4 @@ -problem relquant +problem relquant 3500 ((d 2) (r 2)) diff --git a/src/test/resources/problems/returnzero.kodkod b/src/test/resources/problems/returnzero.kodkod index 8437c86..82656ad 100644 --- a/src/test/resources/problems/returnzero.kodkod +++ b/src/test/resources/problems/returnzero.kodkod @@ -1,4 +1,4 @@ -problem returnzero +problem returnzero 3500 ( (inttype(p2i 0 0)) ) ( (x singleton subset p2i) ) diff --git a/src/test/resources/problems/sendmoremoney.kodkod b/src/test/resources/problems/sendmoremoney.kodkod index 775f4fd..f3791fb 100644 --- a/src/test/resources/problems/sendmoremoney.kodkod +++ b/src/test/resources/problems/sendmoremoney.kodkod @@ -1,4 +1,6 @@ -problem sendmoremoney ((inttype(p2i 0 199980))) +problem sendmoremoney 3500 + +((inttype(p2i 0 199980))) ( (s singleton subset p2i) (e singleton subset p2i) diff --git a/src/test/resources/problems/simpletwovars.kodkod b/src/test/resources/problems/simpletwovars.kodkod index 4ab4aff..f84e7ba 100644 --- a/src/test/resources/problems/simpletwovars.kodkod +++ b/src/test/resources/problems/simpletwovars.kodkod @@ -1,4 +1,4 @@ -problem simpletwovars +problem simpletwovars 3500 ((T 2)) -- GitLab