CBMC
satcheck_glucose.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: 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 
23 void 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 
34 void 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 
45 template<typename T>
47 {
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 
73 template<typename T>
75 {
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 
101 template<typename T>
103 {
104  while((unsigned)solver->nVars()<no_variables())
105  solver->newVar();
106 }
107 
108 template<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)
149  cnf_clause_index++;
150 
151  solver_hardness->register_clause(
152  bv, cnf, cnf_clause_index, !clause_removed);
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 
165 template <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;
202  convert_assumptions(assumptions, 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 
230 template<typename T>
232 {
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 
253 template <typename T>
255  message_handlert &message_handler)
256  : cnf_solvert(message_handler), solver(std::make_unique<T>())
257 {
258 }
259 
260 template <typename T>
262 
263 template<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  {
284  add_variables();
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 {
299 
300  return solver->isEliminated(a.var_no());
301 }
statust status
Definition: cnf.h:87
bool is_true() const
Definition: literal.h:156
bool sign() const
Definition: literal.h:88
bool is_constant() const
Definition: literal.h:166
var_not var_no() const
Definition: literal.h:83
bool is_false() const
Definition: literal.h:161
mstreamt & error() const
Definition: message.h:399
static eomt eom
Definition: message.h:297
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:2776
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