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 Debug("bitvector") << "TheoryBV::check(" << e << ")" << std::endl;
361 // we may be getting new assertions so the model cache may not be sound
362 d_invalidateModelCache.set(true);
363 // if we are using the eager solver
364 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
365 // this can only happen on an empty benchmark
366 if (!d_eagerSolver->isInitialized()) {
367 d_eagerSolver->initialize();
368 }
369 if (!Theory::fullEffort(e))
370 return;
371
372 std::vector<TNode> assertions;
373 while (!done()) {
374 TNode fact = get().assertion;
375 Assert (fact.getKind() == kind::BITVECTOR_EAGER_ATOM);
376 assertions.push_back(fact);
377 }
378 Assert (d_eagerSolver->hasAssertions(assertions));
379
380 bool ok = d_eagerSolver->checkSat();
381 if (!ok) {
382 if (assertions.size() == 1) {
383 d_out->conflict(assertions[0]);
384 return;
385 }
386 Node conflict = NodeManager::currentNM()->mkNode(kind::AND, assertions);
387 d_out->conflict(conflict);
388 return;
389 }
390 return;
391 }
392
393
394 if (Theory::fullEffort(e)) {
395 ++(d_statistics.d_numCallsToCheckFullEffort);
396 } else {
397 ++(d_statistics.d_numCallsToCheckStandardEffort);
398 }
399 // if we are already in conflict just return the conflict
400 if (inConflict()) {
401 sendConflict();
402 return;
403 }
404
405 while (!done()) {
406 TNode fact = get().assertion;
407
408 checkForLemma(fact);
409
410 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
411 d_subtheories[i]->assertFact(fact);
412 }
413 }
414
415 bool ok = true;
416 bool complete = false;
417 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
418 Assert (!inConflict());
419 ok = d_subtheories[i]->check(e);
420 complete = d_subtheories[i]->isComplete();
421
422 if (!ok) {
423 // if we are in a conflict no need to check with other theories
424 Assert (inConflict());
425 sendConflict();
426 return;
427 }
428 if (complete) {
429 // if the last subtheory was complete we stop
430 return;
431 }
432 }
433 }
434
435 void TheoryBV::collectModelInfo( TheoryModel* m, bool fullModel ){
436 Assert(!inConflict());
437 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
438 d_eagerSolver->collectModelInfo(m, fullModel);
439 }
440 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
441 if (d_subtheories[i]->isComplete()) {
442 d_subtheories[i]->collectModelInfo(m, fullModel);
443 return;
444 }
445 }
446 }
447
448 Node TheoryBV::getModelValue(TNode var) {
449 Assert(!inConflict());
450 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
451 if (d_subtheories[i]->isComplete()) {
452 return d_subtheories[i]->getModelValue(var);
453 }
454 }
455 Unreachable();
456 }
457
458 void TheoryBV::propagate(Effort e) {
459 Debug("bitvector") << indent() << "TheoryBV::propagate()" << std::endl;
460 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
461 return;
462 }
463
464 if (inConflict()) {
465 return;
466 }
467
468 // go through stored propagations
469 bool ok = true;
470 for (; d_literalsToPropagateIndex < d_literalsToPropagate.size() && ok; d_literalsToPropagateIndex = d_literalsToPropagateIndex + 1) {
471 TNode literal = d_literalsToPropagate[d_literalsToPropagateIndex];
472 // temporary fix for incremental bit-blasting
473 if (d_valuation.isSatLiteral(literal)) {
474 Debug("bitvector::propagate") << "TheoryBV:: propagating " << literal <<"\n";
475 ok = d_out->propagate(literal);
476 }
477 }
478
479 if (!ok) {
480 Debug("bitvector::propagate") << indent() << "TheoryBV::propagate(): conflict from theory engine" << std::endl;
481 setConflict();
482 }
483 }
484
485
486 Theory::PPAssertStatus TheoryBV::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
487 switch(in.getKind()) {
488 case kind::EQUAL:
489 {
490 if (in[0].isVar() && !in[1].hasSubterm(in[0])) {
491 ++(d_statistics.d_solveSubstitutions);
492 outSubstitutions.addSubstitution(in[0], in[1]);
493 return PP_ASSERT_STATUS_SOLVED;
494 }
495 if (in[1].isVar() && !in[0].hasSubterm(in[1])) {
496 ++(d_statistics.d_solveSubstitutions);
497 outSubstitutions.addSubstitution(in[1], in[0]);
498 return PP_ASSERT_STATUS_SOLVED;
499 }
500 Node node = Rewriter::rewrite(in);
501 if ((node[0].getKind() == kind::BITVECTOR_EXTRACT && node[1].isConst()) ||
502 (node[1].getKind() == kind::BITVECTOR_EXTRACT && node[0].isConst())) {
503 Node extract = node[0].isConst() ? node[1] : node[0];
504 if (extract[0].getKind() == kind::VARIABLE) {
505 Node c = node[0].isConst() ? node[0] : node[1];
506
507 unsigned high = utils::getExtractHigh(extract);
508 unsigned low = utils::getExtractLow(extract);
509 unsigned var_bitwidth = utils::getSize(extract[0]);
510 std::vector<Node> children;
511
512 if (low == 0) {
513 Assert (high != var_bitwidth - 1);
514 unsigned skolem_size = var_bitwidth - high - 1;
515 Node skolem = utils::mkVar(skolem_size);
516 children.push_back(skolem);
517 children.push_back(c);
518 } else if (high == var_bitwidth - 1) {
519 unsigned skolem_size = low;
520 Node skolem = utils::mkVar(skolem_size);
521 children.push_back(c);
522 children.push_back(skolem);
523 } else {
524 unsigned skolem1_size = low;
525 unsigned skolem2_size = var_bitwidth - high - 1;
526 Node skolem1 = utils::mkVar(skolem1_size);
527 Node skolem2 = utils::mkVar(skolem2_size);
528 children.push_back(skolem2);
529 children.push_back(c);
530 children.push_back(skolem1);
531 }
532 Node concat = utils::mkNode(kind::BITVECTOR_CONCAT, children);
533 Assert (utils::getSize(concat) == utils::getSize(extract[0]));
534 outSubstitutions.addSubstitution(extract[0], concat);
535 return PP_ASSERT_STATUS_SOLVED;
536 }
537 }
538 }
539 break;
540 case kind::BITVECTOR_ULT:
541 case kind::BITVECTOR_SLT:
542 case kind::BITVECTOR_ULE:
543 case kind::BITVECTOR_SLE:
544
545 default:
546 // TODO other predicates
547 break;
548 }
549 return PP_ASSERT_STATUS_UNSOLVED;
550 }
551
552 Node TheoryBV::ppRewrite(TNode t)
553 {
554 Debug("bv-pp-rewrite") << "TheoryBV::ppRewrite " << t << "\n";
555 Node res = t;
556 if (RewriteRule<BitwiseEq>::applies(t)) {
557 Node result = RewriteRule<BitwiseEq>::run<false>(t);
558 res = Rewriter::rewrite(result);
559 } else if (d_isCoreTheory && t.getKind() == kind::EQUAL) {
560 std::vector<Node> equalities;
561 Slicer::splitEqualities(t, equalities);
562 res = utils::mkAnd(equalities);
563 } else if (RewriteRule<UltPlusOne>::applies(t)) {
564 Node result = RewriteRule<UltPlusOne>::run<false>(t);
565 res = Rewriter::rewrite(result);
566 } else if( res.getKind() == kind::EQUAL &&
567 ((res[0].getKind() == kind::BITVECTOR_PLUS &&
568 RewriteRule<ConcatToMult>::applies(res[1])) ||
569 res[1].getKind() == kind::BITVECTOR_PLUS &&
570 RewriteRule<ConcatToMult>::applies(res[0]))) {
571 Node mult = RewriteRule<ConcatToMult>::applies(res[0])?
572 RewriteRule<ConcatToMult>::run<false>(res[0]) :
573 RewriteRule<ConcatToMult>::run<true>(res[1]);
574 Node factor = mult[0];
575 Node sum = RewriteRule<ConcatToMult>::applies(res[0])? res[1] : res[0];
576 Node new_eq =utils::mkNode(kind::EQUAL, sum, mult);
577 Node rewr_eq = RewriteRule<SolveEq>::run<true>(new_eq);
578 if (rewr_eq[0].isVar() || rewr_eq[1].isVar()){
579 res = Rewriter::rewrite(rewr_eq);
580 } else {
581 res = t;
582 }
583 }
584
585
586 // if(t.getKind() == kind::EQUAL &&
587 // ((t[0].getKind() == kind::BITVECTOR_MULT && t[1].getKind() == kind::BITVECTOR_PLUS) ||
588 // (t[1].getKind() == kind::BITVECTOR_MULT && t[0].getKind() == kind::BITVECTOR_PLUS))) {
589 // // if we have an equality between a multiplication and addition
590 // // try to express multiplication in terms of addition
591 // Node mult = t[0].getKind() == kind::BITVECTOR_MULT? t[0] : t[1];
592 // Node add = t[0].getKind() == kind::BITVECTOR_PLUS? t[0] : t[1];
593 // if (RewriteRule<MultSlice>::applies(mult)) {
594 // Node new_mult = RewriteRule<MultSlice>::run<false>(mult);
595 // Node new_eq = Rewriter::rewrite(utils::mkNode(kind::EQUAL, new_mult, add));
596
597 // // the simplification can cause the formula to blow up
598 // // only apply if formula reduced
599 // if (d_subtheoryMap.find(SUB_BITBLAST) != d_subtheoryMap.end()) {
600 // BitblastSolver* bv = (BitblastSolver*)d_subtheoryMap[SUB_BITBLAST];
601 // uint64_t old_size = bv->computeAtomWeight(t);
602 // Assert (old_size);
603 // uint64_t new_size = bv->computeAtomWeight(new_eq);
604 // double ratio = ((double)new_size)/old_size;
605 // if (ratio <= 0.4) {
606 // ++(d_statistics.d_numMultSlice);
607 // return new_eq;
608 // }
609 // }
610
611 // if (new_eq.getKind() == kind::CONST_BOOLEAN) {
612 // ++(d_statistics.d_numMultSlice);
613 // return new_eq;
614 // }
615 // }
616 // }
617
618 if (options::bvAbstraction() && t.getType().isBoolean()) {
619 d_abstractionModule->addInputAtom(res);
620 }
621 Debug("bv-pp-rewrite") << "to " << res << "\n";
622 return res;
623 }
624
625 void TheoryBV::presolve() {
626 Debug("bitvector") << "TheoryBV::presolve" << endl;
627 }
628
629 static int prop_count = 0;
630
631 bool TheoryBV::storePropagation(TNode literal, SubTheory subtheory)
632 {
633 Debug("bitvector::propagate") << indent() << getSatContext()->getLevel() << " " << "TheoryBV::storePropagation(" << literal << ", " << subtheory << ")" << std::endl;
634 prop_count++;
635
636 // If already in conflict, no more propagation
637 if (d_conflict) {
638 Debug("bitvector::propagate") << indent() << "TheoryBV::storePropagation(" << literal << ", " << subtheory << "): already in conflict" << std::endl;
639 return false;
640 }
641
642 // If propagated already, just skip
643 PropagatedMap::const_iterator find = d_propagatedBy.find(literal);
644 if (find != d_propagatedBy.end()) {
645 return true;
646 } else {
647 bool polarity = literal.getKind() != kind::NOT;
648 Node negatedLiteral = polarity ? literal.notNode() : (Node) literal[0];
649 find = d_propagatedBy.find(negatedLiteral);
650 if (find != d_propagatedBy.end() && (*find).second != subtheory) {
651 // Safe to ignore this one, subtheory should produce a conflict
652 return true;
653 }
654
655 d_propagatedBy[literal] = subtheory;
656 }
657
658 // Propagate differs depending on the subtheory
659 // * bitblaster needs to be left alone until it's done, otherwise it doesn't know how to explain
660 // * equality engine can propagate eagerly
661 bool ok = true;
662 if (subtheory == SUB_CORE) {
663 d_out->propagate(literal);
664 if (!ok) {
665 setConflict();
666 }
667 } else {
668 d_literalsToPropagate.push_back(literal);
669 }
670 return ok;
671
672 }/* TheoryBV::propagate(TNode) */
673
674
675 void TheoryBV::explain(TNode literal, std::vector<TNode>& assumptions) {
676 Assert (wasPropagatedBySubtheory(literal));
677 SubTheory sub = getPropagatingSubtheory(literal);
678 d_subtheoryMap[sub]->explain(literal, assumptions);
679 }
680
681
682 Node TheoryBV::explain(TNode node) {
683 Debug("bitvector::explain") << "TheoryBV::explain(" << node << ")" << std::endl;
684 std::vector<TNode> assumptions;
685
686 // Ask for the explanation
687 explain(node, assumptions);
688 // this means that it is something true at level 0
689 if (assumptions.size() == 0) {
690 return utils::mkTrue();
691 }
692 // return the explanation
693 Node explanation = utils::mkAnd(assumptions);
694 Debug("bitvector::explain") << "TheoryBV::explain(" << node << ") => " << explanation << std::endl;
695 return explanation;
696 }
697
698
699 void TheoryBV::addSharedTerm(TNode t) {
700 Debug("bitvector::sharing") << indent() << "TheoryBV::addSharedTerm(" << t << ")" << std::endl;
701 d_sharedTermsSet.insert(t);
702 if (options::bitvectorEqualitySolver()) {
703 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
704 d_subtheories[i]->addSharedTerm(t);
705 }
706 }
707 }
708
709
710 EqualityStatus TheoryBV::getEqualityStatus(TNode a, TNode b)
711 {
712 Assert (options::bitblastMode() == theory::bv::BITBLAST_MODE_LAZY);
713 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
714 EqualityStatus status = d_subtheories[i]->getEqualityStatus(a, b);
715 if (status != EQUALITY_UNKNOWN) {
716 return status;
717 }
718 }
719 return EQUALITY_UNKNOWN; ;
720 }
721
722
723 void TheoryBV::enableCoreTheorySlicer() {
724 Assert (!d_calledPreregister);
725 d_isCoreTheory = true;
726 if (d_subtheoryMap.find(SUB_CORE) != d_subtheoryMap.end()) {
727 CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
728 core->enableSlicer();
729 }
730 }
731
732
733 void TheoryBV::ppStaticLearn(TNode in, NodeBuilder<>& learned) {
734 if(d_staticLearnCache.find(in) != d_staticLearnCache.end()){
735 return;
736 }
737 d_staticLearnCache.insert(in);
738
739 if (in.getKind() == kind::EQUAL) {
740 if(in[0].getKind() == kind::BITVECTOR_PLUS && in[1].getKind() == kind::BITVECTOR_SHL ||
741 in[1].getKind() == kind::BITVECTOR_PLUS && in[0].getKind() == kind::BITVECTOR_SHL){
742 TNode p = in[0].getKind() == kind::BITVECTOR_PLUS ? in[0] : in[1];
743 TNode s = in[0].getKind() == kind::BITVECTOR_PLUS ? in[1] : in[0];
744
745 if(p.getNumChildren() == 2
746 && p[0].getKind() == kind::BITVECTOR_SHL
747 && p[1].getKind() == kind::BITVECTOR_SHL ){
748 unsigned size = utils::getSize(s);
749 Node one = utils::mkConst(size, 1u);
750 if(s[0] == one && p[0][0] == one && p[1][0] == one){
751 Node zero = utils::mkConst(size, 0u);
752 TNode b = p[0];
753 TNode c = p[1];
754 // (s : 1 << S) = (b : 1 << B) + (c : 1 << C)
755 Node b_eq_0 = b.eqNode(zero);
756 Node c_eq_0 = c.eqNode(zero);
757 Node b_eq_c = b.eqNode(c);
758
759 Node dis = utils::mkNode(kind::OR, b_eq_0, c_eq_0, b_eq_c);
760 Node imp = in.impNode(dis);
761 learned << imp;
762 }
763 }
764 }
765 }else if(in.getKind() == kind::AND){
766 for(size_t i = 0, N = in.getNumChildren(); i < N; ++i){
767 ppStaticLearn(in[i], learned);
768 }
769 }
770 }
771
772 bool TheoryBV::applyAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions) {
773 bool changed = d_abstractionModule->applyAbstraction(assertions, new_assertions);
774 if (changed &&
775 options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER &&
776 options::bitvectorAig()) {
777 // disable AIG mode
778 AlwaysAssert (!d_eagerSolver->isInitialized());
779 d_eagerSolver->turnOffAig();
780 d_eagerSolver->initialize();
781 }
782 return changed;
783 }
784
785 void TheoryBV::setConflict(Node conflict) {
786 if (options::bvAbstraction()) {
787 Node new_conflict = d_abstractionModule->simplifyConflict(conflict);
788
789 std::vector<Node> lemmas;
790 lemmas.push_back(new_conflict);
791 d_abstractionModule->generalizeConflict(new_conflict, lemmas);
792 for (unsigned i = 0; i < lemmas.size(); ++i) {
793 lemma(utils::mkNode(kind::NOT, lemmas[i]));
794 }
795 }
796 d_conflict = true;
797 d_conflictNode = conflict;
798 }