CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
satcheck_glucose.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include "satcheck_glucose.h"
10
11#include <stack>
12
13#include <util/invariant.h>
14#include <util/threeval.h>
15
16#include <core/Solver.h>
17#include <simp/SimpSolver.h>
18
19#ifndef HAVE_GLUCOSE
20#error "Expected HAVE_GLUCOSE"
21#endif
22
23void convert(const bvt &bv, Glucose::vec<Glucose::Lit> &dest)
24{
25 dest.capacity(bv.size());
26
27 for(const auto &literal : bv)
28 {
29 if(!literal.is_false())
30 dest.push(Glucose::mkLit(literal.var_no(), literal.sign()));
31 }
32}
33
34void convert_assumptions(const bvt &bv, Glucose::vec<Glucose::Lit> &dest)
35{
36 dest.capacity(bv.size());
37
38 for(const auto &literal : bv)
39 {
40 if(!literal.is_true())
41 dest.push(Glucose::mkLit(literal.var_no(), literal.sign()));
42 }
43}
44
45template<typename T>
48 if(a.is_true())
49 return tvt(true);
50 else if(a.is_false())
51 return tvt(false);
52
53 tvt result;
54
55 if(a.var_no()>=(unsigned)solver->model.size())
57
58 using Glucose::lbool;
59
60 if(solver->model[a.var_no()]==l_True)
61 result=tvt(true);
62 else if(solver->model[a.var_no()]==l_False)
63 result=tvt(false);
64 else
66
67 if(a.sign())
68 result=!result;
69
70 return result;
71}
72
73template<typename T>
75{
76 PRECONDITION(!a.is_constant());
77
78 try
79 {
80 add_variables();
81 solver->setPolarity(a.var_no(), value);
82 }
83 catch(Glucose::OutOfMemoryException)
84 {
85 log.error() << "SAT checker ran out of memory" << messaget::eom;
86 status = statust::ERROR;
87 throw std::bad_alloc();
88 }
89}
90
92{
93 return "Glucose Syrup without simplifier";
94}
95
97{
98 return "Glucose Syrup with simplifier";
99}
100
101template<typename T>
103{
104 while((unsigned)solver->nVars()<no_variables())
105 solver->newVar();
106}
107
108template<typename T>
110{
111 try
112 {
113 add_variables();
114
115 for(const auto &literal : bv)
116 {
117 if(literal.is_true())
118 return;
119 else if(!literal.is_false())
120 {
121 INVARIANT(
122 literal.var_no() < (unsigned)solver->nVars(),
123 "variable not added yet");
124 }
125 }
126
127 Glucose::vec<Glucose::Lit> c;
128
129 convert(bv, c);
130
131 // Note the underscore.
132 // Add a clause to the solver without making superflous internal copy.
133
134 solver->addClause_(c);
135
136 if(solver_hardness)
137 {
138 // To map clauses to lines of program code, track clause indices in the
139 // dimacs cnf output. Dimacs output is generated after processing
140 // clauses to remove duplicates and clauses that are trivially true.
141 // Here, a clause is checked to see if it can be thus eliminated. If
142 // not, add the clause index to list of clauses in
143 // solver_hardnesst::register_clause().
144 static size_t cnf_clause_index = 0;
145 bvt cnf;
146 bool clause_removed = process_clause(bv, cnf);
147
148 if(!clause_removed)
150
151 solver_hardness->register_clause(
153 }
154
155 clause_counter++;
156 }
157 catch(Glucose::OutOfMemoryException)
158 {
159 log.error() << "SAT checker ran out of memory" << messaget::eom;
160 status = statust::ERROR;
161 throw std::bad_alloc();
162 }
163}
164
165template <typename T>
167{
168 PRECONDITION(status != statust::ERROR);
169
170 // We start counting at 1, thus there is one variable fewer.
171 log.statistics() << (no_variables() - 1) << " variables, "
172 << solver->nClauses() << " clauses" << messaget::eom;
173
174 try
175 {
176 add_variables();
177
178 if(!solver->okay())
179 {
180 log.status() << "SAT checker inconsistent: instance is UNSATISFIABLE"
181 << messaget::eom;
182 }
183 else
184 {
185 // if assumptions contains false, we need this to be UNSAT
186 bool has_false = false;
187
188 for(const auto &literal : assumptions)
189 {
190 if(literal.is_false())
191 has_false = true;
192 }
193
194 if(has_false)
195 {
196 log.status() << "got FALSE as assumption: instance is UNSATISFIABLE"
197 << messaget::eom;
198 }
199 else
200 {
201 Glucose::vec<Glucose::Lit> solver_assumptions;
203
204 if(solver->solve(solver_assumptions))
205 {
206 log.status() << "SAT checker: instance is SATISFIABLE"
207 << messaget::eom;
208 status = statust::SAT;
209 return resultt::P_SATISFIABLE;
210 }
211 else
212 {
213 log.status() << "SAT checker: instance is UNSATISFIABLE"
214 << messaget::eom;
215 }
216 }
217 }
218
219 status = statust::UNSAT;
220 return resultt::P_UNSATISFIABLE;
221 }
222 catch(Glucose::OutOfMemoryException)
223 {
224 log.error() << "SAT checker ran out of memory" << messaget::eom;
225 status = statust::ERROR;
226 throw std::bad_alloc();
227 }
228}
229
230template<typename T>
232{
233 PRECONDITION(!a.is_constant());
234
235 try
236 {
237 unsigned v = a.var_no();
238 bool sign = a.sign();
239
240 // MiniSat2 kills the model in case of UNSAT
241 solver->model.growTo(v + 1);
242 value ^= sign;
243 solver->model[v] = Glucose::lbool(value);
244 }
245 catch(Glucose::OutOfMemoryException)
246 {
247 log.error() << "SAT checker ran out of memory" << messaget::eom;
248 status = statust::ERROR;
249 throw std::bad_alloc();
250 }
251}
252
253template <typename T>
255 message_handlert &message_handler)
256 : cnf_solvert(message_handler), solver(std::make_unique<T>())
257{
258}
259
260template <typename T>
262
263template<typename T>
265{
266 int v=a.var_no();
267
268 for(int i=0; i<solver->conflict.size(); i++)
269 if(var(solver->conflict[i])==v)
270 return true;
271
272 return false;
273}
274
277
279{
280 try
281 {
282 if(!a.is_constant())
283 {
285 solver->setFrozen(a.var_no(), true);
286 }
287 }
288 catch(Glucose::OutOfMemoryException)
289 {
290 log.error() << "SAT checker ran out of memory" << messaget::eom;
292 throw std::bad_alloc();
293 }
294}
295
297{
298 PRECONDITION(!a.is_constant());
299
300 return solver->isEliminated(a.var_no());
301}
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.
~satcheck_glucose_baset() override
A default destructor defined in the .cpp is used to ensure the unique_ptr to the solver is correctly ...
void lcnf(const bvt &bv) override
std::unique_ptr< Glucose::SimpSolver > solver
void set_polarity(literalt a, bool value)
satcheck_glucose_baset(message_handlert &message_handler)
tvt l_get(literalt a) const override
resultt do_prop_solve(const bvt &assumptions) override
void set_assignment(literalt a, bool value) override
std::string solver_text() const override
void set_frozen(literalt a) override
std::string solver_text() const override
bool is_eliminated(literalt a) const
Definition threeval.h:20
std::vector< literalt > bvt
Definition literal.h:201
double log(double x)
Definition math.c:2449
STL namespace.
void convert(const bvt &bv, Glucose::vec< Glucose::Lit > &dest)
void convert_assumptions(const bvt &bv, Glucose::vec< Glucose::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 PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423