CBMC
Loading...
Searching...
No Matches
satcheck_minisat2.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include "satcheck_minisat2.h"
10
11#ifndef _WIN32
12# include <signal.h>
13# include <unistd.h>
14#endif
15
16#include <limits>
17
18#include <util/invariant.h>
19#include <util/threeval.h>
20
21#include <minisat/core/Solver.h>
22#include <minisat/simp/SimpSolver.h>
23
24#ifndef l_False
25# define l_False Minisat::l_False
26# define l_True Minisat::l_True
27#endif
28
29#ifndef HAVE_MINISAT2
30#error "Expected HAVE_MINISAT2"
31#endif
32
33void convert(const bvt &bv, Minisat::vec<Minisat::Lit> &dest)
34{
36 bv.size() <= static_cast<std::size_t>(std::numeric_limits<int>::max()));
37 dest.capacity(static_cast<int>(bv.size()));
38
39 for(const auto &literal : bv)
40 {
41 if(!literal.is_false())
42 dest.push(Minisat::mkLit(literal.var_no(), literal.sign()));
43 }
45
46void convert_assumptions(const bvt &bv, Minisat::vec<Minisat::Lit> &dest)
49 bv.size() <= static_cast<std::size_t>(std::numeric_limits<int>::max()));
50 dest.capacity(static_cast<int>(bv.size()));
51
52 for(const auto &literal : bv)
53 {
54 // when converting assumptions, ignore 'true'
55 if(!literal.is_true())
56 dest.push(Minisat::mkLit(literal.var_no(), literal.sign()));
57 }
58}
59
60template<typename T>
62{
63 if(a.is_true())
64 return tvt(true);
65 else if(a.is_false())
66 return tvt(false);
67
68 tvt result;
69
70 if(a.var_no()>=(unsigned)solver->model.size())
71 return tvt::unknown();
72
73 using Minisat::lbool;
74
75 if(solver->model[a.var_no()]==l_True)
76 result=tvt(true);
77 else if(solver->model[a.var_no()]==l_False)
78 result=tvt(false);
79 else
80 return tvt::unknown();
81
82 if(a.sign())
83 result=!result;
84
85 return result;
86}
87
88template<typename T>
90{
91 PRECONDITION(!a.is_constant());
92
93 using Minisat::lbool;
94
95 try
96 {
97 add_variables();
98 solver->setPolarity(a.var_no(), value ? l_True : l_False);
99 }
100 catch(Minisat::OutOfMemoryException)
101 {
102 log.error() << "SAT checker ran out of memory" << messaget::eom;
103 status = statust::ERROR;
104 throw std::bad_alloc();
105 }
106}
107
108template<typename T>
110{
111 solver->interrupt();
112}
113
114template<typename T>
116{
117 solver->clearInterrupt();
118}
119
121{
122 return "MiniSAT 2.2.1 without simplifier";
123}
124
126{
127 return "MiniSAT 2.2.1 with simplifier";
128}
129
130template<typename T>
132{
133 while((unsigned)solver->nVars()<no_variables())
134 solver->newVar();
135}
136
137template<typename T>
139{
140 try
141 {
142 add_variables();
143
144 for(const auto &literal : bv)
145 {
146 if(literal.is_true())
147 return;
148 else if(!literal.is_false())
149 {
150 INVARIANT(
151 literal.var_no() < (unsigned)solver->nVars(),
152 "variable not added yet");
153 }
154 }
155
156 Minisat::vec<Minisat::Lit> c;
157
158 convert(bv, c);
159
160 // Note the underscore.
161 // Add a clause to the solver without making superflous internal copy.
162
163 solver->addClause_(c);
164
165 if(solver_hardness)
166 {
167 // To map clauses to lines of program code, track clause indices in the
168 // dimacs cnf output. Dimacs output is generated after processing
169 // clauses to remove duplicates and clauses that are trivially true.
170 // Here, a clause is checked to see if it can be thus eliminated. If
171 // not, add the clause index to list of clauses in
172 // solver_hardnesst::register_clause().
173 static size_t cnf_clause_index = 0;
174 bvt cnf;
175 bool clause_removed = process_clause(bv, cnf);
176
177 if(!clause_removed)
179
180 solver_hardness->register_clause(
182 }
183
184 clause_counter++;
185 }
186 catch(const Minisat::OutOfMemoryException &)
187 {
188 log.error() << "SAT checker ran out of memory" << messaget::eom;
189 status = statust::ERROR;
190 throw std::bad_alloc();
191 }
192}
193
194#ifndef _WIN32
195
196static Minisat::Solver *solver_to_interrupt=nullptr;
197
198static void interrupt_solver(int signum)
199{
200 (void)signum; // unused parameter -- just removing the name trips up cpplint
201 solver_to_interrupt->interrupt();
202}
203
204#endif
205
206template <typename T>
208{
209 PRECONDITION(status != statust::ERROR);
210
211 log.statistics() << (no_variables() - 1) << " variables, "
212 << solver->nClauses() << " clauses" << messaget::eom;
213
214 try
215 {
216 add_variables();
217
218 if(!solver->okay())
219 {
220 log.status() << "SAT checker inconsistent: instance is UNSATISFIABLE"
221 << messaget::eom;
222 status = statust::UNSAT;
223 return resultt::P_UNSATISFIABLE;
224 }
225
226 // if assumptions contains false, we need this to be UNSAT
227 for(const auto &assumption : assumptions)
228 {
229 if(assumption.is_false())
230 {
231 log.status() << "got FALSE as assumption: instance is UNSATISFIABLE"
232 << messaget::eom;
233 status = statust::UNSAT;
234 return resultt::P_UNSATISFIABLE;
235 }
236 }
237
238 Minisat::vec<Minisat::Lit> solver_assumptions;
240
241 using Minisat::lbool;
242
243#ifndef _WIN32
244
246
247 if(time_limit_seconds != 0)
248 {
251 if(old_handler == SIG_ERR)
252 log.warning() << "Failed to set solver time limit" << messaget::eom;
253 else
254 alarm(time_limit_seconds);
255 }
256
258
259 if(old_handler != SIG_ERR)
260 {
261 alarm(0);
264 }
265
266#else // _WIN32
267
268 if(time_limit_seconds != 0)
269 {
270 log.warning() << "Time limit ignored (not supported on Win32 yet)"
271 << messaget::eom;
272 }
273
275
276#endif
277
278 if(solver_result == l_True)
279 {
280 log.status() << "SAT checker: instance is SATISFIABLE" << messaget::eom;
281 CHECK_RETURN(solver->model.size() > 0);
282 status = statust::SAT;
283 return resultt::P_SATISFIABLE;
284 }
285
287 {
288 log.status() << "SAT checker: instance is UNSATISFIABLE" << messaget::eom;
289 status = statust::UNSAT;
290 return resultt::P_UNSATISFIABLE;
291 }
292
293 log.status() << "SAT checker: timed out or other error" << messaget::eom;
294 status = statust::ERROR;
295 return resultt::P_ERROR;
296 }
297 catch(const Minisat::OutOfMemoryException &)
298 {
299 log.error() << "SAT checker ran out of memory" << messaget::eom;
300 status=statust::ERROR;
301 return resultt::P_ERROR;
302 }
303}
304
305template<typename T>
307{
308 PRECONDITION(!a.is_constant());
309
310 try
311 {
312 unsigned v = a.var_no();
313 bool sign = a.sign();
314
315 // MiniSat2 kills the model in case of UNSAT
316 solver->model.growTo(v + 1);
317 value ^= sign;
318 solver->model[v] = Minisat::lbool(value);
319 }
320 catch(const Minisat::OutOfMemoryException &)
321 {
322 log.error() << "SAT checker ran out of memory" << messaget::eom;
323 status = statust::ERROR;
324 throw std::bad_alloc();
325 }
326}
327
328template <typename T>
330 message_handlert &message_handler)
331 : cnf_solvert(message_handler),
332 solver(std::make_unique<T>()),
333 time_limit_seconds(0)
334{
335}
336
337template <typename T>
339
340template<typename T>
342{
343 int v=a.var_no();
344
345 for(int i=0; i<solver->conflict.size(); i++)
346 if(var(solver->conflict[i])==v)
347 return true;
348
349 return false;
350}
351
354
356{
357 try
358 {
359 if(!a.is_constant())
360 {
362 solver->setFrozen(a.var_no(), true);
363 }
364 }
365 catch(const Minisat::OutOfMemoryException &)
366 {
367 log.error() << "SAT checker ran out of memory" << messaget::eom;
369 throw std::bad_alloc();
370 }
371}
372
374{
375 PRECONDITION(!a.is_constant());
376
377 return solver->isEliminated(a.var_no());
378}
static bool convert(const irep_idt &identifier, const std::ostringstream &s, symbol_table_baset &symbol_table, message_handlert &message_handler)
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
ait()
Definition ai.h:565
statust status
Definition cnf.h:87
mstreamt & error() const
Definition message.h:391
static eomt eom
Definition message.h:289
resultt
Definition prop.h:101
messaget log
Definition prop.h:134
bool is_in_conflict(literalt a) const override
Returns true if an assumption is in the final conflict.
std::unique_ptr< Minisat::SimpSolver > solver
~satcheck_minisat2_baset() override
A default destructor defined in the .cpp is used to ensure the unique_ptr to the solver is correctly ...
resultt do_prop_solve(const bvt &) override
satcheck_minisat2_baset(message_handlert &message_handler)
void set_polarity(literalt a, bool value)
void lcnf(const bvt &bv) override final
tvt l_get(literalt a) const override final
void set_assignment(literalt a, bool value) override
std::string solver_text() const override
void set_frozen(literalt a) override final
bool is_eliminated(literalt a) const
std::string solver_text() const override final
Definition threeval.h:20
static tvt unknown()
Definition threeval.h:33
std::vector< literalt > bvt
Definition literal.h:201
double log(double x)
Definition math.c:2449
STL namespace.
void convert_assumptions(const bvt &bv, Glucose::vec< Glucose::Lit > &dest)
static Minisat::Solver * solver_to_interrupt
static void interrupt_solver(int signum)
void convert_assumptions(const bvt &bv, Minisat::vec< Minisat::Lit > &dest)
void convert(const bvt &bv, Minisat::vec< Minisat::Lit > &dest)
#define l_True
#define l_False
void solver(std::vector< framet > &frames, const std::unordered_set< symbol_exprt, irep_hash > &address_taken, const solver_optionst &solver_options, const namespacet &ns, std::vector< propertyt > &properties, std::size_t property_index)
Definition solver.cpp:44
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423