getBBTerm(node, bits);
return;
}
+ Assert( node.getType().isBitVector() );
Debug("bitvector-bitblast") << "Bitblasting term " << node <<"\n";
d_termBBStrategies[node.getKind()] (node, bits, this);
// don't bit-blast lemma atoms
continue;
}
+ if( !utils::isBitblastAtom(atom) ){
+ continue;
+ }
Debug("bitblast-queue") << "Bitblasting atom " << atom <<"\n";
{
TimerStat::CodeTimer codeTimer(d_bitblaster->d_statistics.d_bitblastTimer);
++(d_statistics.d_numCallstoCheck);
+ Debug("bv-bitblast-debug") << "...process queue" << std::endl;
//// Lazy bit-blasting
// bit-blast enqueued nodes
bitblastQueue();
continue;
}
}
+ //skip facts involving integer equalities (from bv2nat)
+ if( !utils::isBitblastAtom( fact ) ){
+ continue;
+ }
if (!d_bv->inConflict() &&
(!d_bv->wasPropagatedBySubtheory(fact) || d_bv->getPropagatingSubtheory(fact) != SUB_BITBLAST)) {
}
}
+ Debug("bv-bitblast-debug") << "...do propagation" << std::endl;
// We need to ensure we are fully propagated, so propagate now
if (d_useSatPropagation) {
d_bv->spendResource(1);
}
// Solving
+ Debug("bv-bitblast-debug") << "...do solving" << std::endl;
if (e == Theory::EFFORT_FULL) {
Assert(!d_bv->inConflict());
Debug("bitvector::bitblaster") << "BitblastSolver::addAssertions solving. \n";
}
}
+ Debug("bv-bitblast-debug") << "...do abs bb" << std::endl;
if (options::bvAbstraction() &&
e == Theory::EFFORT_FULL &&
d_lemmaAtomsQueue.size()) {
// bit-blast lemma atoms
while(!d_lemmaAtomsQueue.empty()) {
TNode lemma_atom = d_lemmaAtomsQueue.front();
- d_bitblaster->bbAtom(lemma_atom);
d_lemmaAtomsQueue.pop();
-
+ if( !utils::isBitblastAtom( lemma_atom ) ){
+ continue;
+ }
+ d_bitblaster->bbAtom(lemma_atom);
// Assert to sat and check for conflicts
bool ok = d_bitblaster->assertToSat(lemma_atom, d_useSatPropagation);
if (!ok) {
// d_equalityEngine.addFunctionKind(kind::BITVECTOR_SLE);
// d_equalityEngine.addFunctionKind(kind::BITVECTOR_SGT);
// d_equalityEngine.addFunctionKind(kind::BITVECTOR_SGE);
+ d_equalityEngine.addFunctionKind(kind::BITVECTOR_TO_NAT);
+ d_equalityEngine.addFunctionKind(kind::INT_TO_BITVECTOR);
}
CoreSolver::~CoreSolver() {
d_solver.conflict(t1, t2);
}
+void CoreSolver::NotifyClass::eqNotifyNewClass(TNode t) {
+ d_solver.eqNotifyNewClass( t );
+}
+
bool CoreSolver::storePropagation(TNode literal) {
return d_bv->storePropagation(literal, SUB_CORE);
}
d_bv->setConflict(conflict);
}
+void CoreSolver::eqNotifyNewClass(TNode t) {
+ Assert( d_bv->getExtTheory()!=NULL );
+ d_bv->getExtTheory()->registerTerm( t );
+}
+
bool CoreSolver::isCompleteForTerm(TNode term, TNodeBoolMap& seen) {
if (d_useSlicer)
return utils::isCoreTerm(term, seen);
bool eqNotifyTriggerPredicate(TNode predicate, bool value);
bool eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value);
void eqNotifyConstantTermMerge(TNode t1, TNode t2);
- void eqNotifyNewClass(TNode t) { }
+ void eqNotifyNewClass(TNode t);
void eqNotifyPreMerge(TNode t1, TNode t2) { }
void eqNotifyPostMerge(TNode t1, TNode t2) { }
void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) { }
/** Store a conflict from merging two constants */
void conflict(TNode a, TNode b);
+ /** new equivalence class */
+ void eqNotifyNewClass(TNode t);
+
Slicer* d_slicer;
context::CDO<bool> d_isComplete;
unsigned d_lemmaThreshold;
Debug("bv-subtheory-inequality") << " "<< fact <<"\n";
if (fact.getKind() == kind::EQUAL) {
TNode a = fact[0];
- TNode b = fact[1];
- ok = addInequality(a, b, false, fact);
- if (ok)
- ok = addInequality(b, a, false, fact);
+ if( a.getType().isBitVector() ){
+ TNode b = fact[1];
+ ok = addInequality(a, b, false, fact);
+ if (ok)
+ ok = addInequality(b, a, false, fact);
+ }
} else if (fact.getKind() == kind::NOT && fact[0].getKind() == kind::EQUAL) {
TNode a = fact[0][0];
- TNode b = fact[0][1];
- ok = d_inequalityGraph.addDisequality(a, b, fact);
+ if( a.getType().isBitVector() ){
+ TNode b = fact[0][1];
+ ok = d_inequalityGraph.addDisequality(a, b, fact);
+ }
}
if (fact.getKind() == kind::NOT && fact[0].getKind() == kind::BITVECTOR_ULE) {
TNode a = fact[0][1];
}
void EagerBitblaster::bbTerm(TNode node, Bits& bits) {
+ Assert( node.getType().isBitVector() );
+
if (hasBBTerm(node)) {
getBBTerm(node, bits);
return;
typerule BITVECTOR_SIGN_EXTEND ::CVC4::theory::bv::BitVectorExtendTypeRule
typerule BITVECTOR_TO_NAT ::CVC4::theory::bv::BitVectorConversionTypeRule
+typerule INT_TO_BITVECTOR_OP ::CVC4::theory::bv::IntToBitVectorOpTypeRule
typerule INT_TO_BITVECTOR ::CVC4::theory::bv::BitVectorConversionTypeRule
endtheory
if (hasBBAtom(node)) {
return;
}
-
+
// make sure it is marked as an atom
addAtom(node);
Debug("bitvector-bitblast") << "Bitblasting node " << node <<"\n";
++d_statistics.d_numAtoms;
+
/// if we are using bit-vector abstraction bit-blast the original interpretation
if (options::bvAbstraction() &&
uint64_t TLazyBitblaster::computeAtomWeight(TNode node, NodeSet& seen) {
node = node.getKind() == kind::NOT? node[0] : node;
-
+ if( !utils::isBitblastAtom( node ) ){
+ return 0;
+ }
Node atom_bb = Rewriter::rewrite(d_atomBBStrategies[node.getKind()](node, this));
uint64_t size = utils::numNodes(atom_bb, seen);
return size;
getBBTerm(node, bits);
return;
}
+ Assert( node.getType().isBitVector() );
d_bv->spendResource(options::bitblastStep());
- Debug("bitvector-bitblast") << "Bitblasting node " << node <<"\n";
+ Debug("bitvector-bitblast") << "Bitblasting term " << node <<"\n";
++d_statistics.d_numTerms;
d_termBBStrategies[node.getKind()] (node, bits,this);
} else {
atom = lit;
}
+ Assert( utils::isBitblastAtom( atom ) );
Assert (hasBBAtom(atom));
d_isCoreTheory(false),
d_calledPreregister(false)
{
+ d_extt = new ExtTheory( this );
+ d_extt->addFunctionKind( kind::BITVECTOR_TO_NAT );
+ d_extt->addFunctionKind( kind::INT_TO_BITVECTOR );
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
d_eagerSolver = new EagerBitblastSolver(this);
delete d_subtheories[i];
}
delete d_abstractionModule;
+ delete d_extt;
}
void TheoryBV::setMasterEqualityEngine(eq::EqualityEngine* eq) {
for (unsigned i = 0; i < d_subtheories.size(); ++i) {
d_subtheories[i]->preRegister(node);
}
+
+ // AJR : equality solver currently registers all terms, if we want a lazy reduction without the bv equality solver, need to call this
+ //getExtTheory()->registerTermRec( node );
}
void TheoryBV::sendConflict() {
}
if (complete) {
// if the last subtheory was complete we stop
+ break;
+ }
+ }
+
+ //check extended functions
+ if (Theory::fullEffort(e)) {
+ //do inferences (adds external lemmas) TODO: this can be improved to add internal inferences
+ std::vector< Node > nred;
+ if( getExtTheory()->doInferences( 0, nred ) ){
+ return;
+ }
+ std::vector< Node > nredr;
+ if( getExtTheory()->doReductions( 0, nred, nredr ) ){
return;
}
+ Assert( nredr.empty() );
}
}
}
}
+
eq::EqualityEngine * TheoryBV::getEqualityEngine() {
return NULL;
}
bool TheoryBV::getCurrentSubstitution( int effort, std::vector< Node >& vars, std::vector< Node >& subs, std::map< Node, std::vector< Node > >& exp ) {
-#if 0
CoreSolver* core = (CoreSolver*)d_subtheoryMap[SUB_CORE];
if( core ){
//get the constant equivalence classes
for( unsigned i=0; i<vars.size(); i++ ){
Node n = vars[i];
if( core->getEqualityEngine()->hasTerm( n ) ){
- Node nr = core->getEqualityEngine()->getRepresenative( n );
+ Node nr = core->getEqualityEngine()->getRepresentative( n );
if( nr.isConst() ){
subs.push_back( nr );
exp[n].push_back( n.eqNode( nr ) );
}else{
subs.push_back( n );
}
+ }else{
+ subs.push_back( n );
}
}
//return true if the substitution is non-trivial
return retVal;
}
-#endif
return false;
}
+
+int TheoryBV::getReduction( int effort, Node n, Node& nr ) {
+ Trace("bv-ext") << "TheoryBV::checkExt : non-reduced : " << n << std::endl;
+ if( n.getKind()==kind::BITVECTOR_TO_NAT ){
+ //taken from rewrite code
+ const unsigned size = utils::getSize(n[0]);
+ NodeManager* const nm = NodeManager::currentNM();
+ const Node z = nm->mkConst(Rational(0));
+ const Node bvone = nm->mkConst(BitVector(1u, 1u));
+ NodeBuilder<> result(kind::PLUS);
+ Integer i = 1;
+ for(unsigned bit = 0; bit < size; ++bit, i *= 2) {
+ Node cond = nm->mkNode(kind::EQUAL, nm->mkNode(nm->mkConst(BitVectorExtract(bit, bit)), n[0]), bvone);
+ result << nm->mkNode(kind::ITE, cond, nm->mkConst(Rational(i)), z);
+ }
+ nr = Node(result);
+ return -1;
+ }else if( n.getKind()==kind::INT_TO_BITVECTOR ){
+ //taken from rewrite code
+ const unsigned size = n.getOperator().getConst<IntToBitVector>().size;
+ NodeManager* const nm = NodeManager::currentNM();
+ const Node bvzero = nm->mkConst(BitVector(1u, 0u));
+ const Node bvone = nm->mkConst(BitVector(1u, 1u));
+ std::vector<Node> v;
+ Integer i = 2;
+ while(v.size() < size) {
+ Node cond = nm->mkNode(kind::GEQ, nm->mkNode(kind::INTS_MODULUS_TOTAL, n[0], nm->mkConst(Rational(i))), nm->mkConst(Rational(i, 2)));
+ cond = Rewriter::rewrite( cond );
+ v.push_back(nm->mkNode(kind::ITE, cond, bvone, bvzero));
+ i *= 2;
+ }
+ NodeBuilder<> result(kind::BITVECTOR_CONCAT);
+ result.append(v.rbegin(), v.rend());
+ nr = Node(result);
+ return -1;
+ }
+ return 0;
+}
Theory::PPAssertStatus TheoryBV::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
switch(in.getKind()) {
/** equality engine */
eq::EqualityEngine * getEqualityEngine();
bool getCurrentSubstitution( int effort, std::vector< Node >& vars, std::vector< Node >& subs, std::map< Node, std::vector< Node > >& exp );
+ int getReduction( int effort, Node n, Node& nr );
PPAssertStatus ppAssert(TNode in, SubstitutionMap& outSubstitutions);
Node RewriteRule<BVToNatEliminate>::apply(TNode node) {
Debug("bv-rewrite") << "RewriteRule<BVToNatEliminate>(" << node << ")" << std::endl;
+ //if( node[0].isConst() ){
+ //TODO? direct computation instead of term construction+rewriting
+ //}
+
const unsigned size = utils::getSize(node[0]);
NodeManager* const nm = NodeManager::currentNM();
const Node z = nm->mkConst(Rational(0));
Node RewriteRule<IntToBVEliminate>::apply(TNode node) {
Debug("bv-rewrite") << "RewriteRule<IntToBVEliminate>(" << node << ")" << std::endl;
+ //if( node[0].isConst() ){
+ //TODO? direct computation instead of term construction+rewriting
+ //}
+
const unsigned size = node.getOperator().getConst<IntToBitVector>().size;
NodeManager* const nm = NodeManager::currentNM();
const Node bvzero = nm->mkConst(BitVector(1u, 0u));
}
RewriteResponse TheoryBVRewriter::RewriteBVToNat(TNode node, bool prerewrite) {
- Node resultNode = LinearRewriteStrategy
- < RewriteRule<BVToNatEliminate>
- >::apply(node);
-
- return RewriteResponse(REWRITE_AGAIN_FULL, resultNode);
+ //do not use lazy rewrite strategy if equality solver is disabled
+ if( node[0].isConst() || !options::bitvectorEqualitySolver() ){
+ Node resultNode = LinearRewriteStrategy
+ < RewriteRule<BVToNatEliminate>
+ >::apply(node);
+ return RewriteResponse(REWRITE_AGAIN_FULL, resultNode);
+ }else{
+ return RewriteResponse(REWRITE_DONE, node);
+ }
}
RewriteResponse TheoryBVRewriter::RewriteIntToBV(TNode node, bool prerewrite) {
- Node resultNode = LinearRewriteStrategy
- < RewriteRule<IntToBVEliminate>
- >::apply(node);
+ //do not use lazy rewrite strategy if equality solver is disabled
+ if( node[0].isConst() || !options::bitvectorEqualitySolver() ){
+ Node resultNode = LinearRewriteStrategy
+ < RewriteRule<IntToBVEliminate>
+ >::apply(node);
- return RewriteResponse(REWRITE_AGAIN_FULL, resultNode);
+ return RewriteResponse(REWRITE_AGAIN_FULL, resultNode);
+ }else{
+ return RewriteResponse(REWRITE_DONE, node);
+ }
}
RewriteResponse TheoryBVRewriter::RewriteEqual(TNode node, bool prerewrite) {
}
}; /* class BitVectorConversionTypeRule */
+class IntToBitVectorOpTypeRule {
+public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
+
+ if(n.getKind() == kind::INT_TO_BITVECTOR_OP) {
+ size_t bvSize = n.getConst<IntToBitVector>();
+ return nodeManager->mkFunctionType( nodeManager->integerType(), nodeManager->mkBitVectorType(bvSize) );
+ }
+
+ InternalError("bv-conversion typerule invoked for non-bv-conversion kind");
+ }
+}; /* class IntToBitVectorOpTypeRule */
+
class CardinalityComputer {
public:
inline static Cardinality computeCardinality(TypeNode type) {
void collectVariables(TNode node, NodeSet& vars);
+// is bitblast atom
+inline bool isBitblastAtom( Node lit ) {
+ TNode atom = lit.getKind()==kind::NOT ? lit[0] : lit;
+ return atom.getKind()!=kind::EQUAL || atom[0].getType().isBitVector();
+}
+
}
}
}
if( options::stringExp() ){
//collect extended functions here: some may not be asserted to strings (such as those with return type Int),
// but we need to record them so they are treated properly
- std::map< Node, bool > visited;
- collectExtendedFuncTerms( n, visited );
+ d_extt->registerTermRec( n );
}
}
//concat terms do not contribute to theory combination? TODO: verify
}
Trace("strings-pending-debug") << " Now collect terms" << std::endl;
//collect extended function terms in the atom
- std::map< Node, bool > visited;
- collectExtendedFuncTerms( atom, visited );
+ d_extt->registerTermRec( atom );
Trace("strings-pending-debug") << " Finished collect terms" << std::endl;
}
return ret;
}
-void TheoryStrings::collectExtendedFuncTerms( Node n, std::map< Node, bool >& visited ) {
- if( visited.find( n )==visited.end() ){
- visited[n] = true;
- d_extt->registerTerm( n );
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- collectExtendedFuncTerms( n[i], visited );
- }
- }
-}
-
}/* CVC4::theory::strings namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
bool d_model_active;
};
std::map< Node, ExtfInfoTmp > d_extf_info_tmp;
- //collect extended operator terms
- void collectExtendedFuncTerms( Node n, std::map< Node, bool >& visited );
private:
class InferInfo {
public:
}
}
+void ExtTheory::registerTermRec( Node n ) {
+ std::map< Node, bool > visited;
+ registerTermRec( n, visited );
+}
+
+void ExtTheory::registerTermRec( Node n, std::map< Node, bool >& visited ) {
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ registerTerm( n );
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ registerTermRec( n[i], visited );
+ }
+ }
+}
+
//mark reduced
void ExtTheory::markReduced( Node n, bool contextDepend ) {
d_ext_func_terms[n] = false;
bool doInferencesInternal( int effort, std::vector< Node >& terms, std::vector< Node >& nred, bool batch, bool isRed );
//send lemma
bool sendLemma( Node lem, bool preprocess = false );
+ //register term (recursive)
+ void registerTermRec( Node n, std::map< Node, bool >& visited );
public:
ExtTheory( Theory * p );
virtual ~ExtTheory(){}
//register term
// adds n to d_ext_func_terms if addFunctionKind( n.getKind() ) was called
void registerTerm( Node n );
+ void registerTermRec( Node n );
// set n as reduced/inactive
// if contextDepend = false, then n remains inactive in the duration of this user-context level
void markReduced( Node n, bool contextDepend = true );
--- /dev/null
+(set-logic QF_BVLIA)
+(set-info :status unsat)
+(declare-const a (_ BitVec 32))
+(declare-const b (_ BitVec 32))
+(declare-const c (_ BitVec 32))
+(declare-const d (_ BitVec 32))
+(declare-const e (_ BitVec 32))
+
+(assert (or (= a #x00000007) (= a #x00000005) (= a #x00000100)))
+
+(assert (not (= (bv2nat a) 7)))
+(assert (not (= (bv2nat a) 5)))
+(assert (< (bv2nat a) 10))
+
+(check-sat)
--- /dev/null
+(set-logic QF_BVLIA)
+(set-info :status unsat)
+(declare-const a (_ BitVec 32))
+(declare-const b (_ BitVec 32))
+(declare-const c (_ BitVec 32))
+(declare-const d (_ BitVec 32))
+(declare-const e (_ BitVec 32))
+
+(assert (or (= a b) (= a c) (= a d) (= a e)))
+
+(assert (not (= (bv2nat a) (bv2nat b))))
+(assert (not (= (bv2nat a) (bv2nat c))))
+(assert (not (= (bv2nat a) (bv2nat d))))
+(assert (not (= (bv2nat a) (bv2nat e))))
+
+(check-sat)
--- /dev/null
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-fun y () Int)
+(declare-fun x () Int)
+
+(assert (and (and (and (and (and (and (and (and (and (and (and (and (and (and (and (and (and (and (not (not (not (= (ite (= (bv2nat (bvand ((_ int2bv 3) (bv2nat (bvor ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1)))) ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1))))))) ((_ int2bv 3) 1))) 0) 1 0) 0)))) (not (= (ite (>= x 0) 1 0) 0))) (not (= (ite (>= y 0) 1 0) 0))) (not (= (ite (= x y) 1 0) 0))) (not (not (= (ite (= x 0) 1 0) 0)))) (not (not (= (ite (= y 0) 1 0) 0)))) (not (= (ite (= (bv2nat (bvand ((_ int2bv 3) (bv2nat (bvor ((_ int2bv 3) x) ((_ int2bv 3) x)))) ((_ int2bv 3) 1))) 0) 1 0) 0))) (and (= x (bv2nat ((_ int2bv 3) x))) (= 1 (bv2nat ((_ int2bv 3) 1))))) (= ((_ extract 0 0) (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1))) (_ bv0 1))) (and (= y (bv2nat ((_ int2bv 3) y))) (= 1 (bv2nat ((_ int2bv 3) 1))))) (= ((_ extract 0 0) (bvashr ((_ int2bv 3) y) ((_ int2bv 3) 1))) (_ bv0 1))) (and (= (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1))) (bv2nat ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1)))))) (= (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1))) (bv2nat ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1)))))))) (= ((_ extract 0 0) (bvor ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1)))) ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1)))))) (_ bv0 1))) (and (= (bv2nat (bvor ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1)))) ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1)))))) (bv2nat ((_ int2bv 3) (bv2nat (bvor ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1)))) ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1))))))))) (= 1 (bv2nat ((_ int2bv 3) 1))))) (= ((_ extract 0 0) (bvand ((_ int2bv 3) (bv2nat (bvor ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1)))) ((_ int2bv 3) (bv2nat (bvashr ((_ int2bv 3) x) ((_ int2bv 3) 1))))))) ((_ int2bv 3) 1))) (_ bv0 1))) (and (= x (bv2nat ((_ int2bv 3) x))) (= x (bv2nat ((_ int2bv 3) x))))) (= ((_ extract 0 0) (bvor ((_ int2bv 3) x) ((_ int2bv 3) x))) (_ bv0 1))) (and (= (bv2nat (bvor ((_ int2bv 3) x) ((_ int2bv 3) x))) (bv2nat ((_ int2bv 3) (bv2nat (bvor ((_ int2bv 3) x) ((_ int2bv 3) x)))))) (= 1 (bv2nat ((_ int2bv 3) 1))))) (= ((_ extract 0 0) (bvand ((_ int2bv 3) (bv2nat (bvor ((_ int2bv 3) x) ((_ int2bv 3) x)))) ((_ int2bv 3) 1))) (_ bv0 1))))
+
+(check-sat)