Add bv util mkConst(unsigned, Integer&). (#1499)
[cvc5.git] / src / theory / bv / theory_bv.cpp
1 /********************* */
2 /*! \file theory_bv.cpp
3 ** \verbatim
4 ** Top contributors (to current version):
5 ** Liana Hadarean, Andrew Reynolds, Clark Barrett
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2017 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.\endverbatim
11 **
12 ** [[ Add lengthier description here ]]
13 ** \todo document this file
14 **/
15
16 #include "theory/bv/theory_bv.h"
17
18 #include "options/bv_options.h"
19 #include "options/smt_options.h"
20 #include "smt/smt_statistics_registry.h"
21 #include "theory/bv/abstraction.h"
22 #include "theory/bv/bv_eager_solver.h"
23 #include "theory/bv/bv_subtheory_algebraic.h"
24 #include "theory/bv/bv_subtheory_bitblast.h"
25 #include "theory/bv/bv_subtheory_core.h"
26 #include "theory/bv/bv_subtheory_inequality.h"
27 #include "theory/bv/slicer.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 #include "proof/theory_proof.h"
34 #include "proof/proof_manager.h"
35 #include "theory/valuation.h"
36
37 using namespace CVC4::context;
38 using namespace CVC4::theory::bv::utils;
39 using namespace std;
40
41 namespace CVC4 {
42 namespace theory {
43 namespace bv {
44
45 TheoryBV::TheoryBV(context::Context* c, context::UserContext* u,
46 OutputChannel& out, Valuation valuation,
47 const LogicInfo& logicInfo, std::string name)
48 : Theory(THEORY_BV, c, u, out, valuation, logicInfo, name),
49 d_context(c),
50 d_alreadyPropagatedSet(c),
51 d_sharedTermsSet(c),
52 d_subtheories(),
53 d_subtheoryMap(),
54 d_statistics(getFullInstanceName()),
55 d_staticLearnCache(),
56 d_BVDivByZero(),
57 d_BVRemByZero(),
58 d_funcToArgs(),
59 d_funcToSkolem(u),
60 d_lemmasAdded(c, false),
61 d_conflict(c, false),
62 d_invalidateModelCache(c, true),
63 d_literalsToPropagate(c),
64 d_literalsToPropagateIndex(c, 0),
65 d_propagatedBy(c),
66 d_eagerSolver(NULL),
67 d_abstractionModule(new AbstractionModule(getFullInstanceName())),
68 d_isCoreTheory(false),
69 d_calledPreregister(false),
70 d_needsLastCallCheck(false),
71 d_extf_range_infer(u),
72 d_extf_collapse_infer(u)
73 {
74 setupExtTheory();
75 getExtTheory()->addFunctionKind(kind::BITVECTOR_TO_NAT);
76 getExtTheory()->addFunctionKind(kind::INT_TO_BITVECTOR);
77
78 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
79 d_eagerSolver = new EagerBitblastSolver(this);
80 return;
81 }
82
83 if (options::bitvectorEqualitySolver()) {
84 SubtheorySolver* core_solver = new CoreSolver(c, this);
85 d_subtheories.push_back(core_solver);
86 d_subtheoryMap[SUB_CORE] = core_solver;
87 }
88
89 if (options::bitvectorInequalitySolver()) {
90 SubtheorySolver* ineq_solver = new InequalitySolver(c, u, this);
91 d_subtheories.push_back(ineq_solver);
92 d_subtheoryMap[SUB_INEQUALITY] = ineq_solver;
93 }
94
95 if (options::bitvectorAlgebraicSolver()) {
96 SubtheorySolver* alg_solver = new AlgebraicSolver(c, this);
97 d_subtheories.push_back(alg_solver);
98 d_subtheoryMap[SUB_ALGEBRAIC] = alg_solver;
99 }
100
101 BitblastSolver* bb_solver = new BitblastSolver(c, this);
102 if (options::bvAbstraction()) {
103 bb_solver->setAbstraction(d_abstractionModule);
104 }
105 d_subtheories.push_back(bb_solver);
106 d_subtheoryMap[SUB_BITBLAST] = bb_solver;
107 }
108
109 TheoryBV::~TheoryBV() {
110 if (d_eagerSolver) {
111 delete d_eagerSolver;
112 }
113 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
114 delete d_subtheories[i];
115 }
116 delete d_abstractionModule;
117 }
118
119 void TheoryBV::setMasterEqualityEngine(eq::EqualityEngine* eq) {
120 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
121 return;
122 }
123 if (options::bitvectorEqualitySolver()) {
124 dynamic_cast<CoreSolver*>(d_subtheoryMap[SUB_CORE])->setMasterEqualityEngine(eq);
125 }
126 }
127
128 void TheoryBV::spendResource(unsigned ammount) throw(UnsafeInterruptException) {
129 getOutputChannel().spendResource(ammount);
130 }
131
132 TheoryBV::Statistics::Statistics(const std::string &name):
133 d_avgConflictSize(name + "theory::bv::AvgBVConflictSize"),
134 d_solveSubstitutions(name + "theory::bv::NumberOfSolveSubstitutions", 0),
135 d_solveTimer(name + "theory::bv::solveTimer"),
136 d_numCallsToCheckFullEffort(name + "theory::bv::NumberOfFullCheckCalls", 0),
137 d_numCallsToCheckStandardEffort(name + "theory::bv::NumberOfStandardCheckCalls", 0),
138 d_weightComputationTimer(name + "theory::bv::weightComputationTimer"),
139 d_numMultSlice(name + "theory::bv::NumMultSliceApplied", 0)
140 {
141 smtStatisticsRegistry()->registerStat(&d_avgConflictSize);
142 smtStatisticsRegistry()->registerStat(&d_solveSubstitutions);
143 smtStatisticsRegistry()->registerStat(&d_solveTimer);
144 smtStatisticsRegistry()->registerStat(&d_numCallsToCheckFullEffort);
145 smtStatisticsRegistry()->registerStat(&d_numCallsToCheckStandardEffort);
146 smtStatisticsRegistry()->registerStat(&d_weightComputationTimer);
147 smtStatisticsRegistry()->registerStat(&d_numMultSlice);
148 }
149
150 TheoryBV::Statistics::~Statistics() {
151 smtStatisticsRegistry()->unregisterStat(&d_avgConflictSize);
152 smtStatisticsRegistry()->unregisterStat(&d_solveSubstitutions);
153 smtStatisticsRegistry()->unregisterStat(&d_solveTimer);
154 smtStatisticsRegistry()->unregisterStat(&d_numCallsToCheckFullEffort);
155 smtStatisticsRegistry()->unregisterStat(&d_numCallsToCheckStandardEffort);
156 smtStatisticsRegistry()->unregisterStat(&d_weightComputationTimer);
157 smtStatisticsRegistry()->unregisterStat(&d_numMultSlice);
158 }
159
160 Node TheoryBV::getBVDivByZero(Kind k, unsigned width) {
161 NodeManager* nm = NodeManager::currentNM();
162 if (k == kind::BITVECTOR_UDIV) {
163 if (d_BVDivByZero.find(width) == d_BVDivByZero.end()) {
164 // lazily create the function symbols
165 ostringstream os;
166 os << "BVUDivByZero_" << width;
167 Node divByZero = nm->mkSkolem(os.str(),
168 nm->mkFunctionType(nm->mkBitVectorType(width), nm->mkBitVectorType(width)),
169 "partial bvudiv", NodeManager::SKOLEM_EXACT_NAME);
170 d_BVDivByZero[width] = divByZero;
171 }
172 return d_BVDivByZero[width];
173 }
174 else if (k == kind::BITVECTOR_UREM) {
175 if (d_BVRemByZero.find(width) == d_BVRemByZero.end()) {
176 ostringstream os;
177 os << "BVURemByZero_" << width;
178 Node divByZero = nm->mkSkolem(os.str(),
179 nm->mkFunctionType(nm->mkBitVectorType(width), nm->mkBitVectorType(width)),
180 "partial bvurem", NodeManager::SKOLEM_EXACT_NAME);
181 d_BVRemByZero[width] = divByZero;
182 }
183 return d_BVRemByZero[width];
184 }
185
186 Unreachable();
187 }
188
189
190 void TheoryBV::collectFunctionSymbols(TNode term, TNodeSet& seen) {
191 if (seen.find(term) != seen.end())
192 return;
193 if (term.getKind() == kind::APPLY_UF) {
194 TNode func = term.getOperator();
195 storeFunction(func, term);
196 } else if (term.getKind() == kind::SELECT) {
197 TNode func = term[0];
198 storeFunction(func, term);
199 } else if (term.getKind() == kind::STORE) {
200 AlwaysAssert(false, "Cannot use eager bitblasting on QF_ABV formula with stores");
201 }
202 for (unsigned i = 0; i < term.getNumChildren(); ++i) {
203 collectFunctionSymbols(term[i], seen);
204 }
205 seen.insert(term);
206 }
207
208 void TheoryBV::storeFunction(TNode func, TNode term) {
209 if (d_funcToArgs.find(func) == d_funcToArgs.end()) {
210 d_funcToArgs.insert(make_pair(func, NodeSet()));
211 }
212 NodeSet& set = d_funcToArgs[func];
213 if (set.find(term) == set.end()) {
214 set.insert(term);
215 Node skolem = utils::mkVar(utils::getSize(term));
216 d_funcToSkolem.addSubstitution(term, skolem);
217 }
218 }
219
220 void TheoryBV::mkAckermanizationAssertions(std::vector<Node>& assertions) {
221 Debug("bv-ackermanize") << "TheoryBV::mkAckermanizationAssertions\n";
222
223 Assert(options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER);
224 AlwaysAssert(!options::incrementalSolving());
225 TNodeSet seen;
226 for (unsigned i = 0; i < assertions.size(); ++i) {
227 collectFunctionSymbols(assertions[i], seen);
228 }
229
230 FunctionToArgs::const_iterator it = d_funcToArgs.begin();
231 NodeManager* nm = NodeManager::currentNM();
232 for (; it!= d_funcToArgs.end(); ++it) {
233 TNode func = it->first;
234 const NodeSet& args = it->second;
235 NodeSet::const_iterator it1 = args.begin();
236 for ( ; it1 != args.end(); ++it1) {
237 for(NodeSet::const_iterator it2 = it1; it2 != args.end(); ++it2) {
238 TNode args1 = *it1;
239 TNode args2 = *it2;
240 Node args_eq;
241
242 if (args1.getKind() == kind::APPLY_UF) {
243 AlwaysAssert (args1.getKind() == kind::APPLY_UF &&
244 args1.getOperator() == func);
245 AlwaysAssert (args2.getKind() == kind::APPLY_UF &&
246 args2.getOperator() == func);
247 AlwaysAssert (args1.getNumChildren() == args2.getNumChildren());
248
249 std::vector<Node> eqs(args1.getNumChildren());
250
251 for (unsigned i = 0; i < args1.getNumChildren(); ++i) {
252 eqs[i] = nm->mkNode(kind::EQUAL, args1[i], args2[i]);
253 }
254 args_eq = eqs.size() == 1 ? eqs[0] : nm->mkNode(kind::AND, eqs);
255 } else {
256 AlwaysAssert (args1.getKind() == kind::SELECT &&
257 args1[0] == func);
258 AlwaysAssert (args2.getKind() == kind::SELECT &&
259 args2[0] == func);
260 AlwaysAssert (args1.getNumChildren() == 2);
261 AlwaysAssert (args2.getNumChildren() == 2);
262 args_eq = nm->mkNode(kind::EQUAL, args1[1], args2[1]);
263 }
264 Node func_eq = nm->mkNode(kind::EQUAL, args1, args2);
265 Node lemma = nm->mkNode(kind::IMPLIES, args_eq, func_eq);
266 assertions.push_back(lemma);
267 }
268 }
269 }
270
271 // replace applications of UF by skolems (FIXME for model building)
272 for(unsigned i = 0; i < assertions.size(); ++i) {
273 assertions[i] = d_funcToSkolem.apply(assertions[i]);
274 }
275 }
276
277 Node TheoryBV::expandDefinition(LogicRequest &logicRequest, Node node) {
278 Debug("bitvector-expandDefinition") << "TheoryBV::expandDefinition(" << node << ")" << std::endl;
279
280 switch (node.getKind()) {
281 case kind::BITVECTOR_SDIV:
282 case kind::BITVECTOR_SREM:
283 case kind::BITVECTOR_SMOD:
284 return TheoryBVRewriter::eliminateBVSDiv(node);
285 break;
286
287 case kind::BITVECTOR_UDIV:
288 case kind::BITVECTOR_UREM: {
289 NodeManager* nm = NodeManager::currentNM();
290 unsigned width = node.getType().getBitVectorSize();
291
292 if (options::bitvectorDivByZeroConst()) {
293 Kind kind = node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_UDIV_TOTAL : kind::BITVECTOR_UREM_TOTAL;
294 return nm->mkNode(kind, node[0], node[1]);
295 }
296
297 TNode num = node[0], den = node[1];
298 Node den_eq_0 = nm->mkNode(kind::EQUAL, den, utils::mkZero(width));
299 Node divTotalNumDen = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_UDIV_TOTAL :
300 kind::BITVECTOR_UREM_TOTAL, num, den);
301
302 // if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
303 // // Ackermanize UF if using eager bit-blasting
304 // Node ackerman_var = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_ACKERMANIZE_UDIV : kind::BITVECTOR_ACKERMANIZE_UREM, num);
305 // node = nm->mkNode(kind::ITE, den_eq_0, ackerman_var, divTotalNumDen);
306 // return node;
307 // } else {
308 Node divByZero = getBVDivByZero(node.getKind(), width);
309 Node divByZeroNum = nm->mkNode(kind::APPLY_UF, divByZero, num);
310 node = nm->mkNode(kind::ITE, den_eq_0, divByZeroNum, divTotalNumDen);
311 logicRequest.widenLogic(THEORY_UF);
312 return node;
313 //}
314 }
315 break;
316
317 default:
318 return node;
319 break;
320 }
321
322 Unreachable();
323 }
324
325
326 void TheoryBV::preRegisterTerm(TNode node) {
327 d_calledPreregister = true;
328 Debug("bitvector-preregister") << "TheoryBV::preRegister(" << node << ")" << std::endl;
329
330 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
331 // the aig bit-blaster option is set heuristically
332 // if bv abstraction is not used
333 if (!d_eagerSolver->isInitialized()) {
334 d_eagerSolver->initialize();
335 }
336
337 if (node.getKind() == kind::BITVECTOR_EAGER_ATOM) {
338 Node formula = node[0];
339 d_eagerSolver->assertFormula(formula);
340 }
341 // nothing to do for the other terms
342 return;
343 }
344
345 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
346 d_subtheories[i]->preRegister(node);
347 }
348
349 // AJR : equality solver currently registers all terms to ExtTheory, if we want a lazy reduction without the bv equality solver, need to call this
350 //getExtTheory()->registerTermRec( node );
351 }
352
353 void TheoryBV::sendConflict() {
354 Assert(d_conflict);
355 if (d_conflictNode.isNull()) {
356 return;
357 } else {
358 Debug("bitvector") << indent() << "TheoryBV::check(): conflict " << d_conflictNode << std::endl;
359 d_out->conflict(d_conflictNode);
360 d_statistics.d_avgConflictSize.addEntry(d_conflictNode.getNumChildren());
361 d_conflictNode = Node::null();
362 }
363 }
364
365 void TheoryBV::checkForLemma(TNode fact) {
366 if (fact.getKind() == kind::EQUAL) {
367 if (fact[0].getKind() == kind::BITVECTOR_UREM_TOTAL) {
368 TNode urem = fact[0];
369 TNode result = fact[1];
370 TNode divisor = urem[1];
371 Node result_ult_div = mkNode(kind::BITVECTOR_ULT, result, divisor);
372 Node divisor_eq_0 = mkNode(
373 kind::EQUAL, divisor, mkZero(getSize(divisor)));
374 Node split = utils::mkNode(
375 kind::OR, divisor_eq_0, mkNode(kind::NOT, fact), result_ult_div);
376 lemma(split);
377 }
378 if (fact[1].getKind() == kind::BITVECTOR_UREM_TOTAL) {
379 TNode urem = fact[1];
380 TNode result = fact[0];
381 TNode divisor = urem[1];
382 Node result_ult_div = mkNode(kind::BITVECTOR_ULT, result, divisor);
383 Node divisor_eq_0 = mkNode(
384 kind::EQUAL, divisor, mkZero(getSize(divisor)));
385 Node split = utils::mkNode(
386 kind::OR, divisor_eq_0, mkNode(kind::NOT, fact), result_ult_div);
387 lemma(split);
388 }
389 }
390 }
391
392 void TheoryBV::check(Effort e)
393 {
394 if (done() && e<Theory::EFFORT_FULL) {
395 return;
396 }
397
398 //last call : do reductions on extended bitvector functions
399 if (e == Theory::EFFORT_LAST_CALL) {
400 std::vector<Node> nred = getExtTheory()->getActive();
401 doExtfReductions(nred);
402 return;
403 }
404
405 TimerStat::CodeTimer checkTimer(d_checkTime);
406 Debug("bitvector") << "TheoryBV::check(" << e << ")" << std::endl;
407 TimerStat::CodeTimer codeTimer(d_statistics.d_solveTimer);
408 // we may be getting new assertions so the model cache may not be sound
409 d_invalidateModelCache.set(true);
410 // if we are using the eager solver
411 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
412 // this can only happen on an empty benchmark
413 if (!d_eagerSolver->isInitialized()) {
414 d_eagerSolver->initialize();
415 }
416 if (!Theory::fullEffort(e))
417 return;
418
419 std::vector<TNode> assertions;
420 while (!done()) {
421 TNode fact = get().assertion;
422 Assert (fact.getKind() == kind::BITVECTOR_EAGER_ATOM);
423 assertions.push_back(fact);
424 }
425 Assert (d_eagerSolver->hasAssertions(assertions));
426
427 bool ok = d_eagerSolver->checkSat();
428 if (!ok) {
429 if (assertions.size() == 1) {
430 d_out->conflict(assertions[0]);
431 return;
432 }
433 Node conflict = NodeManager::currentNM()->mkNode(kind::AND, assertions);
434 d_out->conflict(conflict);
435 return;
436 }
437 return;
438 }
439
440
441 if (Theory::fullEffort(e)) {
442 ++(d_statistics.d_numCallsToCheckFullEffort);
443 } else {
444 ++(d_statistics.d_numCallsToCheckStandardEffort);
445 }
446 // if we are already in conflict just return the conflict
447 if (inConflict()) {
448 sendConflict();
449 return;
450 }
451
452 while (!done()) {
453 TNode fact = get().assertion;
454
455 checkForLemma(fact);
456
457 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
458 d_subtheories[i]->assertFact(fact);
459 }
460 }
461
462 bool ok = true;
463 bool complete = false;
464 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
465 Assert (!inConflict());
466 ok = d_subtheories[i]->check(e);
467 complete = d_subtheories[i]->isComplete();
468
469 if (!ok) {
470 // if we are in a conflict no need to check with other theories
471 Assert (inConflict());
472 sendConflict();
473 return;
474 }
475 if (complete) {
476 // if the last subtheory was complete we stop
477 break;
478 }
479 }
480
481 //check extended functions
482 if (Theory::fullEffort(e)) {
483 //do inferences (adds external lemmas) TODO: this can be improved to add internal inferences
484 std::vector< Node > nred;
485 if( getExtTheory()->doInferences( 0, nred ) ){
486 return;
487 }
488 d_needsLastCallCheck = false;
489 if( !nred.empty() ){
490 //other inferences involving bv2nat, int2bv
491 if( options::bvAlgExtf() ){
492 if( doExtfInferences( nred ) ){
493 return;
494 }
495 }
496 if( !options::bvLazyReduceExtf() ){
497 if( doExtfReductions( nred ) ){
498 return;
499 }
500 }else{
501 d_needsLastCallCheck = true;
502 }
503 }
504 }
505 }
506
507 bool TheoryBV::doExtfInferences( std::vector< Node >& terms ) {
508 bool sentLemma = false;
509 eq::EqualityEngine * ee = getEqualityEngine();
510 std::map< Node, Node > op_map;
511 for( unsigned j=0; j<terms.size(); j++ ){
512 TNode n = terms[j];
513 Assert (n.getKind() == kind::BITVECTOR_TO_NAT
514 || n.getKind() == kind::INT_TO_BITVECTOR );
515 if( n.getKind()==kind::BITVECTOR_TO_NAT ){
516 //range lemmas
517 if( d_extf_range_infer.find( n )==d_extf_range_infer.end() ){
518 d_extf_range_infer.insert( n );
519 unsigned bvs = n[0].getType().getBitVectorSize();
520 Node min = NodeManager::currentNM()->mkConst( Rational( 0 ) );
521 Node max = NodeManager::currentNM()->mkConst( Rational( Integer(1).multiplyByPow2(bvs) ) );
522 Node lem = NodeManager::currentNM()->mkNode( kind::AND, NodeManager::currentNM()->mkNode( kind::GEQ, n, min ), NodeManager::currentNM()->mkNode( kind::LT, n, max ) );
523 Trace("bv-extf-lemma") << "BV extf lemma (range) : " << lem << std::endl;
524 d_out->lemma( lem );
525 sentLemma = true;
526 }
527 }
528 Node r = ( ee && ee->hasTerm( n[0] ) ) ? ee->getRepresentative( n[0] ) : n[0];
529 op_map[r] = n;
530 }
531 for( unsigned j=0; j<terms.size(); j++ ){
532 TNode n = terms[j];
533 Node r = ( ee && ee->hasTerm( n[0] ) ) ? ee->getRepresentative( n ) : n;
534 std::map< Node, Node >::iterator it = op_map.find( r );
535 if( it!=op_map.end() ){
536 Node parent = it->second;
537 //Node cterm = parent[0]==n ? parent : NodeManager::currentNM()->mkNode( parent.getOperator(), n );
538 Node cterm = parent[0].eqNode( n );
539 Trace("bv-extf-lemma-debug") << "BV extf collapse based on : " << cterm << std::endl;
540 if( d_extf_collapse_infer.find( cterm )==d_extf_collapse_infer.end() ){
541 d_extf_collapse_infer.insert( cterm );
542
543 Node t = n[0];
544 if( n.getKind()==kind::INT_TO_BITVECTOR ){
545 Assert( t.getType().isInteger() );
546 //congruent modulo 2^( bv width )
547 unsigned bvs = n.getType().getBitVectorSize();
548 Node coeff = NodeManager::currentNM()->mkConst( Rational( Integer(1).multiplyByPow2(bvs) ) );
549 Node k = NodeManager::currentNM()->mkSkolem( "int_bv_cong", t.getType(), "for int2bv/bv2nat congruence" );
550 t = NodeManager::currentNM()->mkNode( kind::PLUS, t, NodeManager::currentNM()->mkNode( kind::MULT, coeff, k ) );
551 }
552 Node lem = parent.eqNode( t );
553
554 if( parent[0]!=n ){
555 Assert( ee->areEqual( parent[0], n ) );
556 lem = NodeManager::currentNM()->mkNode( kind::IMPLIES, parent[0].eqNode( n ), lem );
557 }
558 Trace("bv-extf-lemma") << "BV extf lemma (collapse) : " << lem << std::endl;
559 d_out->lemma( lem );
560 sentLemma = true;
561 }
562 }
563 }
564 return sentLemma;
565 }
566
567 bool TheoryBV::doExtfReductions( std::vector< Node >& terms ) {
568 std::vector< Node > nredr;
569 if( getExtTheory()->doReductions( 0, terms, nredr ) ){
570 return true;
571 }
572 Assert( nredr.empty() );
573 return false;
574 }
575
576 bool TheoryBV::needsCheckLastEffort() {
577 return d_needsLastCallCheck;
578 }
579 bool TheoryBV::collectModelInfo(TheoryModel* m)
580 {
581 Assert(!inConflict());
582 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
583 if (!d_eagerSolver->collectModelInfo(m, true))
584 {
585 return false;
586 }
587 }
588 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
589 if (d_subtheories[i]->isComplete()) {
590 return d_subtheories[i]->collectModelInfo(m, true);
591 }
592 }
593 return true;
594 }
595
596 Node TheoryBV::getModelValue(TNode var) {
597 Assert(!inConflict());
598 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
599 if (d_subtheories[i]->isComplete()) {
600 return d_subtheories[i]->getModelValue(var);
601 }
602 }
603 Unreachable();
604 }
605
606 void TheoryBV::propagate(Effort e) {
607 Debug("bitvector") << indent() << "TheoryBV::propagate()" << std::endl;
608 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
609 return;
610 }
611
612 if (inConflict()) {
613 return;
614 }
615
616 // go through stored propagations
617 bool ok = true;
618 for (; d_literalsToPropagateIndex < d_literalsToPropagate.size() && ok; d_literalsToPropagateIndex = d_literalsToPropagateIndex + 1) {
619 TNode literal = d_literalsToPropagate[d_literalsToPropagateIndex];
620 // temporary fix for incremental bit-blasting
621 if (d_valuation.isSatLiteral(literal)) {
622 Debug("bitvector::propagate") << "TheoryBV:: propagating " << literal <<"\n";
623 ok = d_out->propagate(literal);
624 }
625 }
626
627 if (!ok) {
628 Debug("bitvector::propagate") << indent() << "TheoryBV::propagate(): conflict from theory engine" << std::endl;
629 setConflict();
630 }
631 }
632
633
634 eq::EqualityEngine * TheoryBV::getEqualityEngine() {
635 CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
636 if( core ){
637 return core->getEqualityEngine();
638 }else{
639 return NULL;
640 }
641 }
642
643 bool TheoryBV::getCurrentSubstitution( int effort, std::vector< Node >& vars, std::vector< Node >& subs, std::map< Node, std::vector< Node > >& exp ) {
644 eq::EqualityEngine * ee = getEqualityEngine();
645 if( ee ){
646 //get the constant equivalence classes
647 bool retVal = false;
648 for( unsigned i=0; i<vars.size(); i++ ){
649 Node n = vars[i];
650 if( ee->hasTerm( n ) ){
651 Node nr = ee->getRepresentative( n );
652 if( nr.isConst() ){
653 subs.push_back( nr );
654 exp[n].push_back( n.eqNode( nr ) );
655 retVal = true;
656 }else{
657 subs.push_back( n );
658 }
659 }else{
660 subs.push_back( n );
661 }
662 }
663 //return true if the substitution is non-trivial
664 return retVal;
665 }
666 return false;
667 }
668
669 int TheoryBV::getReduction( int effort, Node n, Node& nr ) {
670 Trace("bv-ext") << "TheoryBV::checkExt : non-reduced : " << n << std::endl;
671 if( n.getKind()==kind::BITVECTOR_TO_NAT ){
672 //taken from rewrite code
673 const unsigned size = utils::getSize(n[0]);
674 NodeManager* const nm = NodeManager::currentNM();
675 const Node z = nm->mkConst(Rational(0));
676 const Node bvone = utils::mkOne(1);
677 NodeBuilder<> result(kind::PLUS);
678 Integer i = 1;
679 for(unsigned bit = 0; bit < size; ++bit, i *= 2) {
680 Node cond = nm->mkNode(kind::EQUAL, nm->mkNode(nm->mkConst(BitVectorExtract(bit, bit)), n[0]), bvone);
681 result << nm->mkNode(kind::ITE, cond, nm->mkConst(Rational(i)), z);
682 }
683 nr = Node(result);
684 return -1;
685 }else if( n.getKind()==kind::INT_TO_BITVECTOR ){
686 //taken from rewrite code
687 const unsigned size = n.getOperator().getConst<IntToBitVector>().size;
688 NodeManager* const nm = NodeManager::currentNM();
689 const Node bvzero = utils::mkZero(1);
690 const Node bvone = utils::mkOne(1);
691 std::vector<Node> v;
692 Integer i = 2;
693 while(v.size() < size) {
694 Node cond = nm->mkNode(kind::GEQ, nm->mkNode(kind::INTS_MODULUS_TOTAL, n[0], nm->mkConst(Rational(i))), nm->mkConst(Rational(i, 2)));
695 cond = Rewriter::rewrite( cond );
696 v.push_back(nm->mkNode(kind::ITE, cond, bvone, bvzero));
697 i *= 2;
698 }
699 NodeBuilder<> result(kind::BITVECTOR_CONCAT);
700 result.append(v.rbegin(), v.rend());
701 nr = Node(result);
702 return -1;
703 }
704 return 0;
705 }
706
707 Theory::PPAssertStatus TheoryBV::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
708 switch(in.getKind()) {
709 case kind::EQUAL:
710 {
711 if (in[0].isVar() && !in[1].hasSubterm(in[0])) {
712 ++(d_statistics.d_solveSubstitutions);
713 outSubstitutions.addSubstitution(in[0], in[1]);
714 return PP_ASSERT_STATUS_SOLVED;
715 }
716 if (in[1].isVar() && !in[0].hasSubterm(in[1])) {
717 ++(d_statistics.d_solveSubstitutions);
718 outSubstitutions.addSubstitution(in[1], in[0]);
719 return PP_ASSERT_STATUS_SOLVED;
720 }
721 Node node = Rewriter::rewrite(in);
722 if ((node[0].getKind() == kind::BITVECTOR_EXTRACT && node[1].isConst()) ||
723 (node[1].getKind() == kind::BITVECTOR_EXTRACT && node[0].isConst())) {
724 Node extract = node[0].isConst() ? node[1] : node[0];
725 if (extract[0].getKind() == kind::VARIABLE) {
726 Node c = node[0].isConst() ? node[0] : node[1];
727
728 unsigned high = utils::getExtractHigh(extract);
729 unsigned low = utils::getExtractLow(extract);
730 unsigned var_bitwidth = utils::getSize(extract[0]);
731 std::vector<Node> children;
732
733 if (low == 0) {
734 Assert (high != var_bitwidth - 1);
735 unsigned skolem_size = var_bitwidth - high - 1;
736 Node skolem = utils::mkVar(skolem_size);
737 children.push_back(skolem);
738 children.push_back(c);
739 } else if (high == var_bitwidth - 1) {
740 unsigned skolem_size = low;
741 Node skolem = utils::mkVar(skolem_size);
742 children.push_back(c);
743 children.push_back(skolem);
744 } else {
745 unsigned skolem1_size = low;
746 unsigned skolem2_size = var_bitwidth - high - 1;
747 Node skolem1 = utils::mkVar(skolem1_size);
748 Node skolem2 = utils::mkVar(skolem2_size);
749 children.push_back(skolem2);
750 children.push_back(c);
751 children.push_back(skolem1);
752 }
753 Node concat = utils::mkNode(kind::BITVECTOR_CONCAT, children);
754 Assert (utils::getSize(concat) == utils::getSize(extract[0]));
755 outSubstitutions.addSubstitution(extract[0], concat);
756 return PP_ASSERT_STATUS_SOLVED;
757 }
758 }
759 }
760 break;
761 case kind::BITVECTOR_ULT:
762 case kind::BITVECTOR_SLT:
763 case kind::BITVECTOR_ULE:
764 case kind::BITVECTOR_SLE:
765
766 default:
767 // TODO other predicates
768 break;
769 }
770 return PP_ASSERT_STATUS_UNSOLVED;
771 }
772
773 Node TheoryBV::ppRewrite(TNode t)
774 {
775 Debug("bv-pp-rewrite") << "TheoryBV::ppRewrite " << t << "\n";
776 Node res = t;
777 if (RewriteRule<BitwiseEq>::applies(t)) {
778 Node result = RewriteRule<BitwiseEq>::run<false>(t);
779 res = Rewriter::rewrite(result);
780 } else if (d_isCoreTheory && t.getKind() == kind::EQUAL) {
781 std::vector<Node> equalities;
782 Slicer::splitEqualities(t, equalities);
783 res = utils::mkAnd(equalities);
784 } else if (RewriteRule<UltPlusOne>::applies(t)) {
785 Node result = RewriteRule<UltPlusOne>::run<false>(t);
786 res = Rewriter::rewrite(result);
787 } else if( res.getKind() == kind::EQUAL &&
788 ((res[0].getKind() == kind::BITVECTOR_PLUS &&
789 RewriteRule<ConcatToMult>::applies(res[1])) ||
790 (res[1].getKind() == kind::BITVECTOR_PLUS &&
791 RewriteRule<ConcatToMult>::applies(res[0])))) {
792 Node mult = RewriteRule<ConcatToMult>::applies(res[0])?
793 RewriteRule<ConcatToMult>::run<false>(res[0]) :
794 RewriteRule<ConcatToMult>::run<true>(res[1]);
795 Node factor = mult[0];
796 Node sum = RewriteRule<ConcatToMult>::applies(res[0])? res[1] : res[0];
797 Node new_eq =utils::mkNode(kind::EQUAL, sum, mult);
798 Node rewr_eq = RewriteRule<SolveEq>::run<true>(new_eq);
799 if (rewr_eq[0].isVar() || rewr_eq[1].isVar()){
800 res = Rewriter::rewrite(rewr_eq);
801 } else {
802 res = t;
803 }
804 } else if (RewriteRule<SignExtendEqConst>::applies(t)) {
805 res = RewriteRule<SignExtendEqConst>::run<false>(t);
806 } else if (RewriteRule<ZeroExtendEqConst>::applies(t)) {
807 res = RewriteRule<ZeroExtendEqConst>::run<false>(t);
808 }
809
810
811 // if(t.getKind() == kind::EQUAL &&
812 // ((t[0].getKind() == kind::BITVECTOR_MULT && t[1].getKind() == kind::BITVECTOR_PLUS) ||
813 // (t[1].getKind() == kind::BITVECTOR_MULT && t[0].getKind() == kind::BITVECTOR_PLUS))) {
814 // // if we have an equality between a multiplication and addition
815 // // try to express multiplication in terms of addition
816 // Node mult = t[0].getKind() == kind::BITVECTOR_MULT? t[0] : t[1];
817 // Node add = t[0].getKind() == kind::BITVECTOR_PLUS? t[0] : t[1];
818 // if (RewriteRule<MultSlice>::applies(mult)) {
819 // Node new_mult = RewriteRule<MultSlice>::run<false>(mult);
820 // Node new_eq = Rewriter::rewrite(utils::mkNode(kind::EQUAL, new_mult, add));
821
822 // // the simplification can cause the formula to blow up
823 // // only apply if formula reduced
824 // if (d_subtheoryMap.find(SUB_BITBLAST) != d_subtheoryMap.end()) {
825 // BitblastSolver* bv = (BitblastSolver*)d_subtheoryMap[SUB_BITBLAST];
826 // uint64_t old_size = bv->computeAtomWeight(t);
827 // Assert (old_size);
828 // uint64_t new_size = bv->computeAtomWeight(new_eq);
829 // double ratio = ((double)new_size)/old_size;
830 // if (ratio <= 0.4) {
831 // ++(d_statistics.d_numMultSlice);
832 // return new_eq;
833 // }
834 // }
835
836 // if (new_eq.getKind() == kind::CONST_BOOLEAN) {
837 // ++(d_statistics.d_numMultSlice);
838 // return new_eq;
839 // }
840 // }
841 // }
842
843 if (options::bvAbstraction() && t.getType().isBoolean()) {
844 d_abstractionModule->addInputAtom(res);
845 }
846 Debug("bv-pp-rewrite") << "to " << res << "\n";
847 return res;
848 }
849
850 void TheoryBV::presolve() {
851 Debug("bitvector") << "TheoryBV::presolve" << endl;
852 }
853
854 static int prop_count = 0;
855
856 bool TheoryBV::storePropagation(TNode literal, SubTheory subtheory)
857 {
858 Debug("bitvector::propagate") << indent() << getSatContext()->getLevel() << " " << "TheoryBV::storePropagation(" << literal << ", " << subtheory << ")" << std::endl;
859 prop_count++;
860
861 // If already in conflict, no more propagation
862 if (d_conflict) {
863 Debug("bitvector::propagate") << indent() << "TheoryBV::storePropagation(" << literal << ", " << subtheory << "): already in conflict" << std::endl;
864 return false;
865 }
866
867 // If propagated already, just skip
868 PropagatedMap::const_iterator find = d_propagatedBy.find(literal);
869 if (find != d_propagatedBy.end()) {
870 return true;
871 } else {
872 bool polarity = literal.getKind() != kind::NOT;
873 Node negatedLiteral = polarity ? literal.notNode() : (Node) literal[0];
874 find = d_propagatedBy.find(negatedLiteral);
875 if (find != d_propagatedBy.end() && (*find).second != subtheory) {
876 // Safe to ignore this one, subtheory should produce a conflict
877 return true;
878 }
879
880 d_propagatedBy[literal] = subtheory;
881 }
882
883 // Propagate differs depending on the subtheory
884 // * bitblaster needs to be left alone until it's done, otherwise it doesn't know how to explain
885 // * equality engine can propagate eagerly
886 bool ok = true;
887 if (subtheory == SUB_CORE) {
888 d_out->propagate(literal);
889 if (!ok) {
890 setConflict();
891 }
892 } else {
893 d_literalsToPropagate.push_back(literal);
894 }
895 return ok;
896
897 }/* TheoryBV::propagate(TNode) */
898
899
900 void TheoryBV::explain(TNode literal, std::vector<TNode>& assumptions) {
901 Assert (wasPropagatedBySubtheory(literal));
902 SubTheory sub = getPropagatingSubtheory(literal);
903 d_subtheoryMap[sub]->explain(literal, assumptions);
904 }
905
906
907 Node TheoryBV::explain(TNode node) {
908 Debug("bitvector::explain") << "TheoryBV::explain(" << node << ")" << std::endl;
909 std::vector<TNode> assumptions;
910
911 // Ask for the explanation
912 explain(node, assumptions);
913 // this means that it is something true at level 0
914 if (assumptions.size() == 0) {
915 return utils::mkTrue();
916 }
917 // return the explanation
918 Node explanation = utils::mkAnd(assumptions);
919 Debug("bitvector::explain") << "TheoryBV::explain(" << node << ") => " << explanation << std::endl;
920 Debug("bitvector::explain") << "TheoryBV::explain done. \n";
921 return explanation;
922 }
923
924
925 void TheoryBV::addSharedTerm(TNode t) {
926 Debug("bitvector::sharing") << indent() << "TheoryBV::addSharedTerm(" << t << ")" << std::endl;
927 d_sharedTermsSet.insert(t);
928 if (options::bitvectorEqualitySolver()) {
929 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
930 d_subtheories[i]->addSharedTerm(t);
931 }
932 }
933 }
934
935
936 EqualityStatus TheoryBV::getEqualityStatus(TNode a, TNode b)
937 {
938 if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER)
939 return EQUALITY_UNKNOWN;
940 Assert (options::bitblastMode() == theory::bv::BITBLAST_MODE_LAZY);
941 for (unsigned i = 0; i < d_subtheories.size(); ++i) {
942 EqualityStatus status = d_subtheories[i]->getEqualityStatus(a, b);
943 if (status != EQUALITY_UNKNOWN) {
944 return status;
945 }
946 }
947 return EQUALITY_UNKNOWN; ;
948 }
949
950
951 void TheoryBV::enableCoreTheorySlicer() {
952 Assert (!d_calledPreregister);
953 d_isCoreTheory = true;
954 if (d_subtheoryMap.find(SUB_CORE) != d_subtheoryMap.end()) {
955 CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
956 core->enableSlicer();
957 }
958 }
959
960
961 void TheoryBV::ppStaticLearn(TNode in, NodeBuilder<>& learned) {
962 if(d_staticLearnCache.find(in) != d_staticLearnCache.end()){
963 return;
964 }
965 d_staticLearnCache.insert(in);
966
967 if (in.getKind() == kind::EQUAL) {
968 if((in[0].getKind() == kind::BITVECTOR_PLUS && in[1].getKind() == kind::BITVECTOR_SHL) ||
969 (in[1].getKind() == kind::BITVECTOR_PLUS && in[0].getKind() == kind::BITVECTOR_SHL)) {
970 TNode p = in[0].getKind() == kind::BITVECTOR_PLUS ? in[0] : in[1];
971 TNode s = in[0].getKind() == kind::BITVECTOR_PLUS ? in[1] : in[0];
972
973 if(p.getNumChildren() == 2
974 && p[0].getKind() == kind::BITVECTOR_SHL
975 && p[1].getKind() == kind::BITVECTOR_SHL ){
976 unsigned size = utils::getSize(s);
977 Node one = utils::mkConst(size, 1u);
978 if(s[0] == one && p[0][0] == one && p[1][0] == one){
979 Node zero = utils::mkConst(size, 0u);
980 TNode b = p[0];
981 TNode c = p[1];
982 // (s : 1 << S) = (b : 1 << B) + (c : 1 << C)
983 Node b_eq_0 = b.eqNode(zero);
984 Node c_eq_0 = c.eqNode(zero);
985 Node b_eq_c = b.eqNode(c);
986
987 Node dis = utils::mkNode(kind::OR, b_eq_0, c_eq_0, b_eq_c);
988 Node imp = in.impNode(dis);
989 learned << imp;
990 }
991 }
992 }
993 }else if(in.getKind() == kind::AND){
994 for(size_t i = 0, N = in.getNumChildren(); i < N; ++i){
995 ppStaticLearn(in[i], learned);
996 }
997 }
998 }
999
1000 bool TheoryBV::applyAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions) {
1001 bool changed = d_abstractionModule->applyAbstraction(assertions, new_assertions);
1002 if (changed &&
1003 options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER &&
1004 options::bitvectorAig()) {
1005 // disable AIG mode
1006 AlwaysAssert (!d_eagerSolver->isInitialized());
1007 d_eagerSolver->turnOffAig();
1008 d_eagerSolver->initialize();
1009 }
1010 return changed;
1011 }
1012
1013 void TheoryBV::setProofLog( BitVectorProof * bvp ) {
1014 if( options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER ){
1015 d_eagerSolver->setProofLog( bvp );
1016 }else{
1017 for( unsigned i=0; i< d_subtheories.size(); i++ ){
1018 d_subtheories[i]->setProofLog( bvp );
1019 }
1020 }
1021 }
1022
1023 void TheoryBV::setConflict(Node conflict) {
1024 if (options::bvAbstraction()) {
1025 Node new_conflict = d_abstractionModule->simplifyConflict(conflict);
1026
1027 std::vector<Node> lemmas;
1028 lemmas.push_back(new_conflict);
1029 d_abstractionModule->generalizeConflict(new_conflict, lemmas);
1030 for (unsigned i = 0; i < lemmas.size(); ++i) {
1031 lemma(utils::mkNode(kind::NOT, lemmas[i]));
1032 }
1033 }
1034 d_conflict = true;
1035 d_conflictNode = conflict;
1036 }
1037
1038 } /* namespace CVC4::theory::bv */
1039 } /* namespace CVC4::theory */
1040 } /* namespace CVC4 */