summaryrefslogtreecommitdiff
path: root/src/theory/bv/theory_bv.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/theory/bv/theory_bv.cpp')
-rw-r--r--src/theory/bv/theory_bv.cpp308
1 files changed, 158 insertions, 150 deletions
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index b6f12793d..c9d58574e 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -40,15 +40,17 @@ TheoryBV::TheoryBV(context::Context* c, context::UserContext* u, OutputChannel&
: Theory(THEORY_BV, c, u, out, valuation, logicInfo),
d_context(c),
d_assertions(c),
- d_bitblaster(new Bitblaster(c) ),
+ d_bitblaster(new Bitblaster(c, this) ),
d_alreadyPropagatedSet(c),
d_statistics(),
+ d_sharedTermsSet(c),
d_notify(*this),
d_equalityEngine(d_notify, c, "theory::bv::TheoryBV"),
d_conflict(c, false),
d_literalsToPropagate(c),
d_literalsToPropagateIndex(c, 0),
- d_toBitBlast(c)
+ d_toBitBlast(c),
+ d_propagatedBy(c)
{
d_true = utils::mkTrue();
d_false = utils::mkFalse();
@@ -58,6 +60,11 @@ TheoryBV::TheoryBV(context::Context* c, context::UserContext* u, OutputChannel&
d_equalityEngine.addTerm(d_false);
d_equalityEngine.addTriggerEquality(d_true, d_false, d_false);
+ // add disequality between 0 and 1 bits
+ d_equalityEngine.addDisequality(utils::mkConst(BitVector((unsigned)1, (unsigned)0)),
+ utils::mkConst(BitVector((unsigned)1, (unsigned)1)),
+ d_true);
+
// The kinds we are treating as function application in congruence
d_equalityEngine.addFunctionKind(kind::BITVECTOR_CONCAT);
// d_equalityEngine.addFunctionKind(kind::BITVECTOR_AND);
@@ -113,12 +120,18 @@ TheoryBV::Statistics::~Statistics() {
void TheoryBV::preRegisterTerm(TNode node) {
BVDebug("bitvector-preregister") << "TheoryBV::preRegister(" << node << ")" << std::endl;
+
+ if (Options::current()->bitvector_eager_bitblast) {
+ // don't use the equality engine in the eager bit-blasting
+ return;
+ }
+
if (node.getKind() == kind::EQUAL ||
node.getKind() == kind::BITVECTOR_ULT ||
node.getKind() == kind::BITVECTOR_ULE ||
node.getKind() == kind::BITVECTOR_SLT ||
node.getKind() == kind::BITVECTOR_SLE) {
- d_bitblaster->bitblast(node);
+ d_bitblaster->bbAtom(node);
}
if (d_useEqualityEngine) {
@@ -140,56 +153,56 @@ void TheoryBV::preRegisterTerm(TNode node) {
void TheoryBV::check(Effort e)
{
- BVDebug("bitvector") << "TheoryBV::check " << e << "\n";
- BVDebug("bitvector")<< "TheoryBV::check(" << e << ")" << std::endl;
+ BVDebug("bitvector") << "TheoryBV::check(" << e << ")" << std::endl;
+
+ if (Options::current()->bitvector_eager_bitblast) {
+ while (!done()) {
+ Assertion assertion = get();
+ TNode fact = assertion.assertion;
+ if (fact.getKind() == kind::NOT) {
+ if (fact[0].getKind() != kind::BITVECTOR_BITOF) {
+ d_bitblaster->bbAtom(fact[0]);
+ }
+ } else {
+ if (fact.getKind() != kind::BITVECTOR_BITOF) {
+ d_bitblaster->bbAtom(fact);
+ }
+ }
+ }
+ return;
+ }
+
while (!done() && !d_conflict) {
Assertion assertion = get();
TNode fact = assertion.assertion;
BVDebug("bitvector-assertions") << "TheoryBV::check assertion " << fact << "\n";
- // If the assertion doesn't have a literal, it's a shared equality
- bool shared = !assertion.isPreregistered;
- Assert(!d_useEqualityEngine || !shared ||
- ((fact.getKind() == kind::EQUAL && d_equalityEngine.hasTerm(fact[0]) && d_equalityEngine.hasTerm(fact[1])) ||
- (fact.getKind() == kind::NOT && fact[0].getKind() == kind::EQUAL &&
- d_equalityEngine.hasTerm(fact[0][0]) && d_equalityEngine.hasTerm(fact[0][1]))));
-
- // Notify the Equality Engine
- switch (fact.getKind()) {
- case kind::EQUAL:
- if (d_useEqualityEngine) {
- d_equalityEngine.addEquality(fact[0], fact[1], fact);
- }
- if (shared && !d_bitblaster->hasBBAtom(fact)) {
- d_bitblaster->bitblast(fact);
- }
- break;
- case kind::NOT:
- if (fact[0].getKind() == kind::EQUAL) {
- // Assert the dis-equality
- if (d_useEqualityEngine) {
- d_equalityEngine.addDisequality(fact[0][0], fact[0][1], fact);
- }
- if (shared && !d_bitblaster->hasBBAtom(fact[0])) {
- d_bitblaster->bitblast(fact[0]);
- }
+ // Notify the equality engine
+ if (d_useEqualityEngine && !d_conflict && !propagatedBy(fact, SUB_EQUALITY) ) {
+ bool negated = fact.getKind() == kind::NOT;
+ TNode predicate = negated ? fact[0] : fact;
+ if (predicate.getKind() == kind::EQUAL) {
+ if (negated) {
+ // dis-equality
+ d_equalityEngine.addDisequality(predicate[0], predicate[1], fact);
} else {
- if (d_useEqualityEngine) {
- d_equalityEngine.addPredicate(fact[0], false, fact);
- }
- break;
+ // equality
+ d_equalityEngine.addEquality(predicate[0], predicate[1], fact);
}
- break;
- default:
- if (d_useEqualityEngine) {
- d_equalityEngine.addPredicate(fact, true, fact);
+ } else {
+ // Adding predicate if the congruence over it is turned on
+ if (d_equalityEngine.isFunctionKind(predicate.getKind())) {
+ d_equalityEngine.addPredicate(predicate, !negated, fact);
}
- break;
+ }
}
- // make sure we do not assert things we propagated
- if (!d_conflict && d_alreadyPropagatedSet.count(fact) == 0) {
+ // Bit-blaster
+ if (!d_conflict && !propagatedBy(fact, SUB_BITBLASTER)) {
+ // Some atoms have not been bit-blasted yet
+ d_bitblaster->bbAtom(fact);
+ // Assert to sat
bool ok = d_bitblaster->assertToSat(fact, d_useSatPropagation);
if (!ok) {
std::vector<TNode> conflictAtoms;
@@ -204,17 +217,15 @@ void TheoryBV::check(Effort e)
// If in conflict, output the conflict
if (d_conflict) {
- Debug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::check(): conflict " << d_conflictNode << std::endl;
+ BVDebug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::check(): conflict " << d_conflictNode;
d_out->conflict(d_conflictNode);
return;
}
- if (e == EFFORT_FULL) {
-
+ if (e == EFFORT_FULL || Options::current()->bitvector_eager_fullcheck) {
Assert(done() && !d_conflict);
BVDebug("bitvector") << "TheoryBV::check " << e << "\n";
- // in standard effort we only do boolean constraint propagation
- bool ok = d_bitblaster->solve(false);
+ bool ok = d_bitblaster->solve();
if (!ok) {
std::vector<TNode> conflictAtoms;
d_bitblaster->getConflict(conflictAtoms);
@@ -225,7 +236,6 @@ void TheoryBV::check(Effort e)
return;
}
}
-
}
@@ -253,77 +263,55 @@ void TheoryBV::propagate(Effort e) {
return;
}
- // get new propagations from the equality engine
- for (; d_literalsToPropagateIndex < d_literalsToPropagate.size(); d_literalsToPropagateIndex = d_literalsToPropagateIndex + 1) {
+ // go through stored propagations
+ for (; d_literalsToPropagateIndex < d_literalsToPropagate.size();
+ d_literalsToPropagateIndex = d_literalsToPropagateIndex + 1)
+ {
TNode literal = d_literalsToPropagate[d_literalsToPropagateIndex];
- BVDebug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::propagate(): propagating from equality engine: " << literal << std::endl;
- bool satValue;
Node normalized = Rewriter::rewrite(literal);
- if (!d_valuation.hasSatValue(normalized, satValue) || satValue) {
- d_out->propagate(literal);
- } else {
- Debug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::propagate(): in conflict, normalized = " << normalized << std::endl;
- Node negatedLiteral;
- std::vector<TNode> assumptions;
- if (normalized != d_false) {
- negatedLiteral = normalized.getKind() == kind::NOT ? (Node) normalized[0] : normalized.notNode();
- assumptions.push_back(negatedLiteral);
- }
- explain(literal, assumptions);
- d_conflictNode = mkAnd(assumptions);
- d_conflict = true;
- return;
- }
- }
- // get new propagations from the sat solver
- std::vector<TNode> propagations;
- d_bitblaster->getPropagations(propagations);
-
- // propagate the facts on the propagation queue
- for (unsigned i = 0; i < propagations.size(); ++ i) {
- TNode node = propagations[i];
- BVDebug("bitvector") << "TheoryBV::propagate " << node <<" \n";
- if (!d_valuation.isSatLiteral(node)) {
- // TODO: maybe propagate shared terms too?
- continue;
- }
- if (d_valuation.getSatValue(node) == Node::null()) {
- vector<Node> explanation;
- d_bitblaster->explainPropagation(node, explanation);
- if (explanation.size() == 0) {
- d_out->lemma(node);
+ TNode atom = literal.getKind() == kind::NOT ? literal[0] : literal;
+ // check if it's a shared equality in the current context
+ if (atom.getKind() != kind::EQUAL || d_valuation.isSatLiteral(normalized) ||
+ (d_sharedTermsSet.find(atom[0]) != d_sharedTermsSet.end() &&
+ d_sharedTermsSet.find(atom[1]) != d_sharedTermsSet.end())) {
+
+ bool satValue;
+ if (!d_valuation.hasSatValue(normalized, satValue) || satValue) {
+ // check if we already propagated the negation
+ Node neg_literal = literal.getKind() == kind::NOT ? (Node)literal[0] : mkNot(literal);
+ if (d_alreadyPropagatedSet.find(neg_literal) != d_alreadyPropagatedSet.end()) {
+ Debug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::propagate(): in conflict " << literal << " and its negation both propagated \n";
+ // we are in conflict
+ std::vector<TNode> assumptions;
+ explain(literal, assumptions);
+ explain(neg_literal, assumptions);
+ d_conflictNode = mkAnd(assumptions);
+ d_conflict = true;
+ return;
+ }
+
+ BVDebug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::propagate(): " << literal << std::endl;
+ d_out->propagate(literal);
+ d_alreadyPropagatedSet.insert(literal);
} else {
- NodeBuilder<> nb(kind::OR);
- nb << node;
- for (unsigned i = 0; i < explanation.size(); ++ i) {
- nb << explanation[i].notNode();
+ Debug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::propagate(): in conflict, normalized = " << normalized << std::endl;
+
+ Node negatedLiteral;
+ std::vector<TNode> assumptions;
+ if (normalized != d_false) {
+ negatedLiteral = normalized.getKind() == kind::NOT ? (Node) normalized[0] : normalized.notNode();
+ assumptions.push_back(negatedLiteral);
}
- Node lemma = nb;
- d_out->lemma(lemma);
+ explain(literal, assumptions);
+ d_conflictNode = mkAnd(assumptions);
+ d_conflict = true;
+ return;
}
- d_alreadyPropagatedSet.insert(node);
}
}
-
}
-// Node TheoryBV::explain(TNode n) {
-// BVDebug("bitvector") << "TheoryBV::explain node " << n <<"\n";
-// std::vector<Node> explanation;
-// d_bitblaster->explainPropagation(n, explanation);
-// Node exp;
-
-// if (explanation.size() == 0) {
-// return utils::mkTrue();
-// }
-
-// exp = utils::mkAnd(explanation);
-
-// BVDebug("bitvector") << "TheoryBV::explain with " << exp <<"\n";
-// return exp;
-// }
-
Theory::PPAssertStatus TheoryBV::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
switch(in.getKind()) {
case kind::EQUAL:
@@ -351,42 +339,44 @@ Theory::PPAssertStatus TheoryBV::ppAssert(TNode in, SubstitutionMap& outSubstitu
}
-bool TheoryBV::propagate(TNode literal)
+bool TheoryBV::storePropagation(TNode literal, SubTheory subtheory)
{
- Debug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::propagate(" << literal << ")" << std::endl;
+ Debug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::storePropagation(" << literal << ")" << std::endl;
// If already in conflict, no more propagation
if (d_conflict) {
- Debug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::propagate(" << literal << "): already in conflict" << std::endl;
+ Debug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::storePropagation(" << literal << "): already in conflict" << std::endl;
return false;
}
+ // If propagated already, just skip
+ PropagatedMap::const_iterator find = d_propagatedBy.find(literal);
+ if (find != d_propagatedBy.end()) {
+ //unsigned theories = (*find).second | (unsigned) subtheory;
+ //d_propagatedBy[literal] = theories;
+ return true;
+ } else {
+ d_propagatedBy[literal] = subtheory;
+ }
+
// See if the literal has been asserted already
- Node normalized = Rewriter::rewrite(literal);
bool satValue = false;
- bool isAsserted = normalized == d_false || d_valuation.hasSatValue(normalized, satValue);
-
+ bool hasSatValue = d_valuation.hasSatValue(literal, satValue);
// If asserted, we might be in conflict
- if (isAsserted) {
- if (!satValue) {
- Debug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::propagate(" << literal << ", normalized = " << normalized << ") => conflict" << std::endl;
+
+ if (hasSatValue && !satValue) {
+ Debug("bitvector-prop") << spaces(getSatContext()->getLevel()) << "TheoryBV::storePropagation(" << literal << ") => conflict" << std::endl;
std::vector<TNode> assumptions;
- Node negatedLiteral;
- if (normalized != d_false) {
- negatedLiteral = normalized.getKind() == kind::NOT ? (Node) normalized[0] : normalized.notNode();
- assumptions.push_back(negatedLiteral);
- }
+ Node negatedLiteral = literal.getKind() == kind::NOT ? (Node) literal[0] : literal.notNode();
+ assumptions.push_back(negatedLiteral);
explain(literal, assumptions);
d_conflictNode = mkAnd(assumptions);
d_conflict = true;
return false;
- }
- // Propagate even if already known in SAT - could be a new equation between shared terms
- // (terms that weren't shared when the literal was asserted!)
}
// Nothing, just enqueue it for propagation and mark it as asserted already
- Debug("bitvector") << spaces(getSatContext()->getLevel()) << "TheoryBV::propagate(" << literal << ") => enqueuing for propagation" << std::endl;
+ Debug("bitvector-prop") << spaces(getSatContext()->getLevel()) << "TheoryBV::storePropagation(" << literal << ") => enqueuing for propagation" << std::endl;
d_literalsToPropagate.push_back(literal);
return true;
@@ -394,46 +384,60 @@ bool TheoryBV::propagate(TNode literal)
void TheoryBV::explain(TNode literal, std::vector<TNode>& assumptions) {
- TNode lhs, rhs;
- switch (literal.getKind()) {
- case kind::EQUAL:
- lhs = literal[0];
- rhs = literal[1];
- break;
- case kind::NOT:
- if (literal[0].getKind() == kind::EQUAL) {
- // Disequalities
- d_equalityEngine.explainDisequality(literal[0][0], literal[0][1], assumptions);
- return;
- } else {
- // Predicates
+
+ if (propagatedBy(literal, SUB_EQUALITY)) {
+ TNode lhs, rhs;
+ switch (literal.getKind()) {
+ case kind::EQUAL:
lhs = literal[0];
+ rhs = literal[1];
+ break;
+ case kind::NOT:
+ if (literal[0].getKind() == kind::EQUAL) {
+ // Disequalities
+ d_equalityEngine.explainDisequality(literal[0][0], literal[0][1], assumptions);
+ return;
+ } else {
+ // Predicates
+ lhs = literal[0];
+ rhs = d_false;
+ break;
+ }
+ case kind::CONST_BOOLEAN:
+ // we get to explain true = false, since we set false to be the trigger of this
+ lhs = d_true;
rhs = d_false;
break;
- }
- case kind::CONST_BOOLEAN:
- // we get to explain true = false, since we set false to be the trigger of this
- lhs = d_true;
- rhs = d_false;
- break;
- default:
- Unreachable();
+ default:
+ Unreachable();
+ }
+ d_equalityEngine.explainEquality(lhs, rhs, assumptions);
+ } else {
+ Assert(propagatedBy(literal, SUB_BITBLASTER));
+ d_bitblaster->explain(literal, assumptions);
}
- d_equalityEngine.explainEquality(lhs, rhs, assumptions);
}
Node TheoryBV::explain(TNode node) {
BVDebug("bitvector") << "TheoryBV::explain(" << node << ")" << std::endl;
std::vector<TNode> assumptions;
+
+ // Ask for the explanation
explain(node, assumptions);
+ // this means that it is something true at level 0
+ if (assumptions.size() == 0) {
+ return utils::mkTrue();
+ }
+ // return the explanation
return mkAnd(assumptions);
}
void TheoryBV::addSharedTerm(TNode t) {
Debug("bitvector::sharing") << spaces(getSatContext()->getLevel()) << "TheoryBV::addSharedTerm(" << t << ")" << std::endl;
- if (d_useEqualityEngine) {
+ d_sharedTermsSet.insert(t);
+ if (!Options::current()->bitvector_eager_bitblast && d_useEqualityEngine) {
d_equalityEngine.addTriggerTerm(t);
}
}
@@ -441,6 +445,10 @@ void TheoryBV::addSharedTerm(TNode t) {
EqualityStatus TheoryBV::getEqualityStatus(TNode a, TNode b)
{
+ if (Options::current()->bitvector_eager_bitblast) {
+ return EQUALITY_UNKNOWN;
+ }
+
if (d_useEqualityEngine) {
if (d_equalityEngine.areEqual(a, b)) {
// The terms are implied to be equal
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback