Merge branch '1.4.x'
[cvc5.git] / src / theory / bv / theory_bv.cpp
1 /********************* */
2 /*! \file theory_bv.cpp
3 ** \verbatim
4 ** Original author: Dejan Jovanovic
5 ** Major contributors: Liana Hadarean
6 ** Minor contributors (to current version): Tim King, Kshitij Bansal, Clark Barrett, Andrew Reynolds, Morgan Deters, Martin Brain <>
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2014 New York University and The University of Iowa
9 ** See the file COPYING in the top-level source directory for licensing
10 ** information.\endverbatim
11 **
12 ** [[ Add lengthier description here ]]
13 ** \todo document this file
14 **/
15
16 #include "smt/options.h"
17 #include "theory/bv/theory_bv.h"
18 #include "theory/bv/theory_bv_utils.h"
19 #include "theory/bv/slicer.h"
20 #include "theory/valuation.h"
21 #include "theory/bv/options.h"
22 #include "theory/bv/theory_bv_rewrite_rules_normalization.h"
23 #include "theory/bv/theory_bv_rewrite_rules_simplification.h"
24 #include "theory/bv/bv_subtheory_core.h"
25 #include "theory/bv/bv_subtheory_inequality.h"
26 #include "theory/bv/bv_subtheory_algebraic.h"
27 #include "theory/bv/bv_subtheory_bitblast.h"
28 #include "theory/bv/bv_eager_solver.h"
29 #include "theory/bv/theory_bv_rewriter.h"
30 #include "theory/theory_model.h"
31 #include "theory/bv/abstraction.h"
32
33 using namespace CVC4;
34 using namespace CVC4::theory;
35 using namespace CVC4::theory::bv;
36 using namespace CVC4::context;
37
38 using namespace std;
39 using namespace CVC4::theory::bv::utils;
40
41 TheoryBV::TheoryBV(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo)
42 : Theory(THEORY_BV, c, u, out, valuation, logicInfo),
43 d_context(c),
44 d_alreadyPropagatedSet(c),
45 d_sharedTermsSet(c),
46 d_subtheories(),
47 d_subtheoryMap(),
48 d_statistics(),
49 d_staticLearnCache(),
50 d_lemmasAdded(c, false),
51 d_conflict(c, false),
52 d_invalidateModelCache(c, true),
53 d_literalsToPropagate(c),
54 d_literalsToPropagateIndex(c, 0),
55 d_propagatedBy(c),
56 d_eagerSolver(NULL),
57 d_abstractionModule(new AbstractionModule()),
58 d_isCoreTheory(false),
59 d_calledPreregister(false)
60 {
61
62 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
63 d_eagerSolver = new EagerBitblastSolver(this);
64 return;
65 }
66
67 if (options::bitvectorEqualitySolver()) {
68 SubtheorySolver* core_solver = new CoreSolver(c, this);
69 d_subtheories.push_back(core_solver);
70 d_subtheoryMap[SUB_CORE] = core_solver;
71 }
72
73 if (options::bitvectorInequalitySolver()) {
74 SubtheorySolver* ineq_solver = new InequalitySolver(c, this);
75 d_subtheories.push_back(ineq_solver);
76 d_subtheoryMap[SUB_INEQUALITY] = ineq_solver;
77 }
78
79 if (options::bitvectorAlgebraicSolver()) {
80 SubtheorySolver* alg_solver = new AlgebraicSolver(c, this);
81 d_subtheories.push_back(alg_solver);
82 d_subtheoryMap[SUB_ALGEBRAIC] = alg_solver;
83 }
84
85 BitblastSolver* bb_solver = new BitblastSolver(c, this);
86 if (options::bvAbstraction()) {
87 bb_solver->setAbstraction(d_abstractionModule);
88 }
89 d_subtheories.push_back(bb_solver);
90 d_subtheoryMap[SUB_BITBLAST] = bb_solver;
91 }
92
93
94 TheoryBV::~TheoryBV() {
95 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
96 delete d_subtheories[i];
97 }
98 }
99
100 void TheoryBV::setMasterEqualityEngine(eq::EqualityEngine* eq) {
101 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
102 return;
103 }
104 if (options::bitvectorEqualitySolver()) {
105 dynamic_cast<CoreSolver*>(d_subtheoryMap[SUB_CORE])->setMasterEqualityEngine(eq);
106 }
107 }
108
109 TheoryBV::Statistics::Statistics():
110 d_avgConflictSize("theory::bv::AvgBVConflictSize"),
111 d_solveSubstitutions("theory::bv::NumberOfSolveSubstitutions", 0),
112 d_solveTimer("theory::bv::solveTimer"),
113 d_numCallsToCheckFullEffort("theory::bv::NumberOfFullCheckCalls", 0),
114 d_numCallsToCheckStandardEffort("theory::bv::NumberOfStandardCheckCalls", 0),
115 d_weightComputationTimer("theory::bv::weightComputationTimer"),
116 d_numMultSlice("theory::bv::NumMultSliceApplied", 0)
117 {
118 StatisticsRegistry::registerStat(&d_avgConflictSize);
119 StatisticsRegistry::registerStat(&d_solveSubstitutions);
120 StatisticsRegistry::registerStat(&d_solveTimer);
121 StatisticsRegistry::registerStat(&d_numCallsToCheckFullEffort);
122 StatisticsRegistry::registerStat(&d_numCallsToCheckStandardEffort);
123 StatisticsRegistry::registerStat(&d_weightComputationTimer);
124 StatisticsRegistry::registerStat(&d_numMultSlice);
125 }
126
127 TheoryBV::Statistics::~Statistics() {
128 StatisticsRegistry::unregisterStat(&d_avgConflictSize);
129 StatisticsRegistry::unregisterStat(&d_solveSubstitutions);
130 StatisticsRegistry::unregisterStat(&d_solveTimer);
131 StatisticsRegistry::unregisterStat(&d_numCallsToCheckFullEffort);
132 StatisticsRegistry::unregisterStat(&d_numCallsToCheckStandardEffort);
133 StatisticsRegistry::unregisterStat(&d_weightComputationTimer);
134 StatisticsRegistry::unregisterStat(&d_numMultSlice);
135 }
136
137 Node TheoryBV::getBVDivByZero(Kind k, unsigned width) {
138 NodeManager* nm = NodeManager::currentNM();
139 if (k == kind::BITVECTOR_UDIV) {
140 if (d_BVDivByZero.find(width) == d_BVDivByZero.end()) {
141 // lazily create the function symbols
142 ostringstream os;
143 os << "BVUDivByZero_" << width;
144 Node divByZero = nm->mkSkolem(os.str(),
145 nm->mkFunctionType(nm->mkBitVectorType(width), nm->mkBitVectorType(width)),
146 "partial bvudiv", NodeManager::SKOLEM_EXACT_NAME);
147 d_BVDivByZero[width] = divByZero;
148 }
149 return d_BVDivByZero[width];
150 }
151 else if (k == kind::BITVECTOR_UREM) {
152 if (d_BVRemByZero.find(width) == d_BVRemByZero.end()) {
153 ostringstream os;
154 os << "BVURemByZero_" << width;
155 Node divByZero = nm->mkSkolem(os.str(),
156 nm->mkFunctionType(nm->mkBitVectorType(width), nm->mkBitVectorType(width)),
157 "partial bvurem", NodeManager::SKOLEM_EXACT_NAME);
158 d_BVRemByZero[width] = divByZero;
159 }
160 return d_BVRemByZero[width];
161 }
162
163 Unreachable();
164 }
165
166
167 void TheoryBV::collectNumerators(TNode term, TNodeSet& seen) {
168 if (seen.find(term) != seen.end())
169 return;
170 if (term.getKind() == kind::BITVECTOR_ACKERMANIZE_UDIV) {
171 unsigned size = utils::getSize(term[0]);
172 if (d_BVDivByZeroAckerman.find(size) == d_BVDivByZeroAckerman.end()) {
173 d_BVDivByZeroAckerman[size] = TNodeSet();
174 }
175 d_BVDivByZeroAckerman[size].insert(term[0]);
176 seen.insert(term);
177 } else if (term.getKind() == kind::BITVECTOR_ACKERMANIZE_UREM) {
178 unsigned size = utils::getSize(term[0]);
179 if (d_BVRemByZeroAckerman.find(size) == d_BVRemByZeroAckerman.end()) {
180 d_BVRemByZeroAckerman[size] = TNodeSet();
181 }
182 d_BVRemByZeroAckerman[size].insert(term[0]);
183 seen.insert(term);
184 }
185 for (unsigned i = 0; i < term.getNumChildren(); ++i) {
186 collectNumerators(term[i], seen);
187 }
188 seen.insert(term);
189 }
190
191 void TheoryBV::mkAckermanizationAsssertions(std::vector<Node>& assertions) {
192 Debug("bv-ackermanize") << "TheoryBV::mkAckermanizationAsssertions\n";
193
194 Assert(options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER);
195 AlwaysAssert(!options::incrementalSolving());
196 TNodeSet seen;
197 for (unsigned i = 0; i < assertions.size(); ++i) {
198 collectNumerators(assertions[i], seen);
199 }
200
201 // process division UF
202 Debug("bv-ackermanize") << "Process division UF...\n";
203 for (WidthToNumerators::const_iterator it = d_BVDivByZeroAckerman.begin(); it != d_BVDivByZeroAckerman.end(); ++it) {
204 const TNodeSet& numerators= it->second;
205 for (TNodeSet::const_iterator i = numerators.begin(); i != numerators.end(); ++i) {
206 TNodeSet::const_iterator j = i;
207 j++;
208 for (; j != numerators.end(); ++j) {
209 TNode arg1 = *i;
210 TNode arg2 = *j;
211 TNode acker1 = utils::mkNode(kind::BITVECTOR_ACKERMANIZE_UDIV, arg1);
212 TNode acker2 = utils::mkNode(kind::BITVECTOR_ACKERMANIZE_UDIV, arg2);
213
214 Node arg_eq = utils::mkNode(kind::EQUAL, arg1, arg2);
215 Node acker_eq = utils::mkNode(kind::EQUAL, acker1, acker2);
216 Node lemma = utils::mkNode(kind::IMPLIES, arg_eq, acker_eq);
217 Debug("bv-ackermanize") << " " << lemma << "\n";
218 assertions.push_back(lemma);
219 }
220 }
221 }
222 // process remainder UF
223 Debug("bv-ackermanize") << "Process remainder UF...\n";
224 for (WidthToNumerators::const_iterator it = d_BVRemByZeroAckerman.begin(); it != d_BVRemByZeroAckerman.end(); ++it) {
225 const TNodeSet& numerators= it->second;
226 for (TNodeSet::const_iterator i = numerators.begin(); i != numerators.end(); ++i) {
227 TNodeSet::const_iterator j = i;
228 j++;
229 for (; j != numerators.end(); ++j) {
230 TNode arg1 = *i;
231 TNode arg2 = *j;
232 TNode acker1 = utils::mkNode(kind::BITVECTOR_ACKERMANIZE_UREM, arg1);
233 TNode acker2 = utils::mkNode(kind::BITVECTOR_ACKERMANIZE_UREM, arg2);
234
235 Node arg_eq = utils::mkNode(kind::EQUAL, arg1, arg2);
236 Node acker_eq = utils::mkNode(kind::EQUAL, acker1, acker2);
237 Node lemma = utils::mkNode(kind::IMPLIES, arg_eq, acker_eq);
238 Debug("bv-ackermanize") << " " << lemma << "\n";
239 assertions.push_back(lemma);
240 }
241 }
242 }
243 }
244
245 Node TheoryBV::expandDefinition(LogicRequest &logicRequest, Node node) {
246 Debug("bitvector-expandDefinition") << "TheoryBV::expandDefinition(" << node << ")" << std::endl;
247
248 switch (node.getKind()) {
249 case kind::BITVECTOR_SDIV:
250 case kind::BITVECTOR_SREM:
251 case kind::BITVECTOR_SMOD:
252 return TheoryBVRewriter::eliminateBVSDiv(node);
253 break;
254
255 case kind::BITVECTOR_UDIV:
256 case kind::BITVECTOR_UREM: {
257 NodeManager* nm = NodeManager::currentNM();
258 unsigned width = node.getType().getBitVectorSize();
259
260 if (options::bitvectorDivByZeroConst()) {
261 Kind kind = node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_UDIV_TOTAL : kind::BITVECTOR_UREM_TOTAL;
262 return nm->mkNode(kind, node[0], node[1]);
263 }
264
265 TNode num = node[0], den = node[1];
266 Node den_eq_0 = nm->mkNode(kind::EQUAL, den, nm->mkConst(BitVector(width, Integer(0))));
267 Node divTotalNumDen = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_UDIV_TOTAL :
268 kind::BITVECTOR_UREM_TOTAL, num, den);
269
270 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
271 // Ackermanize UF if using eager bit-blasting
272 Node ackerman_var = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_ACKERMANIZE_UDIV : kind::BITVECTOR_ACKERMANIZE_UREM, num);
273 node = nm->mkNode(kind::ITE, den_eq_0, ackerman_var, divTotalNumDen);
274 return node;
275 } else {
276 Node divByZero = getBVDivByZero(node.getKind(), width);
277 Node divByZeroNum = nm->mkNode(kind::APPLY_UF, divByZero, num);
278 node = nm->mkNode(kind::ITE, den_eq_0, divByZeroNum, divTotalNumDen);
279 logicRequest.widenLogic(THEORY_UF);
280 return node;
281 }
282 }
283 break;
284
285 default:
286 return node;
287 break;
288 }
289
290 Unreachable();
291 }
292
293
294 void TheoryBV::preRegisterTerm(TNode node) {
295 d_calledPreregister = true;
296 Debug("bitvector-preregister") << "TheoryBV::preRegister(" << node << ")" << std::endl;
297
298 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
299 // the aig bit-blaster option is set heuristically
300 // if bv abstraction is not used
301 if (!d_eagerSolver->isInitialized()) {
302 d_eagerSolver->initialize();
303 }
304
305 if (node.getKind() == kind::BITVECTOR_EAGER_ATOM) {
306 Node formula = node[0];
307 d_eagerSolver->assertFormula(formula);
308 }
309 // nothing to do for the other terms
310 return;
311 }
312
313 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
314 d_subtheories[i]->preRegister(node);
315 }
316 }
317
318 void TheoryBV::sendConflict() {
319 Assert(d_conflict);
320 if (d_conflictNode.isNull()) {
321 return;
322 } else {
323 Debug("bitvector") << indent() << "TheoryBV::check(): conflict " << d_conflictNode;
324 d_out->conflict(d_conflictNode);
325 d_statistics.d_avgConflictSize.addEntry(d_conflictNode.getNumChildren());
326 d_conflictNode = Node::null();
327 }
328 }
329
330 void TheoryBV::checkForLemma(TNode fact) {
331 if (fact.getKind() == kind::EQUAL) {
332 if (fact[0].getKind() == kind::BITVECTOR_UREM_TOTAL) {
333 TNode urem = fact[0];
334 TNode result = fact[1];
335 TNode divisor = urem[1];
336 Node result_ult_div = mkNode(kind::BITVECTOR_ULT, result, divisor);
337 Node divisor_eq_0 = mkNode(kind::EQUAL,
338 divisor,
339 mkConst(BitVector(getSize(divisor), 0u)));
340 Node split = utils::mkNode(kind::OR, divisor_eq_0, mkNode(kind::NOT, fact), result_ult_div);
341 lemma(split);
342 }
343 if (fact[1].getKind() == kind::BITVECTOR_UREM_TOTAL) {
344 TNode urem = fact[1];
345 TNode result = fact[0];
346 TNode divisor = urem[1];
347 Node result_ult_div = mkNode(kind::BITVECTOR_ULT, result, divisor);
348 Node divisor_eq_0 = mkNode(kind::EQUAL,
349 divisor,
350 mkConst(BitVector(getSize(divisor), 0u)));
351 Node split = utils::mkNode(kind::OR, divisor_eq_0, mkNode(kind::NOT, fact), result_ult_div);
352 lemma(split);
353 }
354 }
355 }
356
357
358 void TheoryBV::check(Effort e)
359 {
360 if (done() && !fullEffort(e)) {
361 return;
362 }
363 Debug("bitvector") << "TheoryBV::check(" << e << ")" << std::endl;
364 // we may be getting new assertions so the model cache may not be sound
365 d_invalidateModelCache.set(true);
366 // if we are using the eager solver
367 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
368 // this can only happen on an empty benchmark
369 if (!d_eagerSolver->isInitialized()) {
370 d_eagerSolver->initialize();
371 }
372 if (!Theory::fullEffort(e))
373 return;
374
375 std::vector<TNode> assertions;
376 while (!done()) {
377 TNode fact = get().assertion;
378 Assert (fact.getKind() == kind::BITVECTOR_EAGER_ATOM);
379 assertions.push_back(fact);
380 }
381 Assert (d_eagerSolver->hasAssertions(assertions));
382
383 bool ok = d_eagerSolver->checkSat();
384 if (!ok) {
385 if (assertions.size() == 1) {
386 d_out->conflict(assertions[0]);
387 return;
388 }
389 Node conflict = NodeManager::currentNM()->mkNode(kind::AND, assertions);
390 d_out->conflict(conflict);
391 return;
392 }
393 return;
394 }
395
396
397 if (Theory::fullEffort(e)) {
398 ++(d_statistics.d_numCallsToCheckFullEffort);
399 } else {
400 ++(d_statistics.d_numCallsToCheckStandardEffort);
401 }
402 // if we are already in conflict just return the conflict
403 if (inConflict()) {
404 sendConflict();
405 return;
406 }
407
408 while (!done()) {
409 TNode fact = get().assertion;
410
411 checkForLemma(fact);
412
413 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
414 d_subtheories[i]->assertFact(fact);
415 }
416 }
417
418 bool ok = true;
419 bool complete = false;
420 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
421 Assert (!inConflict());
422 ok = d_subtheories[i]->check(e);
423 complete = d_subtheories[i]->isComplete();
424
425 if (!ok) {
426 // if we are in a conflict no need to check with other theories
427 Assert (inConflict());
428 sendConflict();
429 return;
430 }
431 if (complete) {
432 // if the last subtheory was complete we stop
433 return;
434 }
435 }
436 }
437
438 void TheoryBV::collectModelInfo( TheoryModel* m, bool fullModel ){
439 Assert(!inConflict());
440 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
441 d_eagerSolver->collectModelInfo(m, fullModel);
442 }
443 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
444 if (d_subtheories[i]->isComplete()) {
445 d_subtheories[i]->collectModelInfo(m, fullModel);
446 return;
447 }
448 }
449 }
450
451 Node TheoryBV::getModelValue(TNode var) {
452 Assert(!inConflict());
453 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
454 if (d_subtheories[i]->isComplete()) {
455 return d_subtheories[i]->getModelValue(var);
456 }
457 }
458 Unreachable();
459 }
460
461 void TheoryBV::propagate(Effort e) {
462 Debug("bitvector") << indent() << "TheoryBV::propagate()" << std::endl;
463 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
464 return;
465 }
466
467 if (inConflict()) {
468 return;
469 }
470
471 // go through stored propagations
472 bool ok = true;
473 for (; d_literalsToPropagateIndex < d_literalsToPropagate.size() && ok; d_literalsToPropagateIndex = d_literalsToPropagateIndex + 1) {
474 TNode literal = d_literalsToPropagate[d_literalsToPropagateIndex];
475 // temporary fix for incremental bit-blasting
476 if (d_valuation.isSatLiteral(literal)) {
477 Debug("bitvector::propagate") << "TheoryBV:: propagating " << literal <<"\n";
478 ok = d_out->propagate(literal);
479 }
480 }
481
482 if (!ok) {
483 Debug("bitvector::propagate") << indent() << "TheoryBV::propagate(): conflict from theory engine" << std::endl;
484 setConflict();
485 }
486 }
487
488
489 Theory::PPAssertStatus TheoryBV::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
490 switch(in.getKind()) {
491 case kind::EQUAL:
492 {
493 if (in[0].isVar() && !in[1].hasSubterm(in[0])) {
494 ++(d_statistics.d_solveSubstitutions);
495 outSubstitutions.addSubstitution(in[0], in[1]);
496 return PP_ASSERT_STATUS_SOLVED;
497 }
498 if (in[1].isVar() && !in[0].hasSubterm(in[1])) {
499 ++(d_statistics.d_solveSubstitutions);
500 outSubstitutions.addSubstitution(in[1], in[0]);
501 return PP_ASSERT_STATUS_SOLVED;
502 }
503 Node node = Rewriter::rewrite(in);
504 if ((node[0].getKind() == kind::BITVECTOR_EXTRACT && node[1].isConst()) ||
505 (node[1].getKind() == kind::BITVECTOR_EXTRACT && node[0].isConst())) {
506 Node extract = node[0].isConst() ? node[1] : node[0];
507 if (extract[0].getKind() == kind::VARIABLE) {
508 Node c = node[0].isConst() ? node[0] : node[1];
509
510 unsigned high = utils::getExtractHigh(extract);
511 unsigned low = utils::getExtractLow(extract);
512 unsigned var_bitwidth = utils::getSize(extract[0]);
513 std::vector<Node> children;
514
515 if (low == 0) {
516 Assert (high != var_bitwidth - 1);
517 unsigned skolem_size = var_bitwidth - high - 1;
518 Node skolem = utils::mkVar(skolem_size);
519 children.push_back(skolem);
520 children.push_back(c);
521 } else if (high == var_bitwidth - 1) {
522 unsigned skolem_size = low;
523 Node skolem = utils::mkVar(skolem_size);
524 children.push_back(c);
525 children.push_back(skolem);
526 } else {
527 unsigned skolem1_size = low;
528 unsigned skolem2_size = var_bitwidth - high - 1;
529 Node skolem1 = utils::mkVar(skolem1_size);
530 Node skolem2 = utils::mkVar(skolem2_size);
531 children.push_back(skolem2);
532 children.push_back(c);
533 children.push_back(skolem1);
534 }
535 Node concat = utils::mkNode(kind::BITVECTOR_CONCAT, children);
536 Assert (utils::getSize(concat) == utils::getSize(extract[0]));
537 outSubstitutions.addSubstitution(extract[0], concat);
538 return PP_ASSERT_STATUS_SOLVED;
539 }
540 }
541 }
542 break;
543 case kind::BITVECTOR_ULT:
544 case kind::BITVECTOR_SLT:
545 case kind::BITVECTOR_ULE:
546 case kind::BITVECTOR_SLE:
547
548 default:
549 // TODO other predicates
550 break;
551 }
552 return PP_ASSERT_STATUS_UNSOLVED;
553 }
554
555 Node TheoryBV::ppRewrite(TNode t)
556 {
557 Debug("bv-pp-rewrite") << "TheoryBV::ppRewrite " << t << "\n";
558 Node res = t;
559 if (RewriteRule<BitwiseEq>::applies(t)) {
560 Node result = RewriteRule<BitwiseEq>::run<false>(t);
561 res = Rewriter::rewrite(result);
562 } else if (d_isCoreTheory && t.getKind() == kind::EQUAL) {
563 std::vector<Node> equalities;
564 Slicer::splitEqualities(t, equalities);
565 res = utils::mkAnd(equalities);
566 } else if (RewriteRule<UltPlusOne>::applies(t)) {
567 Node result = RewriteRule<UltPlusOne>::run<false>(t);
568 res = Rewriter::rewrite(result);
569 } else if( res.getKind() == kind::EQUAL &&
570 ((res[0].getKind() == kind::BITVECTOR_PLUS &&
571 RewriteRule<ConcatToMult>::applies(res[1])) ||
572 res[1].getKind() == kind::BITVECTOR_PLUS &&
573 RewriteRule<ConcatToMult>::applies(res[0]))) {
574 Node mult = RewriteRule<ConcatToMult>::applies(res[0])?
575 RewriteRule<ConcatToMult>::run<false>(res[0]) :
576 RewriteRule<ConcatToMult>::run<true>(res[1]);
577 Node factor = mult[0];
578 Node sum = RewriteRule<ConcatToMult>::applies(res[0])? res[1] : res[0];
579 Node new_eq =utils::mkNode(kind::EQUAL, sum, mult);
580 Node rewr_eq = RewriteRule<SolveEq>::run<true>(new_eq);
581 if (rewr_eq[0].isVar() || rewr_eq[1].isVar()){
582 res = Rewriter::rewrite(rewr_eq);
583 } else {
584 res = t;
585 }
586 }
587
588
589 // if(t.getKind() == kind::EQUAL &&
590 // ((t[0].getKind() == kind::BITVECTOR_MULT && t[1].getKind() == kind::BITVECTOR_PLUS) ||
591 // (t[1].getKind() == kind::BITVECTOR_MULT && t[0].getKind() == kind::BITVECTOR_PLUS))) {
592 // // if we have an equality between a multiplication and addition
593 // // try to express multiplication in terms of addition
594 // Node mult = t[0].getKind() == kind::BITVECTOR_MULT? t[0] : t[1];
595 // Node add = t[0].getKind() == kind::BITVECTOR_PLUS? t[0] : t[1];
596 // if (RewriteRule<MultSlice>::applies(mult)) {
597 // Node new_mult = RewriteRule<MultSlice>::run<false>(mult);
598 // Node new_eq = Rewriter::rewrite(utils::mkNode(kind::EQUAL, new_mult, add));
599
600 // // the simplification can cause the formula to blow up
601 // // only apply if formula reduced
602 // if (d_subtheoryMap.find(SUB_BITBLAST) != d_subtheoryMap.end()) {
603 // BitblastSolver* bv = (BitblastSolver*)d_subtheoryMap[SUB_BITBLAST];
604 // uint64_t old_size = bv->computeAtomWeight(t);
605 // Assert (old_size);
606 // uint64_t new_size = bv->computeAtomWeight(new_eq);
607 // double ratio = ((double)new_size)/old_size;
608 // if (ratio <= 0.4) {
609 // ++(d_statistics.d_numMultSlice);
610 // return new_eq;
611 // }
612 // }
613
614 // if (new_eq.getKind() == kind::CONST_BOOLEAN) {
615 // ++(d_statistics.d_numMultSlice);
616 // return new_eq;
617 // }
618 // }
619 // }
620
621 if (options::bvAbstraction() && t.getType().isBoolean()) {
622 d_abstractionModule->addInputAtom(res);
623 }
624 Debug("bv-pp-rewrite") << "to " << res << "\n";
625 return res;
626 }
627
628 void TheoryBV::presolve() {
629 Debug("bitvector") << "TheoryBV::presolve" << endl;
630 }
631
632 static int prop_count = 0;
633
634 bool TheoryBV::storePropagation(TNode literal, SubTheory subtheory)
635 {
636 Debug("bitvector::propagate") << indent() << getSatContext()->getLevel() << " " << "TheoryBV::storePropagation(" << literal << ", " << subtheory << ")" << std::endl;
637 prop_count++;
638
639 // If already in conflict, no more propagation
640 if (d_conflict) {
641 Debug("bitvector::propagate") << indent() << "TheoryBV::storePropagation(" << literal << ", " << subtheory << "): already in conflict" << std::endl;
642 return false;
643 }
644
645 // If propagated already, just skip
646 PropagatedMap::const_iterator find = d_propagatedBy.find(literal);
647 if (find != d_propagatedBy.end()) {
648 return true;
649 } else {
650 bool polarity = literal.getKind() != kind::NOT;
651 Node negatedLiteral = polarity ? literal.notNode() : (Node) literal[0];
652 find = d_propagatedBy.find(negatedLiteral);
653 if (find != d_propagatedBy.end() && (*find).second != subtheory) {
654 // Safe to ignore this one, subtheory should produce a conflict
655 return true;
656 }
657
658 d_propagatedBy[literal] = subtheory;
659 }
660
661 // Propagate differs depending on the subtheory
662 // * bitblaster needs to be left alone until it's done, otherwise it doesn't know how to explain
663 // * equality engine can propagate eagerly
664 bool ok = true;
665 if (subtheory == SUB_CORE) {
666 d_out->propagate(literal);
667 if (!ok) {
668 setConflict();
669 }
670 } else {
671 d_literalsToPropagate.push_back(literal);
672 }
673 return ok;
674
675 }/* TheoryBV::propagate(TNode) */
676
677
678 void TheoryBV::explain(TNode literal, std::vector<TNode>& assumptions) {
679 Assert (wasPropagatedBySubtheory(literal));
680 SubTheory sub = getPropagatingSubtheory(literal);
681 d_subtheoryMap[sub]->explain(literal, assumptions);
682 }
683
684
685 Node TheoryBV::explain(TNode node) {
686 Debug("bitvector::explain") << "TheoryBV::explain(" << node << ")" << std::endl;
687 std::vector<TNode> assumptions;
688
689 // Ask for the explanation
690 explain(node, assumptions);
691 // this means that it is something true at level 0
692 if (assumptions.size() == 0) {
693 return utils::mkTrue();
694 }
695 // return the explanation
696 Node explanation = utils::mkAnd(assumptions);
697 Debug("bitvector::explain") << "TheoryBV::explain(" << node << ") => " << explanation << std::endl;
698 return explanation;
699 }
700
701
702 void TheoryBV::addSharedTerm(TNode t) {
703 Debug("bitvector::sharing") << indent() << "TheoryBV::addSharedTerm(" << t << ")" << std::endl;
704 d_sharedTermsSet.insert(t);
705 if (options::bitvectorEqualitySolver()) {
706 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
707 d_subtheories[i]->addSharedTerm(t);
708 }
709 }
710 }
711
712
713 EqualityStatus TheoryBV::getEqualityStatus(TNode a, TNode b)
714 {
715 Assert (options::bitblastMode() == theory::bv::BITBLAST_MODE_LAZY);
716 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
717 EqualityStatus status = d_subtheories[i]->getEqualityStatus(a, b);
718 if (status != EQUALITY_UNKNOWN) {
719 return status;
720 }
721 }
722 return EQUALITY_UNKNOWN; ;
723 }
724
725
726 void TheoryBV::enableCoreTheorySlicer() {
727 Assert (!d_calledPreregister);
728 d_isCoreTheory = true;
729 if (d_subtheoryMap.find(SUB_CORE) != d_subtheoryMap.end()) {
730 CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
731 core->enableSlicer();
732 }
733 }
734
735
736 void TheoryBV::ppStaticLearn(TNode in, NodeBuilder<>& learned) {
737 if(d_staticLearnCache.find(in) != d_staticLearnCache.end()){
738 return;
739 }
740 d_staticLearnCache.insert(in);
741
742 if (in.getKind() == kind::EQUAL) {
743 if(in[0].getKind() == kind::BITVECTOR_PLUS && in[1].getKind() == kind::BITVECTOR_SHL ||
744 in[1].getKind() == kind::BITVECTOR_PLUS && in[0].getKind() == kind::BITVECTOR_SHL){
745 TNode p = in[0].getKind() == kind::BITVECTOR_PLUS ? in[0] : in[1];
746 TNode s = in[0].getKind() == kind::BITVECTOR_PLUS ? in[1] : in[0];
747
748 if(p.getNumChildren() == 2
749 && p[0].getKind() == kind::BITVECTOR_SHL
750 && p[1].getKind() == kind::BITVECTOR_SHL ){
751 unsigned size = utils::getSize(s);
752 Node one = utils::mkConst(size, 1u);
753 if(s[0] == one && p[0][0] == one && p[1][0] == one){
754 Node zero = utils::mkConst(size, 0u);
755 TNode b = p[0];
756 TNode c = p[1];
757 // (s : 1 << S) = (b : 1 << B) + (c : 1 << C)
758 Node b_eq_0 = b.eqNode(zero);
759 Node c_eq_0 = c.eqNode(zero);
760 Node b_eq_c = b.eqNode(c);
761
762 Node dis = utils::mkNode(kind::OR, b_eq_0, c_eq_0, b_eq_c);
763 Node imp = in.impNode(dis);
764 learned << imp;
765 }
766 }
767 }
768 }else if(in.getKind() == kind::AND){
769 for(size_t i = 0, N = in.getNumChildren(); i < N; ++i){
770 ppStaticLearn(in[i], learned);
771 }
772 }
773 }
774
775 bool TheoryBV::applyAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions) {
776 bool changed = d_abstractionModule->applyAbstraction(assertions, new_assertions);
777 if (changed &&
778 options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER &&
779 options::bitvectorAig()) {
780 // disable AIG mode
781 AlwaysAssert (!d_eagerSolver->isInitialized());
782 d_eagerSolver->turnOffAig();
783 d_eagerSolver->initialize();
784 }
785 return changed;
786 }
787
788 void TheoryBV::setConflict(Node conflict) {
789 if (options::bvAbstraction()) {
790 Node new_conflict = d_abstractionModule->simplifyConflict(conflict);
791
792 std::vector<Node> lemmas;
793 lemmas.push_back(new_conflict);
794 d_abstractionModule->generalizeConflict(new_conflict, lemmas);
795 for (unsigned i = 0; i < lemmas.size(); ++i) {
796 lemma(utils::mkNode(kind::NOT, lemmas[i]));
797 }
798 }
799 d_conflict = true;
800 d_conflictNode = conflict;
801 }