CBMC
Loading...
Searching...
No Matches
qbf_bdd_core.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: CM Wintersteiger
6
7\*******************************************************************/
8
10
11#include <fstream>
12
13#include <util/arith_tools.h>
14#include <util/invariant.h>
15#include <util/std_expr.h>
16
17#include <cuddObj.hh> // CUDD Library
18
20// FIX FOR THE CUDD LIBRARY
21
22inline DdNode *DD::getNode() const
23{
24 return node;
25} // DD::getNode
29#include "qbf_bdd_core.h"
30
35
37{
38 for(const BDD* model : model_bdds)
39 {
40 if(model)
41 delete model;
42 }
43 model_bdds.clear();
44
45 delete(bdd_manager);
47}
48
50{
52
53 if(!is_quantified(l))
54 add_quantifier(quantifiert::EXISTENTIAL, l);
55
56 return l;
57}
58
64
66{
67 for(const BDD* variable : bdd_variable_map)
68 {
69 if(variable)
70 delete variable;
71 }
73
74 if(matrix)
75 {
76 delete(matrix);
78 }
79}
80
85
86std::string qbf_bdd_coret::solver_text() const
87{
88 return "QBF/BDD/CORE";
89}
90
92{
93 {
94 status() << solver_text() << ": "
95 << std::to_string(no_variables()) << " variables, "
96 << std::to_string(matrix->nodeCount()) << " nodes" << eom;
97 }
98
99 model_bdds.resize(no_variables()+1, NULL);
100
101 // Eliminate variables
102 for(auto it=quantifiers.rbegin();
103 it!=quantifiers.rend();
104 it++)
105 {
106 unsigned var=it->var_no;
107
108 if(it->type==quantifiert::EXISTENTIAL)
109 {
110 #if 0
111 std::cout << "BDD E: " << var << ", " <<
112 matrix->nodeCount() << " nodes\n";
113 #endif
114
115 BDD *model=new BDD();
116 const BDD &varbdd=*bdd_variable_map[var];
117 *model=matrix->AndAbstract(
118 varbdd.Xnor(bdd_manager->bddOne()),
119 varbdd);
120 model_bdds[var]=model;
121
122 *matrix=matrix->ExistAbstract(*bdd_variable_map[var]);
123 }
124 else
125 {
126 INVARIANT(
127 it->type == quantifiert::UNIVERSAL,
128 "only handles quantified variables");
129 #if 0
130 std::cout << "BDD A: " << var << ", " <<
131 matrix->nodeCount() << " nodes\n";
132 #endif
133
134 *matrix=matrix->UnivAbstract(*bdd_variable_map[var]);
135 }
136 }
137
138 if(*matrix==bdd_manager->bddOne())
139 {
141 return P_SATISFIABLE;
142 }
143 else if(*matrix==bdd_manager->bddZero())
144 {
145 model_bdds.clear();
146 return P_UNSATISFIABLE;
147 }
148 else
149 return P_ERROR;
150}
151
156
161
163{
165
166 bdd_variable_map.resize(res.var_no()+1, NULL);
167 BDD &var=*(new BDD());
168 var=bdd_manager->bddVar();
169 bdd_variable_map[res.var_no()]=&var;
170
171 return res;
172}
173
175{
176 bvt new_bv;
177
178 if(process_clause(bv, new_bv))
179 return;
180
181 BDD clause(bdd_manager->bddZero());
182
183 for(const literalt &l : new_bv)
184 {
185 BDD v(*bdd_variable_map[l.var_no()]);
186
187 if(l.sign())
188 v=~v;
189
190 clause|=v;
191 }
192
193 *matrix&=clause;
194}
195
197{
199
200 BDD abdd(*bdd_variable_map[a.var_no()]);
201 BDD bbdd(*bdd_variable_map[b.var_no()]);
202
203 if(a.sign())
204 abdd=~abdd;
205 if(b.sign())
206 bbdd=~bbdd;
207
208 *bdd_variable_map[nl.var_no()]|=abdd | bbdd;
209
210 return nl;
211}
212
214{
215 for(const literalt &literal : bv)
216 {
217 if(literal==const_literal(true))
218 return literal;
219 }
220
222
223 BDD &orbdd=*bdd_variable_map[nl.var_no()];
224
225 for(const literalt &literal : bv)
226 {
227 if(literal==const_literal(false))
228 continue;
229
230 BDD v(*bdd_variable_map[literal.var_no()]);
231 if(literal.sign())
232 v=~v;
233
234 orbdd|=v;
235 }
236
237 return nl;
238}
239
241{
242 status() << "Compressing Certificate" << eom;
243
245 {
246 if(quantifier.type==quantifiert::EXISTENTIAL)
247 {
248 const BDD &var=*bdd_variable_map[quantifier.var_no];
249 const BDD &model=*model_bdds[quantifier.var_no];
250
251 if(model==bdd_manager->bddOne() ||
252 model==bdd_manager->bddZero())
253 {
255 {
257
258 if(model==bdd_manager->bddZero())
259 model2=model2.AndAbstract(~var, var);
260 else
261 model2=model2.AndAbstract(var, var);
262 }
263 }
264 }
265 }
266}
267
269{
272 !find_quantifier(l, q), "no model for unquantified variables");
273
274 // universal?
275 if(q.type==quantifiert::UNIVERSAL)
276 {
277 INVARIANT(l.var_no() != 0, "input literal wasn't properly initialized");
278 variable_mapt::const_iterator it=variable_map.find(l.var_no());
279
280 INVARIANT(
281 it != variable_map.end(), "variable not found in the variable map");
282
283 const exprt &sym=it->second.first;
284 unsigned index=it->second.second;
285
287
288 if(l.sign())
289 extract_expr.negate();
290
291 return extract_expr;
292 }
293 else
294 {
295 // skolem functions for existentials
296 INVARIANT(
297 q.type == quantifiert::EXISTENTIAL,
298 "only quantified literals are supported");
299
300 function_cachet::const_iterator it=function_cache.find(l.var_no());
301 if(it!=function_cache.end())
302 {
303 #if 0
304 std::cout << "CACHE HIT for " << l.dimacs() << '\n';
305 #endif
306
307 if(l.sign())
308 return not_exprt(it->second);
309 else
310 return it->second;
311 }
312
313 // no cached function, so construct one
314
315 INVARIANT(
316 model_bdds[l.var_no()] != nullptr,
317 "there must be a model BDD for the literal");
318 BDD &model=*model_bdds[l.var_no()];
319
320 #if 0
321 std::cout << "Model " << l.var_no() << '\n';
322 model.PrintMinterm();
323 #endif
324
325 int *cube;
326 DdGen *generator;
327
328 or_exprt result;
329
331 bdd_manager->getManager(),
332 model.getNode(),
333 model.getNode(),
334 generator,
335 cube)
336 {
338
339 #if 0
340 std::cout << "CUBE: ";
341 for(signed i=0; i<bdd_manager->ReadSize(); i++)
342 std::cout << cube[i];
343 std::cout << '\n';
344 #endif
345
346 for(signed i=0; i<bdd_manager->ReadSize(); i++)
347 {
348 if(quantifiers[i].var_no==l.var_no())
349 break; // is this sound?
350
351 if(cube[i]!=2)
352 {
353 exprt subf=f_get(literalt(quantifiers[i].var_no, (cube[i]==1)));
354 prime.add_to_operands(std::move(subf));
355 }
356 }
357
359
360 if(prime.operands().empty())
362 else if(prime.operands().size()==1)
363 result.add_to_operands(std::move(prime.op0()));
364 else
365 result.add_to_operands(std::move(prime));
366 }
367
368 cube=NULL; // cube is free'd by nextCube
369
370 exprt final;
371
372 if(result.operands().empty())
373 final=false_exprt();
374 else if(result.operands().size()==1)
375 final=result.op0();
376 else
377 final=result;
378
379 function_cache[l.var_no()]=final;
380
381 if(l.sign())
382 return not_exprt(final);
383 else
384 return final;
385 }
386}
387
389{
390 const BDD &model=*model_bdds[a.var_no()];
391
392 if(model==bdd_manager->bddZero())
394 else if(model==bdd_manager->bddOne())
396 else
398}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
virtual void clear()
Reset the abstract state.
Definition ai.h:265
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
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 size_t no_variables() const override
Definition cnf.h:42
Base class for all expressions.
Definition expr.h:56
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition expr.h:163
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:3199
Unbounded, signed integers (mathematical integers, not bitvectors)
bool sign() const
Definition literal.h:88
int dimacs() const
Definition literal.h:117
var_not var_no() const
Definition literal.h:83
exprt & op0()
Definition std_expr.h:932
Boolean negation.
Definition std_expr.h:2454
Boolean OR.
Definition std_expr.h:2270
resultt
Definition prop.h:101
virtual literalt new_variable()=0
tvt l_get(literalt a) const override
model_bddst model_bdds
const exprt f_get(literalt l) override
~qbf_bdd_certificatet(void) override
function_cachet function_cache
literalt new_variable(void) override
Generate a new variable and return it as a literal.
literalt new_variable() override
Generate a new variable and return it as a literal.
void lcnf(const bvt &bv) override
bool is_in_core(literalt l) const override
resultt prop_solve() override
~qbf_bdd_coret() override
tvt l_get(literalt a) const override
bdd_variable_mapt bdd_variable_map
modeltypet m_get(literalt a) const override
std::string solver_text() const override
literalt lor(literalt a, literalt b) override
void compress_certificate(void)
virtual void add_quantifier(const quantifiert &quantifier)
Definition qdimacs_cnf.h:64
bool find_quantifier(const literalt l, quantifiert &q) const
quantifierst quantifiers
Definition qdimacs_cnf.h:62
bool is_quantified(const literalt l) const
void simplify_extractbits(exprt &expr) const
variable_mapt variable_map
The Boolean constant true.
Definition std_expr.h:3190
Definition threeval.h:20
std::vector< literalt > bvt
Definition literal.h:201
literalt const_literal(bool value)
Definition literal.h:188
#define PRECONDITION_WITH_DIAGNOSTICS(CONDITION,...)
Definition invariant.h:464
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define UNIMPLEMENTED
Definition invariant.h:558
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
API to expression classes.