1 /********************* */
2 /*! \file minisat.cpp
3 ** \verbatim
4 ** Top contributors (to current version):
5 ** Liana Hadarean, Dejan Jovanovic, Tim King
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS
8 ** in the top-level source directory) and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\endverbatim
11 **
12 ** \brief SAT Solver.
13 **
14 ** Implementation of the minisat interface for cvc4.
15 **/
16
17 #include "prop/minisat/minisat.h"
18
19 #include "options/base_options.h"
20 #include "options/decision_options.h"
21 #include "options/prop_options.h"
22 #include "options/smt_options.h"
23 #include "prop/minisat/simp/SimpSolver.h"
24 #include "proof/clause_id.h"
25 #include "proof/sat_proof.h"
26 #include "util/statistics_registry.h"
27
28 namespace CVC4 {
29 namespace prop {
30
31 //// DPllMinisatSatSolver
32
MinisatSatSolver(StatisticsRegistry * registry)33 MinisatSatSolver::MinisatSatSolver(StatisticsRegistry* registry) :
34 d_minisat(NULL),
35 d_context(NULL),
36 d_statistics(registry)
37 {}
38
~MinisatSatSolver()39 MinisatSatSolver::~MinisatSatSolver()
40 {
41 delete d_minisat;
42 }
43
toSatVariable(Minisat::Var var)44 SatVariable MinisatSatSolver::toSatVariable(Minisat::Var var) {
45 if (var == var_Undef) {
46 return undefSatVariable;
47 }
48 return SatVariable(var);
49 }
50
toMinisatLit(SatLiteral lit)51 Minisat::Lit MinisatSatSolver::toMinisatLit(SatLiteral lit) {
52 if (lit == undefSatLiteral) {
53 return Minisat::lit_Undef;
54 }
55 return Minisat::mkLit(lit.getSatVariable(), lit.isNegated());
56 }
57
toSatLiteral(Minisat::Lit lit)58 SatLiteral MinisatSatSolver::toSatLiteral(Minisat::Lit lit) {
59 if (lit == Minisat::lit_Undef) {
60 return undefSatLiteral;
61 }
62
63 return SatLiteral(SatVariable(Minisat::var(lit)),
64 Minisat::sign(lit));
65 }
66
toSatLiteralValue(Minisat::lbool res)67 SatValue MinisatSatSolver::toSatLiteralValue(Minisat::lbool res) {
68 if(res == (Minisat::lbool((uint8_t)0))) return SAT_VALUE_TRUE;
69 if(res == (Minisat::lbool((uint8_t)2))) return SAT_VALUE_UNKNOWN;
70 Assert(res == (Minisat::lbool((uint8_t)1)));
71 return SAT_VALUE_FALSE;
72 }
73
toMinisatlbool(SatValue val)74 Minisat::lbool MinisatSatSolver::toMinisatlbool(SatValue val)
75 {
76 if(val == SAT_VALUE_TRUE) return Minisat::lbool((uint8_t)0);
77 if(val == SAT_VALUE_UNKNOWN) return Minisat::lbool((uint8_t)2);
78 Assert(val == SAT_VALUE_FALSE);
79 return Minisat::lbool((uint8_t)1);
80 }
81
82 /*bool MinisatSatSolver::tobool(SatValue val)
83 {
84 if(val == SAT_VALUE_TRUE) return true;
85 Assert(val == SAT_VALUE_FALSE);
86 return false;
87 }*/
88
toMinisatClause(SatClause & clause,Minisat::vec<Minisat::Lit> & minisat_clause)89 void MinisatSatSolver::toMinisatClause(SatClause& clause,
90 Minisat::vec<Minisat::Lit>& minisat_clause) {
91 for (unsigned i = 0; i < clause.size(); ++i) {
92 minisat_clause.push(toMinisatLit(clause[i]));
93 }
94 Assert(clause.size() == (unsigned)minisat_clause.size());
95 }
96
toSatClause(const Minisat::Clause & clause,SatClause & sat_clause)97 void MinisatSatSolver::toSatClause(const Minisat::Clause& clause,
98 SatClause& sat_clause) {
99 for (int i = 0; i < clause.size(); ++i) {
100 sat_clause.push_back(toSatLiteral(clause[i]));
101 }
102 Assert((unsigned)clause.size() == sat_clause.size());
103 }
104
initialize(context::Context * context,TheoryProxy * theoryProxy)105 void MinisatSatSolver::initialize(context::Context* context, TheoryProxy* theoryProxy) {
106
107 d_context = context;
108
109 if( options::decisionMode() != decision::DECISION_STRATEGY_INTERNAL ) {
110 Notice() << "minisat: Incremental solving is forced on (to avoid variable elimination)"
111 << " unless using internal decision strategy." << std::endl;
112 }
113
114 // Create the solver
115 d_minisat = new Minisat::SimpSolver(theoryProxy, d_context,
116 options::incrementalSolving() ||
117 options::decisionMode() != decision::DECISION_STRATEGY_INTERNAL );
118
119 d_statistics.init(d_minisat);
120 }
121
122 // Like initialize() above, but called just before each search when in
123 // incremental mode
setupOptions()124 void MinisatSatSolver::setupOptions() {
125 // Copy options from CVC4 options structure into minisat, as appropriate
126
127 // Set up the verbosity
128 d_minisat->verbosity = (options::verbosity() > 0) ? 1 : -1;
129
130 // Set up the random decision parameters
131 d_minisat->random_var_freq = options::satRandomFreq();
132 // If 0, we use whatever we like (here, the Minisat default seed)
133 if(options::satRandomSeed() != 0) {
134 d_minisat->random_seed = double(options::satRandomSeed());
135 }
136
137 // Give access to all possible options in the sat solver
138 d_minisat->var_decay = options::satVarDecay();
139 d_minisat->clause_decay = options::satClauseDecay();
140 d_minisat->restart_first = options::satRestartFirst();
141 d_minisat->restart_inc = options::satRestartInc();
142 }
143
addClause(SatClause & clause,bool removable)144 ClauseId MinisatSatSolver::addClause(SatClause& clause, bool removable) {
145 Minisat::vec<Minisat::Lit> minisat_clause;
146 toMinisatClause(clause, minisat_clause);
147 ClauseId clause_id = ClauseIdError;
148 // FIXME: This relies on the invariant that when ok() is false
149 // the SAT solver does not add the clause (which is what Minisat currently does)
150 if (!ok()) {
151 return ClauseIdUndef;
152 }
153 d_minisat->addClause(minisat_clause, removable, clause_id);
154 PROOF( Assert (clause_id != ClauseIdError););
155 return clause_id;
156 }
157
newVar(bool isTheoryAtom,bool preRegister,bool canErase)158 SatVariable MinisatSatSolver::newVar(bool isTheoryAtom, bool preRegister, bool canErase) {
159 return d_minisat->newVar(true, true, isTheoryAtom, preRegister, canErase);
160 }
161
solve(unsigned long & resource)162 SatValue MinisatSatSolver::solve(unsigned long& resource) {
163 Trace("limit") << "SatSolver::solve(): have limit of " << resource << " conflicts" << std::endl;
164 setupOptions();
165 if(resource == 0) {
166 d_minisat->budgetOff();
167 } else {
168 d_minisat->setConfBudget(resource);
169 }
170 Minisat::vec<Minisat::Lit> empty;
171 unsigned long conflictsBefore = d_minisat->conflicts + d_minisat->resources_consumed;
172 SatValue result = toSatLiteralValue(d_minisat->solveLimited(empty));
173 d_minisat->clearInterrupt();
174 resource = d_minisat->conflicts + d_minisat->resources_consumed - conflictsBefore;
175 Trace("limit") << "SatSolver::solve(): it took " << resource << " conflicts" << std::endl;
176 return result;
177 }
178
solve()179 SatValue MinisatSatSolver::solve() {
180 setupOptions();
181 d_minisat->budgetOff();
182 return toSatLiteralValue(d_minisat->solve());
183 }
184
ok() const185 bool MinisatSatSolver::ok() const {
186 return d_minisat->okay();
187 }
188
interrupt()189 void MinisatSatSolver::interrupt() {
190 d_minisat->interrupt();
191 }
192
value(SatLiteral l)193 SatValue MinisatSatSolver::value(SatLiteral l) {
194 return toSatLiteralValue(d_minisat->value(toMinisatLit(l)));
195 }
196
modelValue(SatLiteral l)197 SatValue MinisatSatSolver::modelValue(SatLiteral l){
198 return toSatLiteralValue(d_minisat->modelValue(toMinisatLit(l)));
199 }
200
properExplanation(SatLiteral lit,SatLiteral expl) const201 bool MinisatSatSolver::properExplanation(SatLiteral lit, SatLiteral expl) const {
202 return true;
203 }
204
requirePhase(SatLiteral lit)205 void MinisatSatSolver::requirePhase(SatLiteral lit) {
206 Assert(!d_minisat->rnd_pol);
207 Debug("minisat") << "requirePhase(" << lit << ")" << " " << lit.getSatVariable() << " " << lit.isNegated() << std::endl;
208 SatVariable v = lit.getSatVariable();
209 d_minisat->freezePolarity(v, lit.isNegated());
210 }
211
isDecision(SatVariable decn) const212 bool MinisatSatSolver::isDecision(SatVariable decn) const {
213 return d_minisat->isDecision( decn );
214 }
215
216 /** Incremental interface */
217
getAssertionLevel() const218 unsigned MinisatSatSolver::getAssertionLevel() const {
219 return d_minisat->getAssertionLevel();
220 }
221
push()222 void MinisatSatSolver::push() {
223 d_minisat->push();
224 }
225
pop()226 void MinisatSatSolver::pop() {
227 d_minisat->pop();
228 }
229
resetTrail()230 void MinisatSatSolver::resetTrail() { d_minisat->resetTrail(); }
231
232 /// Statistics for MinisatSatSolver
233
Statistics(StatisticsRegistry * registry)234 MinisatSatSolver::Statistics::Statistics(StatisticsRegistry* registry) :
235 d_registry(registry),
236 d_statStarts("sat::starts"),
237 d_statDecisions("sat::decisions"),
238 d_statRndDecisions("sat::rnd_decisions"),
239 d_statPropagations("sat::propagations"),
240 d_statConflicts("sat::conflicts"),
241 d_statClausesLiterals("sat::clauses_literals"),
242 d_statLearntsLiterals("sat::learnts_literals"),
243 d_statMaxLiterals("sat::max_literals"),
244 d_statTotLiterals("sat::tot_literals")
245 {
246 d_registry->registerStat(&d_statStarts);
247 d_registry->registerStat(&d_statDecisions);
248 d_registry->registerStat(&d_statRndDecisions);
249 d_registry->registerStat(&d_statPropagations);
250 d_registry->registerStat(&d_statConflicts);
251 d_registry->registerStat(&d_statClausesLiterals);
252 d_registry->registerStat(&d_statLearntsLiterals);
253 d_registry->registerStat(&d_statMaxLiterals);
254 d_registry->registerStat(&d_statTotLiterals);
255 }
256
~Statistics()257 MinisatSatSolver::Statistics::~Statistics() {
258 d_registry->unregisterStat(&d_statStarts);
259 d_registry->unregisterStat(&d_statDecisions);
260 d_registry->unregisterStat(&d_statRndDecisions);
261 d_registry->unregisterStat(&d_statPropagations);
262 d_registry->unregisterStat(&d_statConflicts);
263 d_registry->unregisterStat(&d_statClausesLiterals);
264 d_registry->unregisterStat(&d_statLearntsLiterals);
265 d_registry->unregisterStat(&d_statMaxLiterals);
266 d_registry->unregisterStat(&d_statTotLiterals);
267 }
268
init(Minisat::SimpSolver * d_minisat)269 void MinisatSatSolver::Statistics::init(Minisat::SimpSolver* d_minisat){
270 d_statStarts.setData(d_minisat->starts);
271 d_statDecisions.setData(d_minisat->decisions);
272 d_statRndDecisions.setData(d_minisat->rnd_decisions);
273 d_statPropagations.setData(d_minisat->propagations);
274 d_statConflicts.setData(d_minisat->conflicts);
275 d_statClausesLiterals.setData(d_minisat->clauses_literals);
276 d_statLearntsLiterals.setData(d_minisat->learnts_literals);
277 d_statMaxLiterals.setData(d_minisat->max_literals);
278 d_statTotLiterals.setData(d_minisat->tot_literals);
279 }
280
281 } /* namespace CVC4::prop */
282 } /* namespace CVC4 */
283
284
285 namespace CVC4 {
286 template<>
toSatLiteral(Minisat::Solver::TLit lit)287 prop::SatLiteral toSatLiteral< CVC4::Minisat::Solver>(Minisat::Solver::TLit lit) {
288 return prop::MinisatSatSolver::toSatLiteral(lit);
289 }
290
291 template<>
toSatClause(const CVC4::Minisat::Solver::TClause & minisat_cl,prop::SatClause & sat_cl)292 void toSatClause< CVC4::Minisat::Solver> (const CVC4::Minisat::Solver::TClause& minisat_cl,
293 prop::SatClause& sat_cl) {
294 prop::MinisatSatSolver::toSatClause(minisat_cl, sat_cl);
295 }
296
297 } /* namespace CVC4 */
298