CBMC
qbf_squolem_core.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Squolem Backend (with proofs)
4 
5 Author: CM Wintersteiger
6 
7 \*******************************************************************/
8 
11 
12 #include "qbf_squolem_core.h"
13 
14 #include <algorithm>
15 
16 #include <util/std_expr.h>
17 #include <util/arith_tools.h>
18 
19 #include <util/c_types.h> // uint type for indices
20 
22 {
23  setup();
24 }
25 
27 {
28  quantifiers.clear();
29  clauses.clear();
30  early_decision=false;
31  variable_map.clear();
32  squolem=new Squolem2();
33 
34 // squolem->options.set_extractCoreVariables(true);
35 // squolem->options.set_saveCertificate(true);
36  squolem->options.set_keepModelFunctions(true);
37  squolem->options.set_keepResolutionProof(false);
38  squolem->options.set_freeOnExit(true);
39 // squolem->options.set_useExpansion(true);
40  squolem->options.set_debugFilename("debug.qdimacs");
41  squolem->options.set_saveDebugFile(true);
42  squolem->options.set_compressModel(true);
43 // squolem->options.set_showStatus(true);
44 // squolem->options.set_predictOnLiteralBound(true);
45 }
46 
48 {
49  squolem->reset();
50  delete(squolem);
51  squolem=NULL;
52  setup();
53 }
54 
56 {
57  squolem->reset();
58  delete(squolem);
59  squolem=NULL;
60 }
61 
63 {
64  if(a.is_true())
66  else if(a.is_false())
68  else if(squolem->modelIsTrue(a.var_no()))
70  else if(squolem->modelIsFalse(a.var_no()) ||
71  squolem->modelIsDontCare(a.var_no()))
73  else
75 }
76 
77 std::string qbf_squolem_coret::solver_text() const
78 {
79  return "Squolem (Certifying)";
80 }
81 
83 {
84  {
85  std::string msg=
86  "Squolem: "+
87  std::to_string(no_variables())+" variables, "+
88  std::to_string(no_clauses())+" clauses";
89  messaget::status() << msg << messaget::eom;
90  }
91 
92  squolem->endOfOriginals();
93  bool result=squolem->decide();
94 
95  if(result)
96  {
97  messaget::status() << "Squolem: VALID" << messaget::eom;
98  return P_SATISFIABLE;
99  }
100  else
101  {
102  messaget::status() << "Squolem: INVALID" << messaget::eom;
103  return P_UNSATISFIABLE;
104  }
105 
106  return P_ERROR;
107 }
108 
110 {
111  return squolem->inCore(l.var_no());
112 }
113 
115 {
116  if(squolem->modelIsTrue(a.var_no()))
117  return M_TRUE;
118  else if(squolem->modelIsFalse(a.var_no()))
119  return M_FALSE;
120  else if(squolem->modelIsComplex(a.var_no()))
121  return M_COMPLEX;
122  else
123  return M_DONTCARE;
124 }
125 
127 {
128  if(early_decision)
129  return; // we don't need no more...
130 
131  bvt new_bv;
132 
133  if(process_clause(bv, new_bv))
134  return;
135 
136  if(new_bv.empty())
137  {
138  early_decision=true;
139  return;
140  }
141 
142  std::vector<Literal> buffer(new_bv.size());
143  unsigned long i=0;
144  do
145  {
146  buffer[i]=new_bv[i].dimacs();
147  i++;
148  }
149  while(i<new_bv.size());
150 
151  if(!squolem->addClause(buffer))
152  early_decision=true;
153 }
154 
156 {
157  squolem->quantifyVariableInner(
158  quantifier.var_no,
159  quantifier.type==quantifiert::UNIVERSAL);
160 
161  qdimacs_cnft::add_quantifier(quantifier); // necessary?
162 }
163 
165 {
166  squolem->setLastVariable(no+1);
168 }
169 
171  const quantifiert::typet type,
172  const literalt l)
173 {
175  squolem->requantifyVariable(l.var_no(), type==quantifiert::UNIVERSAL);
176 }
177 
178 void qbf_squolem_coret::set_debug_filename(const std::string &str)
179 {
180  squolem->options.set_debugFilename(str.c_str());
181 }
182 
184 {
185  squolem->saveQCNF(out);
186 }
187 
189 {
190  if(squolem->isUniversal(l.var_no()))
191  {
193  l.var_no() != 0, "unknown variable: ", std::to_string(l.var_no()));
194  variable_mapt::const_iterator it=variable_map.find(l.var_no());
195 
196  INVARIANT(
197  it != variable_map.end(), "variable not found in the variable map");
198 
199  const exprt &sym=it->second.first;
200  unsigned index=it->second.second;
201 
202  extractbit_exprt extract_expr(sym, from_integer(index, integer_typet()));
203 
204  if(l.sign())
205  extract_expr.negate();
206 
207  return extract_expr;
208  }
209 
210  function_cachet::const_iterator it=function_cache.find(l.var_no());
211  if(it!=function_cache.end())
212  {
213  #if 0
214  std::cout << "CACHE HIT for " << l.dimacs() << '\n';
215  #endif
216 
217  if(l.sign())
218  return not_exprt(it->second);
219  else
220  return it->second;
221  }
222  else
223  {
224  WitnessStack *wsp=squolem->getModelFunction(Literal(l.dimacs()));
225  exprt res;
226 
227  if(wsp==NULL || wsp->empty())
228  {
229 // res=exprt(ID_nondet_bool, typet(ID_bool));
230  res=false_exprt(); // just set it to zero
231  }
232  else if(wsp->pSize<=wsp->nSize)
233  res=f_get_cnf(wsp);
234  else
235  res=f_get_dnf(wsp);
236 
237  function_cache[l.var_no()]=res;
238 
239  if(l.sign())
240  return not_exprt(res);
241  else
242  return res;
243  }
244 }
245 
246 const exprt qbf_squolem_coret::f_get_cnf(WitnessStack *wsp)
247 {
248  Clause *p=wsp->negWits;
249 
250  if(!p)
251  return exprt(ID_true, typet(ID_bool));
252 
253  exprt::operandst operands;
254 
255  while(p!=NULL)
256  {
257  or_exprt clause;
258 
259  for(unsigned i=0; i<p->size; i++)
260  {
261  const Literal &lit=p->literals[i];
262  exprt subf=f_get(literalt(var(lit), isPositive(lit))); // negated!
263  if(find(clause.operands().begin(), clause.operands().end(), subf)==
264  clause.operands().end())
265  clause.add_to_operands(std::move(subf));
266  }
267 
268  if(clause.operands().empty())
269  clause=false_exprt();
270  else if(clause.operands().size()==1)
271  {
272  const exprt tmp=clause.op0();
273  clause=tmp;
274  }
275 
276  #if 0
277  std::cout << "CLAUSE: " << clause << '\n';
278  #endif
279 
280  operands.push_back(clause);
281 
282  p=p->next;
283  }
284 
285  return and_exprt(operands);
286 }
287 
288 const exprt qbf_squolem_coret::f_get_dnf(WitnessStack *wsp)
289 {
290  Clause *p=wsp->posWits;
291 
292  if(!p)
293  return exprt(ID_false, typet(ID_bool));
294 
295  exprt::operandst operands;
296 
297  while(p!=NULL)
298  {
299  and_exprt cube;
300 
301  for(unsigned i=0; i<p->size; i++)
302  {
303  const Literal &lit=p->literals[i];
304  exprt subf=f_get(literalt(var(lit), !isPositive(lit)));
305  if(find(cube.operands().begin(), cube.operands().end(), subf)==
306  cube.operands().end())
307  cube.add_to_operands(std::move(subf));
308 
309  simplify_extractbits(cube);
310  }
311 
312  if(cube.operands().empty())
313  cube=true_exprt();
314  else if(cube.operands().size()==1)
315  {
316  const exprt tmp=cube.op0();
317  cube=tmp;
318  }
319 
320  #if 0
321  std::cout << "CUBE: " << cube << '\n';
322  #endif
323 
324  operands.push_back(cube);
325 
326  p=p->next;
327  }
328 
329  return or_exprt(operands);
330 }
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:99
Boolean AND.
Definition: std_expr.h:2125
bool process_clause(const bvt &bv, bvt &dest) const
filter 'true' from clause, eliminate duplicates, recognise trivially satisfied clauses
Definition: cnf.cpp:424
virtual void set_no_variables(size_t no)
Definition: cnf.h:43
virtual size_t no_variables() const override
Definition: cnf.h:42
Base class for all expressions.
Definition: expr.h:56
std::vector< exprt > operandst
Definition: expr.h:58
operandst & operands()
Definition: expr.h:94
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:170
Extracts a single bit of a bit-vector operand.
The Boolean constant false.
Definition: std_expr.h:3082
Unbounded, signed integers (mathematical integers, not bitvectors)
bool is_true() const
Definition: literal.h:156
bool sign() const
Definition: literal.h:88
int dimacs() const
Definition: literal.h:117
var_not var_no() const
Definition: literal.h:83
bool is_false() const
Definition: literal.h:161
mstreamt & status() const
Definition: message.h:406
static eomt eom
Definition: message.h:289
exprt & op0()
Definition: std_expr.h:932
Boolean negation.
Definition: std_expr.h:2337
Boolean OR.
Definition: std_expr.h:2233
resultt
Definition: prop.h:101
void set_quantifier(const quantifiert::typet type, const literalt l) override
void set_debug_filename(const std::string &str)
~qbf_squolem_coret() override
const exprt f_get_cnf(WitnessStack *wsp)
void set_no_variables(size_t no) override
void lcnf(const bvt &bv) override
void write_qdimacs_cnf(std::ostream &out) override
const exprt f_get(literalt l) override
function_cachet function_cache
void add_quantifier(const quantifiert &quantifier) override
std::string solver_text() const override
bool is_in_core(literalt l) const override
const exprt f_get_dnf(WitnessStack *wsp)
resultt prop_solve() override
modeltypet m_get(literalt a) const override
tvt l_get(literalt a) const override
virtual size_t no_clauses() const
virtual void add_quantifier(const quantifiert &quantifier)
Definition: qdimacs_cnf.h:64
virtual void set_quantifier(const quantifiert::typet type, const literalt l)
Definition: qdimacs_cnf.cpp:73
quantifierst quantifiers
Definition: qdimacs_cnf.h:62
void simplify_extractbits(exprt &expr) const
variable_mapt variable_map
Definition: qdimacs_core.h:35
The Boolean constant true.
Definition: std_expr.h:3073
Definition: threeval.h:20
The type of an expression, extends irept.
Definition: type.h:29
std::vector< literalt > bvt
Definition: literal.h:201
Squolem Backend (with Proofs)
#define INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Same as invariant, with one or more diagnostics attached Diagnostics can be of any type that has a sp...
Definition: invariant.h:437
API to expression classes.
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.