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