1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Mathias Preiner, Liana Hadarean, Andrew Reynolds |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 by the authors listed in the file AUTHORS |
8 |
|
* in the top-level source directory and their institutional affiliations. |
9 |
|
* All rights reserved. See the file COPYING in the top-level source |
10 |
|
* directory for licensing information. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* Lazy bit-vector solver. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/bv/bv_solver_lazy.h" |
17 |
|
|
18 |
|
#include "expr/node_algorithm.h" |
19 |
|
#include "options/bv_options.h" |
20 |
|
#include "options/smt_options.h" |
21 |
|
#include "smt/smt_statistics_registry.h" |
22 |
|
#include "theory/bv/abstraction.h" |
23 |
|
#include "theory/bv/bv_eager_solver.h" |
24 |
|
#include "theory/bv/bv_subtheory_algebraic.h" |
25 |
|
#include "theory/bv/bv_subtheory_bitblast.h" |
26 |
|
#include "theory/bv/bv_subtheory_core.h" |
27 |
|
#include "theory/bv/bv_subtheory_inequality.h" |
28 |
|
#include "theory/bv/theory_bv_rewrite_rules_normalization.h" |
29 |
|
#include "theory/bv/theory_bv_rewrite_rules_simplification.h" |
30 |
|
#include "theory/bv/theory_bv_rewriter.h" |
31 |
|
#include "theory/bv/theory_bv_utils.h" |
32 |
|
#include "theory/theory_model.h" |
33 |
|
|
34 |
|
using namespace cvc5::theory::bv::utils; |
35 |
|
|
36 |
|
namespace cvc5 { |
37 |
|
namespace theory { |
38 |
|
namespace bv { |
39 |
|
|
40 |
9444 |
BVSolverLazy::BVSolverLazy(TheoryBV& bv, |
41 |
|
context::Context* c, |
42 |
|
context::UserContext* u, |
43 |
|
ProofNodeManager* pnm, |
44 |
9444 |
std::string name) |
45 |
|
: BVSolver(bv.d_state, bv.d_im), |
46 |
|
d_bv(bv), |
47 |
|
d_context(c), |
48 |
|
d_alreadyPropagatedSet(c), |
49 |
|
d_sharedTermsSet(c), |
50 |
|
d_subtheories(), |
51 |
|
d_subtheoryMap(), |
52 |
|
d_statistics(), |
53 |
|
d_staticLearnCache(), |
54 |
|
d_lemmasAdded(c, false), |
55 |
|
d_conflict(c, false), |
56 |
|
d_invalidateModelCache(c, true), |
57 |
|
d_literalsToPropagate(c), |
58 |
|
d_literalsToPropagateIndex(c, 0), |
59 |
|
d_propagatedBy(c), |
60 |
|
d_eagerSolver(), |
61 |
28332 |
d_abstractionModule(new AbstractionModule(getStatsPrefix(THEORY_BV))), |
62 |
37776 |
d_calledPreregister(false) |
63 |
|
{ |
64 |
9444 |
if (options::bitblastMode() == options::BitblastMode::EAGER) |
65 |
|
{ |
66 |
39 |
d_eagerSolver.reset(new EagerBitblastSolver(c, this)); |
67 |
39 |
return; |
68 |
|
} |
69 |
|
|
70 |
9405 |
if (options::bitvectorEqualitySolver()) |
71 |
|
{ |
72 |
9403 |
d_subtheories.emplace_back(new CoreSolver(c, this)); |
73 |
9403 |
d_subtheoryMap[SUB_CORE] = d_subtheories.back().get(); |
74 |
|
} |
75 |
|
|
76 |
18810 |
if (options::bitvectorInequalitySolver()) |
77 |
|
{ |
78 |
9405 |
d_subtheories.emplace_back(new InequalitySolver(c, u, this)); |
79 |
9405 |
d_subtheoryMap[SUB_INEQUALITY] = d_subtheories.back().get(); |
80 |
|
} |
81 |
|
|
82 |
9405 |
if (options::bitvectorAlgebraicSolver()) |
83 |
|
{ |
84 |
|
d_subtheories.emplace_back(new AlgebraicSolver(c, this)); |
85 |
|
d_subtheoryMap[SUB_ALGEBRAIC] = d_subtheories.back().get(); |
86 |
|
} |
87 |
|
|
88 |
9405 |
BitblastSolver* bb_solver = new BitblastSolver(c, this); |
89 |
9405 |
if (options::bvAbstraction()) |
90 |
|
{ |
91 |
2 |
bb_solver->setAbstraction(d_abstractionModule.get()); |
92 |
|
} |
93 |
9405 |
d_subtheories.emplace_back(bb_solver); |
94 |
9405 |
d_subtheoryMap[SUB_BITBLAST] = bb_solver; |
95 |
|
} |
96 |
|
|
97 |
18888 |
BVSolverLazy::~BVSolverLazy() {} |
98 |
|
|
99 |
9444 |
bool BVSolverLazy::needsEqualityEngine(EeSetupInfo& esi) |
100 |
|
{ |
101 |
9444 |
CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE]; |
102 |
9444 |
if (core) |
103 |
|
{ |
104 |
9403 |
return core->needsEqualityEngine(esi); |
105 |
|
} |
106 |
|
// otherwise we don't use an equality engine |
107 |
41 |
return false; |
108 |
|
} |
109 |
|
|
110 |
9444 |
void BVSolverLazy::finishInit() |
111 |
|
{ |
112 |
9444 |
CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE]; |
113 |
9444 |
if (core) |
114 |
|
{ |
115 |
|
// must finish initialization in the core solver |
116 |
9403 |
core->finishInit(); |
117 |
|
} |
118 |
9444 |
} |
119 |
|
|
120 |
489872 |
void BVSolverLazy::spendResource(Resource r) |
121 |
|
{ |
122 |
489872 |
d_im.spendResource(r); |
123 |
489872 |
} |
124 |
|
|
125 |
9444 |
BVSolverLazy::Statistics::Statistics() |
126 |
9444 |
: d_avgConflictSize(smtStatisticsRegistry().registerAverage( |
127 |
18888 |
"theory::bv::lazy::AvgBVConflictSize")), |
128 |
9444 |
d_solveTimer(smtStatisticsRegistry().registerTimer( |
129 |
18888 |
"theory::bv::lazy::solveTimer")), |
130 |
9444 |
d_numCallsToCheckFullEffort(smtStatisticsRegistry().registerInt( |
131 |
18888 |
"theory::bv::lazy::NumFullCheckCalls")), |
132 |
9444 |
d_numCallsToCheckStandardEffort(smtStatisticsRegistry().registerInt( |
133 |
18888 |
"theory::bv::lazy::NumStandardCheckCalls")), |
134 |
9444 |
d_weightComputationTimer(smtStatisticsRegistry().registerTimer( |
135 |
18888 |
"theory::bv::lazy::weightComputationTimer")), |
136 |
9444 |
d_numMultSlice(smtStatisticsRegistry().registerInt( |
137 |
56664 |
"theory::bv::lazy::NumMultSliceApplied")) |
138 |
|
{ |
139 |
9444 |
} |
140 |
|
|
141 |
223289 |
void BVSolverLazy::preRegisterTerm(TNode node) |
142 |
|
{ |
143 |
223289 |
d_calledPreregister = true; |
144 |
446578 |
Debug("bitvector-preregister") |
145 |
223289 |
<< "BVSolverLazy::preRegister(" << node << ")" << std::endl; |
146 |
|
|
147 |
223289 |
if (options::bitblastMode() == options::BitblastMode::EAGER) |
148 |
|
{ |
149 |
|
// the aig bit-blaster option is set heuristically |
150 |
|
// if bv abstraction is used |
151 |
1996 |
if (!d_eagerSolver->isInitialized()) |
152 |
|
{ |
153 |
27 |
d_eagerSolver->initialize(); |
154 |
|
} |
155 |
|
|
156 |
1996 |
if (node.getKind() == kind::BITVECTOR_EAGER_ATOM) |
157 |
|
{ |
158 |
612 |
Node formula = node[0]; |
159 |
306 |
d_eagerSolver->assertFormula(formula); |
160 |
|
} |
161 |
1996 |
return; |
162 |
|
} |
163 |
|
|
164 |
885158 |
for (unsigned i = 0; i < d_subtheories.size(); ++i) |
165 |
|
{ |
166 |
663865 |
d_subtheories[i]->preRegister(node); |
167 |
|
} |
168 |
|
|
169 |
|
// AJR : equality solver currently registers all terms to ExtTheory, if we |
170 |
|
// want a lazy reduction without the bv equality solver, need to call this |
171 |
|
// d_bv.d_extTheory->registerTermRec( node ); |
172 |
|
} |
173 |
|
|
174 |
15249 |
void BVSolverLazy::sendConflict() |
175 |
|
{ |
176 |
15249 |
Assert(d_conflict); |
177 |
15249 |
if (d_conflictNode.isNull()) |
178 |
|
{ |
179 |
|
return; |
180 |
|
} |
181 |
|
else |
182 |
|
{ |
183 |
30498 |
Debug("bitvector") << indent() << "BVSolverLazy::check(): conflict " |
184 |
15249 |
<< d_conflictNode << std::endl; |
185 |
15249 |
d_im.conflict(d_conflictNode, InferenceId::BV_LAZY_CONFLICT); |
186 |
15249 |
d_statistics.d_avgConflictSize << d_conflictNode.getNumChildren(); |
187 |
15249 |
d_conflictNode = Node::null(); |
188 |
|
} |
189 |
|
} |
190 |
|
|
191 |
1397643 |
void BVSolverLazy::checkForLemma(TNode fact) |
192 |
|
{ |
193 |
1397643 |
if (fact.getKind() == kind::EQUAL) |
194 |
|
{ |
195 |
458007 |
NodeManager* nm = NodeManager::currentNM(); |
196 |
458007 |
if (fact[0].getKind() == kind::BITVECTOR_UREM) |
197 |
|
{ |
198 |
1894 |
TNode urem = fact[0]; |
199 |
1894 |
TNode result = fact[1]; |
200 |
1894 |
TNode divisor = urem[1]; |
201 |
1894 |
Node result_ult_div = nm->mkNode(kind::BITVECTOR_ULT, result, divisor); |
202 |
|
Node divisor_eq_0 = |
203 |
1894 |
nm->mkNode(kind::EQUAL, divisor, mkZero(getSize(divisor))); |
204 |
|
Node split = nm->mkNode( |
205 |
1894 |
kind::OR, divisor_eq_0, nm->mkNode(kind::NOT, fact), result_ult_div); |
206 |
947 |
lemma(split); |
207 |
|
} |
208 |
458007 |
if (fact[1].getKind() == kind::BITVECTOR_UREM) |
209 |
|
{ |
210 |
124 |
TNode urem = fact[1]; |
211 |
124 |
TNode result = fact[0]; |
212 |
124 |
TNode divisor = urem[1]; |
213 |
124 |
Node result_ult_div = nm->mkNode(kind::BITVECTOR_ULT, result, divisor); |
214 |
|
Node divisor_eq_0 = |
215 |
124 |
nm->mkNode(kind::EQUAL, divisor, mkZero(getSize(divisor))); |
216 |
|
Node split = nm->mkNode( |
217 |
124 |
kind::OR, divisor_eq_0, nm->mkNode(kind::NOT, fact), result_ult_div); |
218 |
62 |
lemma(split); |
219 |
|
} |
220 |
|
} |
221 |
1397643 |
} |
222 |
|
|
223 |
238457 |
bool BVSolverLazy::preCheck(Theory::Effort e) |
224 |
|
{ |
225 |
238457 |
check(e); |
226 |
238457 |
return true; |
227 |
|
} |
228 |
|
|
229 |
238457 |
void BVSolverLazy::check(Theory::Effort e) |
230 |
|
{ |
231 |
238457 |
if (done() && e < Theory::EFFORT_FULL) |
232 |
|
{ |
233 |
15503 |
return; |
234 |
|
} |
235 |
|
|
236 |
|
// last call : do reductions on extended bitvector functions |
237 |
238457 |
if (e == Theory::EFFORT_LAST_CALL) |
238 |
|
{ |
239 |
|
CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE]; |
240 |
|
if (core) |
241 |
|
{ |
242 |
|
// check extended functions at last call effort |
243 |
|
core->checkExtf(e); |
244 |
|
} |
245 |
|
return; |
246 |
|
} |
247 |
|
|
248 |
238457 |
Debug("bitvector") << "BVSolverLazy::check(" << e << ")" << std::endl; |
249 |
461411 |
TimerStat::CodeTimer codeTimer(d_statistics.d_solveTimer); |
250 |
|
// we may be getting new assertions so the model cache may not be sound |
251 |
238457 |
d_invalidateModelCache.set(true); |
252 |
|
// if we are using the eager solver |
253 |
238457 |
if (options::bitblastMode() == options::BitblastMode::EAGER) |
254 |
|
{ |
255 |
|
// this can only happen on an empty benchmark |
256 |
254 |
if (!d_eagerSolver->isInitialized()) |
257 |
|
{ |
258 |
2 |
d_eagerSolver->initialize(); |
259 |
|
} |
260 |
254 |
if (!Theory::fullEffort(e)) return; |
261 |
|
|
262 |
106 |
std::vector<TNode> assertions; |
263 |
681 |
while (!done()) |
264 |
|
{ |
265 |
628 |
TNode fact = get().d_assertion; |
266 |
314 |
Assert(fact.getKind() == kind::BITVECTOR_EAGER_ATOM); |
267 |
314 |
assertions.push_back(fact); |
268 |
314 |
d_eagerSolver->assertFormula(fact[0]); |
269 |
|
} |
270 |
|
|
271 |
53 |
bool ok = d_eagerSolver->checkSat(); |
272 |
53 |
if (!ok) |
273 |
|
{ |
274 |
20 |
if (assertions.size() == 1) |
275 |
|
{ |
276 |
6 |
d_im.conflict(assertions[0], InferenceId::BV_LAZY_CONFLICT); |
277 |
6 |
return; |
278 |
|
} |
279 |
28 |
Node conflict = utils::mkAnd(assertions); |
280 |
14 |
d_im.conflict(conflict, InferenceId::BV_LAZY_CONFLICT); |
281 |
14 |
return; |
282 |
|
} |
283 |
33 |
return; |
284 |
|
} |
285 |
|
|
286 |
238203 |
if (Theory::fullEffort(e)) |
287 |
|
{ |
288 |
30936 |
++(d_statistics.d_numCallsToCheckFullEffort); |
289 |
|
} |
290 |
|
else |
291 |
|
{ |
292 |
207267 |
++(d_statistics.d_numCallsToCheckStandardEffort); |
293 |
|
} |
294 |
|
// if we are already in conflict just return the conflict |
295 |
238203 |
if (inConflict()) |
296 |
|
{ |
297 |
|
sendConflict(); |
298 |
|
return; |
299 |
|
} |
300 |
|
|
301 |
3033489 |
while (!done()) |
302 |
|
{ |
303 |
2795286 |
TNode fact = get().d_assertion; |
304 |
|
|
305 |
1397643 |
checkForLemma(fact); |
306 |
|
|
307 |
5590564 |
for (unsigned i = 0; i < d_subtheories.size(); ++i) |
308 |
|
{ |
309 |
4192921 |
d_subtheories[i]->assertFact(fact); |
310 |
|
} |
311 |
|
} |
312 |
|
|
313 |
238203 |
bool ok = true; |
314 |
238203 |
bool complete = false; |
315 |
639221 |
for (unsigned i = 0; i < d_subtheories.size(); ++i) |
316 |
|
{ |
317 |
639221 |
Assert(!inConflict()); |
318 |
639221 |
ok = d_subtheories[i]->check(e); |
319 |
639221 |
complete = d_subtheories[i]->isComplete(); |
320 |
|
|
321 |
639221 |
if (!ok) |
322 |
|
{ |
323 |
|
// if we are in a conflict no need to check with other theories |
324 |
15249 |
Assert(inConflict()); |
325 |
15249 |
sendConflict(); |
326 |
15249 |
return; |
327 |
|
} |
328 |
623972 |
if (complete) |
329 |
|
{ |
330 |
|
// if the last subtheory was complete we stop |
331 |
222954 |
break; |
332 |
|
} |
333 |
|
} |
334 |
|
|
335 |
|
// check extended functions |
336 |
222954 |
if (Theory::fullEffort(e)) |
337 |
|
{ |
338 |
25784 |
CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE]; |
339 |
25784 |
if (core) |
340 |
|
{ |
341 |
|
// check extended functions at full effort |
342 |
25782 |
core->checkExtf(e); |
343 |
|
} |
344 |
|
} |
345 |
|
} |
346 |
|
|
347 |
8473 |
bool BVSolverLazy::needsCheckLastEffort() |
348 |
|
{ |
349 |
8473 |
CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE]; |
350 |
8473 |
if (core) |
351 |
|
{ |
352 |
8438 |
return core->needsCheckLastEffort(); |
353 |
|
} |
354 |
35 |
return false; |
355 |
|
} |
356 |
|
|
357 |
7158 |
bool BVSolverLazy::collectModelValues(TheoryModel* m, |
358 |
|
const std::set<Node>& termSet) |
359 |
|
{ |
360 |
7158 |
Assert(!inConflict()); |
361 |
7158 |
if (options::bitblastMode() == options::BitblastMode::EAGER) |
362 |
|
{ |
363 |
9 |
if (!d_eagerSolver->collectModelInfo(m, true)) |
364 |
|
{ |
365 |
|
return false; |
366 |
|
} |
367 |
|
} |
368 |
13560 |
for (unsigned i = 0; i < d_subtheories.size(); ++i) |
369 |
|
{ |
370 |
13551 |
if (d_subtheories[i]->isComplete()) |
371 |
|
{ |
372 |
7149 |
return d_subtheories[i]->collectModelValues(m, termSet); |
373 |
|
} |
374 |
|
} |
375 |
9 |
return true; |
376 |
|
} |
377 |
|
|
378 |
|
Node BVSolverLazy::getModelValue(TNode var) |
379 |
|
{ |
380 |
|
Assert(!inConflict()); |
381 |
|
for (unsigned i = 0; i < d_subtheories.size(); ++i) |
382 |
|
{ |
383 |
|
if (d_subtheories[i]->isComplete()) |
384 |
|
{ |
385 |
|
return d_subtheories[i]->getModelValue(var); |
386 |
|
} |
387 |
|
} |
388 |
|
Unreachable(); |
389 |
|
} |
390 |
|
|
391 |
829493 |
void BVSolverLazy::propagate(Theory::Effort e) |
392 |
|
{ |
393 |
829493 |
Debug("bitvector") << indent() << "BVSolverLazy::propagate()" << std::endl; |
394 |
829493 |
if (options::bitblastMode() == options::BitblastMode::EAGER) |
395 |
|
{ |
396 |
234 |
return; |
397 |
|
} |
398 |
|
|
399 |
829259 |
if (inConflict()) |
400 |
|
{ |
401 |
|
return; |
402 |
|
} |
403 |
|
|
404 |
|
// go through stored propagations |
405 |
829259 |
bool ok = true; |
406 |
2535653 |
for (; d_literalsToPropagateIndex < d_literalsToPropagate.size() && ok; |
407 |
1137596 |
d_literalsToPropagateIndex = d_literalsToPropagateIndex + 1) |
408 |
|
{ |
409 |
1137596 |
TNode literal = d_literalsToPropagate[d_literalsToPropagateIndex]; |
410 |
|
// temporary fix for incremental bit-blasting |
411 |
568798 |
if (d_state.isSatLiteral(literal)) |
412 |
|
{ |
413 |
1062380 |
Debug("bitvector::propagate") |
414 |
531190 |
<< "BVSolverLazy:: propagating " << literal << "\n"; |
415 |
531190 |
ok = d_im.propagateLit(literal); |
416 |
|
} |
417 |
|
} |
418 |
|
|
419 |
829259 |
if (!ok) |
420 |
|
{ |
421 |
|
Debug("bitvector::propagate") |
422 |
|
<< indent() << "BVSolverLazy::propagate(): conflict from theory engine" |
423 |
|
<< std::endl; |
424 |
|
setConflict(); |
425 |
|
} |
426 |
|
} |
427 |
|
|
428 |
315684 |
TrustNode BVSolverLazy::ppRewrite(TNode t) |
429 |
|
{ |
430 |
315684 |
Debug("bv-pp-rewrite") << "BVSolverLazy::ppRewrite " << t << "\n"; |
431 |
631368 |
Node res = t; |
432 |
631368 |
if (options::bitwiseEq() && RewriteRule<BitwiseEq>::applies(t)) |
433 |
|
{ |
434 |
840 |
Node result = RewriteRule<BitwiseEq>::run<false>(t); |
435 |
420 |
res = Rewriter::rewrite(result); |
436 |
|
} |
437 |
315264 |
else if (RewriteRule<UltAddOne>::applies(t)) |
438 |
|
{ |
439 |
108 |
Node result = RewriteRule<UltAddOne>::run<false>(t); |
440 |
54 |
res = Rewriter::rewrite(result); |
441 |
|
} |
442 |
630420 |
else if (res.getKind() == kind::EQUAL |
443 |
945634 |
&& ((res[0].getKind() == kind::BITVECTOR_ADD |
444 |
316010 |
&& RewriteRule<ConcatToMult>::applies(res[1])) |
445 |
332688 |
|| (res[1].getKind() == kind::BITVECTOR_ADD |
446 |
315636 |
&& RewriteRule<ConcatToMult>::applies(res[0])))) |
447 |
|
{ |
448 |
8 |
Node mult = RewriteRule<ConcatToMult>::applies(res[0]) |
449 |
|
? RewriteRule<ConcatToMult>::run<false>(res[0]) |
450 |
8 |
: RewriteRule<ConcatToMult>::run<true>(res[1]); |
451 |
8 |
Node factor = mult[0]; |
452 |
8 |
Node sum = RewriteRule<ConcatToMult>::applies(res[0]) ? res[1] : res[0]; |
453 |
8 |
Node new_eq = NodeManager::currentNM()->mkNode(kind::EQUAL, sum, mult); |
454 |
8 |
Node rewr_eq = RewriteRule<SolveEq>::run<true>(new_eq); |
455 |
4 |
if (rewr_eq[0].isVar() || rewr_eq[1].isVar()) |
456 |
|
{ |
457 |
4 |
res = Rewriter::rewrite(rewr_eq); |
458 |
|
} |
459 |
|
else |
460 |
|
{ |
461 |
|
res = t; |
462 |
|
} |
463 |
|
} |
464 |
315206 |
else if (RewriteRule<SignExtendEqConst>::applies(t)) |
465 |
|
{ |
466 |
346 |
res = RewriteRule<SignExtendEqConst>::run<false>(t); |
467 |
|
} |
468 |
314860 |
else if (RewriteRule<ZeroExtendEqConst>::applies(t)) |
469 |
|
{ |
470 |
|
res = RewriteRule<ZeroExtendEqConst>::run<false>(t); |
471 |
|
} |
472 |
314860 |
else if (RewriteRule<NormalizeEqAddNeg>::applies(t)) |
473 |
|
{ |
474 |
1216 |
res = RewriteRule<NormalizeEqAddNeg>::run<false>(t); |
475 |
|
} |
476 |
|
|
477 |
|
// if(t.getKind() == kind::EQUAL && |
478 |
|
// ((t[0].getKind() == kind::BITVECTOR_MULT && t[1].getKind() == |
479 |
|
// kind::BITVECTOR_ADD) || |
480 |
|
// (t[1].getKind() == kind::BITVECTOR_MULT && t[0].getKind() == |
481 |
|
// kind::BITVECTOR_ADD))) { |
482 |
|
// // if we have an equality between a multiplication and addition |
483 |
|
// // try to express multiplication in terms of addition |
484 |
|
// Node mult = t[0].getKind() == kind::BITVECTOR_MULT? t[0] : t[1]; |
485 |
|
// Node add = t[0].getKind() == kind::BITVECTOR_ADD? t[0] : t[1]; |
486 |
|
// if (RewriteRule<MultSlice>::applies(mult)) { |
487 |
|
// Node new_mult = RewriteRule<MultSlice>::run<false>(mult); |
488 |
|
// Node new_eq = |
489 |
|
// Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::EQUAL, |
490 |
|
// new_mult, add)); |
491 |
|
|
492 |
|
// // the simplification can cause the formula to blow up |
493 |
|
// // only apply if formula reduced |
494 |
|
// if (d_subtheoryMap.find(SUB_BITBLAST) != d_subtheoryMap.end()) { |
495 |
|
// BitblastSolver* bv = (BitblastSolver*)d_subtheoryMap[SUB_BITBLAST]; |
496 |
|
// uint64_t old_size = bv->computeAtomWeight(t); |
497 |
|
// Assert (old_size); |
498 |
|
// uint64_t new_size = bv->computeAtomWeight(new_eq); |
499 |
|
// double ratio = ((double)new_size)/old_size; |
500 |
|
// if (ratio <= 0.4) { |
501 |
|
// ++(d_statistics.d_numMultSlice); |
502 |
|
// return new_eq; |
503 |
|
// } |
504 |
|
// } |
505 |
|
|
506 |
|
// if (new_eq.getKind() == kind::CONST_BOOLEAN) { |
507 |
|
// ++(d_statistics.d_numMultSlice); |
508 |
|
// return new_eq; |
509 |
|
// } |
510 |
|
// } |
511 |
|
// } |
512 |
|
|
513 |
315684 |
if (options::bvAbstraction() && t.getType().isBoolean()) |
514 |
|
{ |
515 |
12 |
d_abstractionModule->addInputAtom(res); |
516 |
|
} |
517 |
315684 |
Debug("bv-pp-rewrite") << "to " << res << "\n"; |
518 |
315684 |
if (res != t) |
519 |
|
{ |
520 |
1138 |
return TrustNode::mkTrustRewrite(t, res, nullptr); |
521 |
|
} |
522 |
314546 |
return TrustNode::null(); |
523 |
|
} |
524 |
|
|
525 |
14287 |
void BVSolverLazy::presolve() |
526 |
|
{ |
527 |
14287 |
Debug("bitvector") << "BVSolverLazy::presolve" << std::endl; |
528 |
14287 |
} |
529 |
|
|
530 |
|
static int prop_count = 0; |
531 |
|
|
532 |
2435890 |
bool BVSolverLazy::storePropagation(TNode literal, SubTheory subtheory) |
533 |
|
{ |
534 |
4871780 |
Debug("bitvector::propagate") << indent() << d_context->getLevel() << " " |
535 |
2435890 |
<< "BVSolverLazy::storePropagation(" << literal |
536 |
2435890 |
<< ", " << subtheory << ")" << std::endl; |
537 |
2435890 |
prop_count++; |
538 |
|
|
539 |
|
// If already in conflict, no more propagation |
540 |
2435890 |
if (d_conflict) |
541 |
|
{ |
542 |
|
Debug("bitvector::propagate") |
543 |
|
<< indent() << "BVSolverLazy::storePropagation(" << literal << ", " |
544 |
|
<< subtheory << "): already in conflict" << std::endl; |
545 |
|
return false; |
546 |
|
} |
547 |
|
|
548 |
|
// If propagated already, just skip |
549 |
2435890 |
PropagatedMap::const_iterator find = d_propagatedBy.find(literal); |
550 |
2435890 |
if (find != d_propagatedBy.end()) |
551 |
|
{ |
552 |
887100 |
return true; |
553 |
|
} |
554 |
|
else |
555 |
|
{ |
556 |
1548790 |
bool polarity = literal.getKind() != kind::NOT; |
557 |
3095551 |
Node negatedLiteral = polarity ? literal.notNode() : (Node)literal[0]; |
558 |
1548790 |
find = d_propagatedBy.find(negatedLiteral); |
559 |
1548790 |
if (find != d_propagatedBy.end() && (*find).second != subtheory) |
560 |
|
{ |
561 |
|
// Safe to ignore this one, subtheory should produce a conflict |
562 |
2029 |
return true; |
563 |
|
} |
564 |
|
|
565 |
1546761 |
d_propagatedBy[literal] = subtheory; |
566 |
|
} |
567 |
|
|
568 |
|
// Propagate differs depending on the subtheory |
569 |
|
// * bitblaster needs to be left alone until it's done, otherwise it doesn't |
570 |
|
// know how to explain |
571 |
|
// * equality engine can propagate eagerly |
572 |
|
// TODO(2348): Determine if ok should be set by propagate. If not, remove ok. |
573 |
1546761 |
constexpr bool ok = true; |
574 |
1546761 |
if (subtheory == SUB_CORE) |
575 |
|
{ |
576 |
782000 |
d_im.propagateLit(literal); |
577 |
|
if (!ok) |
578 |
|
{ |
579 |
|
setConflict(); |
580 |
|
} |
581 |
|
} |
582 |
|
else |
583 |
|
{ |
584 |
764761 |
d_literalsToPropagate.push_back(literal); |
585 |
|
} |
586 |
1546761 |
return ok; |
587 |
|
|
588 |
|
} /* BVSolverLazy::propagate(TNode) */ |
589 |
|
|
590 |
23652 |
void BVSolverLazy::explain(TNode literal, std::vector<TNode>& assumptions) |
591 |
|
{ |
592 |
23652 |
Assert(wasPropagatedBySubtheory(literal)); |
593 |
23652 |
SubTheory sub = getPropagatingSubtheory(literal); |
594 |
23652 |
d_subtheoryMap[sub]->explain(literal, assumptions); |
595 |
23652 |
} |
596 |
|
|
597 |
23652 |
TrustNode BVSolverLazy::explain(TNode node) |
598 |
|
{ |
599 |
47304 |
Debug("bitvector::explain") |
600 |
23652 |
<< "BVSolverLazy::explain(" << node << ")" << std::endl; |
601 |
47304 |
std::vector<TNode> assumptions; |
602 |
|
|
603 |
|
// Ask for the explanation |
604 |
23652 |
explain(node, assumptions); |
605 |
|
// this means that it is something true at level 0 |
606 |
47304 |
Node explanation; |
607 |
23652 |
if (assumptions.size() == 0) |
608 |
|
{ |
609 |
132 |
explanation = utils::mkTrue(); |
610 |
|
} |
611 |
|
else |
612 |
|
{ |
613 |
|
// return the explanation |
614 |
23520 |
explanation = utils::mkAnd(assumptions); |
615 |
|
} |
616 |
47304 |
Debug("bitvector::explain") << "BVSolverLazy::explain(" << node << ") => " |
617 |
23652 |
<< explanation << std::endl; |
618 |
23652 |
Debug("bitvector::explain") << "BVSolverLazy::explain done. \n"; |
619 |
47304 |
return TrustNode::mkTrustPropExp(node, explanation, nullptr); |
620 |
|
} |
621 |
|
|
622 |
52392 |
void BVSolverLazy::notifySharedTerm(TNode t) |
623 |
|
{ |
624 |
104784 |
Debug("bitvector::sharing") |
625 |
52392 |
<< indent() << "BVSolverLazy::notifySharedTerm(" << t << ")" << std::endl; |
626 |
52392 |
d_sharedTermsSet.insert(t); |
627 |
52392 |
} |
628 |
|
|
629 |
55014 |
EqualityStatus BVSolverLazy::getEqualityStatus(TNode a, TNode b) |
630 |
|
{ |
631 |
55014 |
if (options::bitblastMode() == options::BitblastMode::EAGER) |
632 |
|
return EQUALITY_UNKNOWN; |
633 |
55014 |
Assert(options::bitblastMode() == options::BitblastMode::LAZY); |
634 |
113914 |
for (unsigned i = 0; i < d_subtheories.size(); ++i) |
635 |
|
{ |
636 |
113812 |
EqualityStatus status = d_subtheories[i]->getEqualityStatus(a, b); |
637 |
113812 |
if (status != EQUALITY_UNKNOWN) |
638 |
|
{ |
639 |
54912 |
return status; |
640 |
|
} |
641 |
|
} |
642 |
102 |
return EQUALITY_UNKNOWN; |
643 |
|
; |
644 |
|
} |
645 |
|
|
646 |
525438 |
void BVSolverLazy::ppStaticLearn(TNode in, NodeBuilder& learned) |
647 |
|
{ |
648 |
525438 |
if (d_staticLearnCache.find(in) != d_staticLearnCache.end()) |
649 |
|
{ |
650 |
61154 |
return; |
651 |
|
} |
652 |
464284 |
d_staticLearnCache.insert(in); |
653 |
|
|
654 |
464284 |
if (in.getKind() == kind::EQUAL) |
655 |
|
{ |
656 |
68688 |
if ((in[0].getKind() == kind::BITVECTOR_ADD |
657 |
22910 |
&& in[1].getKind() == kind::BITVECTOR_SHL) |
658 |
114480 |
|| (in[1].getKind() == kind::BITVECTOR_ADD |
659 |
22898 |
&& in[0].getKind() == kind::BITVECTOR_SHL)) |
660 |
|
{ |
661 |
4 |
TNode p = in[0].getKind() == kind::BITVECTOR_ADD ? in[0] : in[1]; |
662 |
4 |
TNode s = in[0].getKind() == kind::BITVECTOR_ADD ? in[1] : in[0]; |
663 |
|
|
664 |
6 |
if (p.getNumChildren() == 2 && p[0].getKind() == kind::BITVECTOR_SHL |
665 |
6 |
&& p[1].getKind() == kind::BITVECTOR_SHL) |
666 |
|
{ |
667 |
2 |
unsigned size = utils::getSize(s); |
668 |
4 |
Node one = utils::mkConst(size, 1u); |
669 |
2 |
if (s[0] == one && p[0][0] == one && p[1][0] == one) |
670 |
|
{ |
671 |
4 |
Node zero = utils::mkConst(size, 0u); |
672 |
4 |
TNode b = p[0]; |
673 |
4 |
TNode c = p[1]; |
674 |
|
// (s : 1 << S) = (b : 1 << B) + (c : 1 << C) |
675 |
4 |
Node b_eq_0 = b.eqNode(zero); |
676 |
4 |
Node c_eq_0 = c.eqNode(zero); |
677 |
4 |
Node b_eq_c = b.eqNode(c); |
678 |
|
|
679 |
|
Node dis = NodeManager::currentNM()->mkNode( |
680 |
4 |
kind::OR, b_eq_0, c_eq_0, b_eq_c); |
681 |
4 |
Node imp = in.impNode(dis); |
682 |
2 |
learned << imp; |
683 |
|
} |
684 |
|
} |
685 |
|
} |
686 |
|
} |
687 |
441388 |
else if (in.getKind() == kind::AND) |
688 |
|
{ |
689 |
426069 |
for (size_t i = 0, N = in.getNumChildren(); i < N; ++i) |
690 |
|
{ |
691 |
421404 |
ppStaticLearn(in[i], learned); |
692 |
|
} |
693 |
|
} |
694 |
|
} |
695 |
|
|
696 |
4 |
bool BVSolverLazy::applyAbstraction(const std::vector<Node>& assertions, |
697 |
|
std::vector<Node>& new_assertions) |
698 |
|
{ |
699 |
|
bool changed = |
700 |
4 |
d_abstractionModule->applyAbstraction(assertions, new_assertions); |
701 |
4 |
if (changed && options::bitblastMode() == options::BitblastMode::EAGER |
702 |
4 |
&& options::bitvectorAig()) |
703 |
|
{ |
704 |
|
// disable AIG mode |
705 |
|
AlwaysAssert(!d_eagerSolver->isInitialized()); |
706 |
|
d_eagerSolver->turnOffAig(); |
707 |
|
d_eagerSolver->initialize(); |
708 |
|
} |
709 |
4 |
return changed; |
710 |
|
} |
711 |
|
|
712 |
15249 |
void BVSolverLazy::setConflict(Node conflict) |
713 |
|
{ |
714 |
15249 |
if (options::bvAbstraction()) |
715 |
|
{ |
716 |
|
NodeManager* const nm = NodeManager::currentNM(); |
717 |
|
Node new_conflict = d_abstractionModule->simplifyConflict(conflict); |
718 |
|
|
719 |
|
std::vector<Node> lemmas; |
720 |
|
lemmas.push_back(new_conflict); |
721 |
|
d_abstractionModule->generalizeConflict(new_conflict, lemmas); |
722 |
|
for (unsigned i = 0; i < lemmas.size(); ++i) |
723 |
|
{ |
724 |
|
lemma(nm->mkNode(kind::NOT, lemmas[i])); |
725 |
|
} |
726 |
|
} |
727 |
15249 |
d_conflict = true; |
728 |
15249 |
d_conflictNode = conflict; |
729 |
15249 |
} |
730 |
|
|
731 |
|
} // namespace bv |
732 |
|
} // namespace theory |
733 |
353280 |
} // namespace cvc5 |