#include "smt/smt_engine.h"
#include "smt/smt_engine_scope.h"
#include "theory/theory_engine.h"
+#include "theory/bv/theory_bv_rewrite_rules.h"
#include "proof/proof_manager.h"
#include "util/proof.h"
#include "util/boolean_simplification.h"
*/
Node d_divByZero;
+ /**
+ * Maps from bit-vector width to divison-by-zero uninterpreted
+ * function symbols.
+ */
+ hash_map<unsigned, Node> d_BVDivByZero;
+ hash_map<unsigned, Node> d_BVRemByZero;
+
+
/**
* Function symbol used to implement uninterpreted
* int-division-by-zero semantics. Needed to deal with partial
void addFormula(TNode n)
throw(TypeCheckingException, LogicException);
+ /**
+ * Return the uinterpreted function symbol corresponding to division-by-zero
+ * for this particular bit-wdith
+ * @param k should be UREM or UDIV
+ * @param width
+ *
+ * @return
+ */
+ Node getBVDivByZero(Kind k, unsigned width);
+ /**
+ * Returns the node modeling the division-by-zero semantics of node n.
+ *
+ * @param n
+ *
+ * @return
+ */
+ Node expandBVDivByZero(TNode n);
/**
* Expand definitions in n.
*/
d_logic.lock();
// may need to force uninterpreted functions to be on for non-linear
- if(d_logic.isTheoryEnabled(theory::THEORY_ARITH) &&
- !d_logic.isLinear() &&
+ if(((d_logic.isTheoryEnabled(theory::THEORY_ARITH) && !d_logic.isLinear()) ||
+ d_logic.isTheoryEnabled(theory::THEORY_BV)) &&
!d_logic.isTheoryEnabled(theory::THEORY_UF)){
d_logic = d_logic.getUnlockedCopy();
d_logic.enableTheory(theory::THEORY_UF);
d_definedFunctions->insert(funcNode, def);
}
+
+Node SmtEnginePrivate::getBVDivByZero(Kind k, unsigned width) {
+ NodeManager* nm = d_smt.d_nodeManager;
+ if (k == kind::BITVECTOR_UDIV) {
+ if (d_BVDivByZero.find(width) == d_BVDivByZero.end()) {
+ // lazily create the function symbols
+ std::ostringstream os;
+ os << "BVUDivByZero_" << width;
+ Node divByZero = nm->mkSkolem(os.str(),
+ nm->mkFunctionType(nm->mkBitVectorType(width), nm->mkBitVectorType(width)),
+ "partial bvudiv", NodeManager::SKOLEM_EXACT_NAME);
+ d_BVDivByZero[width] = divByZero;
+ }
+ return d_BVDivByZero[width];
+ }
+ else if (k == kind::BITVECTOR_UREM) {
+ if (d_BVRemByZero.find(width) == d_BVRemByZero.end()) {
+ std::ostringstream os;
+ os << "BVURemByZero_" << width;
+ Node divByZero = nm->mkSkolem(os.str(),
+ nm->mkFunctionType(nm->mkBitVectorType(width), nm->mkBitVectorType(width)),
+ "partial bvurem", NodeManager::SKOLEM_EXACT_NAME);
+ d_BVRemByZero[width] = divByZero;
+ }
+ return d_BVRemByZero[width];
+ }
+
+ Unreachable();
+}
+
+
+Node SmtEnginePrivate::expandBVDivByZero(TNode n) {
+ // we only deal wioth the unsigned division operators as the signed ones should have been
+ // expanded in terms of the unsigned operators
+ NodeManager* nm = d_smt.d_nodeManager;
+ unsigned width = n.getType().getBitVectorSize();
+ Node divByZero = getBVDivByZero(n.getKind(), width);
+ TNode num = n[0], den = n[1];
+ Node den_eq_0 = nm->mkNode(kind::EQUAL, den, nm->mkConst(BitVector(width, Integer(0))));
+ Node divByZeroNum = nm->mkNode(kind::APPLY_UF, divByZero, num);
+ Node divTotalNumDen = nm->mkNode(n.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_UDIV_TOTAL :
+ kind::BITVECTOR_UREM_TOTAL, num, den);
+ Node node = nm->mkNode(kind::ITE, den_eq_0, divByZeroNum, divTotalNumDen);
+ return node;
+}
+
+
Node SmtEnginePrivate::expandDefinitions(TNode n, hash_map<Node, Node, NodeHashFunction>& cache)
throw(TypeCheckingException, LogicException) {
// otherwise expand it
- Node node;
+ Node node = n;
NodeManager* nm = d_smt.d_nodeManager;
switch(k) {
+ case kind::BITVECTOR_SDIV:
+ case kind::BITVECTOR_SREM:
+ case kind::BITVECTOR_SMOD: {
+ node = bv::LinearRewriteStrategy <
+ bv::RewriteRule<bv::SremEliminate>,
+ bv::RewriteRule<bv::SdivEliminate>,
+ bv::RewriteRule<bv::SmodEliminate>
+ >::apply(node);
+ break;
+ }
+
+ case kind::BITVECTOR_UDIV:
+ case kind::BITVECTOR_UREM: {
+ node = expandBVDivByZero(node);
+ break;
+ }
case kind::DIVISION: {
// partial function: division
if(d_smt.d_logic.isLinear()) {
void DefaultUdivBB (TNode node, Bits& q, Bitblaster* bb) {
BVDebug("bitvector-bb") << "theory::bv::DefaultUdivBB bitblasting " << node << "\n";
- Assert(node.getKind() == kind::BITVECTOR_UDIV && q.size() == 0);
+ Assert(node.getKind() == kind::BITVECTOR_UDIV_TOTAL && q.size() == 0);
Bits a, b;
bb->bbTerm(node[0], a);
uDivModRec(a, b, q, r, getSize(node));
// cache the remainder in case we need it later
- Node remainder = mkNode(kind::BITVECTOR_UREM, node[0], node[1]);
+ Node remainder = mkNode(kind::BITVECTOR_UREM_TOTAL, node[0], node[1]);
bb->cacheTermDef(remainder, r);
}
void DefaultUremBB (TNode node, Bits& rem, Bitblaster* bb) {
BVDebug("bitvector-bb") << "theory::bv::DefaultUremBB bitblasting " << node << "\n";
- Assert(node.getKind() == kind::BITVECTOR_UREM && rem.size() == 0);
+ Assert(node.getKind() == kind::BITVECTOR_UREM_TOTAL && rem.size() == 0);
Bits a, b;
bb->bbTerm(node[0], a);
uDivModRec(a, b, q, rem, getSize(node));
// cache the quotient in case we need it later
- Node quotient = mkNode(kind::BITVECTOR_UDIV, node[0], node[1]);
+ Node quotient = mkNode(kind::BITVECTOR_UDIV_TOTAL, node[0], node[1]);
bb->cacheTermDef(quotient, q);
}
*/
bool Bitblaster::solve(bool quick_solve) {
+ if (Trace.isOn("bitvector")) {
+ Trace("bitvector") << "Bitblaster::solve() asserted atoms ";
+ context::CDList<prop::SatLiteral>::const_iterator it = d_assertedAtoms.begin();
+ for (; it != d_assertedAtoms.end(); ++it) {
+ Trace("bitvector") << " " << d_cnfStream->getNode(*it) << "\n";
+ }
+ }
BVDebug("bitvector") << "Bitblaster::solve() asserted atoms " << d_assertedAtoms.size() <<"\n";
return SAT_VALUE_TRUE == d_satSolver->solve();
}
d_termBBStrategies [ kind::BITVECTOR_PLUS ] = DefaultPlusBB;
d_termBBStrategies [ kind::BITVECTOR_SUB ] = DefaultSubBB;
d_termBBStrategies [ kind::BITVECTOR_NEG ] = DefaultNegBB;
- d_termBBStrategies [ kind::BITVECTOR_UDIV ] = DefaultUdivBB;
- d_termBBStrategies [ kind::BITVECTOR_UREM ] = DefaultUremBB;
- d_termBBStrategies [ kind::BITVECTOR_SDIV ] = DefaultSdivBB;
- d_termBBStrategies [ kind::BITVECTOR_SREM ] = DefaultSremBB;
- d_termBBStrategies [ kind::BITVECTOR_SMOD ] = DefaultSmodBB;
+ d_termBBStrategies [ kind::BITVECTOR_UDIV ] = UndefinedTermBBStrategy;
+ d_termBBStrategies [ kind::BITVECTOR_UREM ] = UndefinedTermBBStrategy;
+ d_termBBStrategies [ kind::BITVECTOR_UDIV_TOTAL ] = DefaultUdivBB;
+ d_termBBStrategies [ kind::BITVECTOR_UREM_TOTAL ] = DefaultUremBB;
+ d_termBBStrategies [ kind::BITVECTOR_SDIV ] = UndefinedTermBBStrategy;
+ d_termBBStrategies [ kind::BITVECTOR_SREM ] = UndefinedTermBBStrategy;
+ d_termBBStrategies [ kind::BITVECTOR_SMOD ] = UndefinedTermBBStrategy;
d_termBBStrategies [ kind::BITVECTOR_SHL ] = DefaultShlBB;
d_termBBStrategies [ kind::BITVECTOR_LSHR ] = DefaultLshrBB;
d_termBBStrategies [ kind::BITVECTOR_ASHR ] = DefaultAshrBB;
TNode var = *it;
if (Theory::theoryOf(var) == theory::THEORY_BV || isSharedTerm(var)) {
Node const_value = getVarValue(var);
+ Debug("bitvector-model") << "Bitblaster::collectModelInfo (assert (= "
+ << var << " "
+ << const_value << "))\n";
m->assertEquality(var, const_value, true);
}
}
EqualitySolver::EqualitySolver(context::Context* c, TheoryBV* bv)
: SubtheorySolver(c, bv),
d_notify(*this),
- d_equalityEngine(d_notify, c, "theory::bv::TheoryBV")
+ d_equalityEngine(d_notify, c, "theory::bv::TheoryBV"),
+ d_assertions(c)
{
if (d_useEqualityEngine) {
}
bool EqualitySolver::addAssertions(const std::vector<TNode>& assertions, Theory::Effort e) {
- BVDebug("bitvector::equality") << "EqualitySolver::addAssertions \n";
+ Trace("bitvector::equality") << "EqualitySolver::addAssertions \n";
Assert (!d_bv->inConflict());
for (unsigned i = 0; i < assertions.size(); ++i) {
TNode fact = assertions[i];
-
+
// Notify the equality engine
if (d_useEqualityEngine && !d_bv->inConflict() && !d_bv->propagatedBy(fact, SUB_EQUALITY) ) {
+ Trace("bitvector::equality") << " (assert " << fact << ")\n";
+ d_assertions.push_back(fact);
bool negated = fact.getKind() == kind::NOT;
TNode predicate = negated ? fact[0] : fact;
if (predicate.getKind() == kind::EQUAL) {
}
void EqualitySolver::collectModelInfo(TheoryModel* m) {
+ if (Debug.isOn("bitvector-model")) {
+ context::CDList<TNode>::const_iterator it = d_assertions.begin();
+ for (; it!= d_assertions.end(); ++it) {
+ Debug("bitvector-model") << "EqualitySolver::collectModelInfo (assert "
+ << *it << ")\n";
+ }
+ }
m->assertEqualityEngine(&d_equalityEngine);
}
/** Store a conflict from merging two constants */
void conflict(TNode a, TNode b);
+ /** FIXME: for debugging purposes only */
+ context::CDList<TNode> d_assertions;
public:
EqualitySolver(context::Context* c, TheoryBV* bv);
operator BITVECTOR_SDIV 2 "bit-vector 2's complement signed division"
operator BITVECTOR_SREM 2 "bit-vector 2's complement signed remainder (sign follows dividend)"
operator BITVECTOR_SMOD 2 "bit-vector 2's complement signed remainder (sign follows divisor)"
+# total division kinds
+operator BITVECTOR_UDIV_TOTAL 2 "bit-vector total unsigned division, truncating towards 0 (undefined if divisor is 0)"
+operator BITVECTOR_UREM_TOTAL 2 "bit-vector total unsigned remainder from truncating division (undefined if divisor is 0)"
+
operator BITVECTOR_SHL 2 "bit-vector left shift"
operator BITVECTOR_LSHR 2 "bit-vector logical shift right"
operator BITVECTOR_ASHR 2 "bit-vector arithmetic shift right"
typerule BITVECTOR_UDIV ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_UREM ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_UDIV_TOTAL ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_UREM_TOTAL ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_SDIV ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_SREM ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_SMOD ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
}
template<> inline
bool RewriteRule<EvalUdiv>::applies(TNode node) {
- return (node.getKind() == kind::BITVECTOR_UDIV &&
+ return (node.getKind() == kind::BITVECTOR_UDIV_TOTAL &&
utils::isBVGroundTerm(node));
}
}
template<> inline
bool RewriteRule<EvalUrem>::applies(TNode node) {
- return (node.getKind() == kind::BITVECTOR_UREM &&
+ return (node.getKind() == kind::BITVECTOR_UREM_TOTAL &&
utils::isBVGroundTerm(node));
}
template<> inline
bool RewriteRule<UdivPow2>::applies(TNode node) {
- return (node.getKind() == kind::BITVECTOR_UDIV &&
+ return (node.getKind() == kind::BITVECTOR_UDIV_TOTAL &&
utils::isPow2Const(node[1]));
}
template<> inline
bool RewriteRule<UdivOne>::applies(TNode node) {
- return (node.getKind() == kind::BITVECTOR_UDIV &&
+ return (node.getKind() == kind::BITVECTOR_UDIV_TOTAL &&
node[1] == utils::mkConst(utils::getSize(node), 1));
}
template<> inline
bool RewriteRule<UdivSelf>::applies(TNode node) {
- return (node.getKind() == kind::BITVECTOR_UDIV &&
+ return (node.getKind() == kind::BITVECTOR_UDIV_TOTAL &&
node[0] == node[1]);
}
template<> inline
bool RewriteRule<UremPow2>::applies(TNode node) {
- return (node.getKind() == kind::BITVECTOR_UREM &&
+ return (node.getKind() == kind::BITVECTOR_UREM_TOTAL &&
utils::isPow2Const(node[1]));
}
template<> inline
bool RewriteRule<UremOne>::applies(TNode node) {
- return (node.getKind() == kind::BITVECTOR_UREM &&
+ return (node.getKind() == kind::BITVECTOR_UREM_TOTAL &&
node[1] == utils::mkConst(utils::getSize(node), 1));
}
template<> inline
bool RewriteRule<UremSelf>::applies(TNode node) {
- return (node.getKind() == kind::BITVECTOR_UREM &&
+ return (node.getKind() == kind::BITVECTOR_UREM_TOTAL &&
node[0] == node[1]);
}
return RewriteResponse(REWRITE_DONE, resultNode);
}
-RewriteResponse TheoryBVRewriter::RewriteUdiv(TNode node, bool preregister){
+
+RewriteResponse TheoryBVRewriter::RewriteUdivTotal(TNode node, bool preregister){
Node resultNode = node;
if(RewriteRule<UdivPow2>::applies(node)) {
return RewriteResponse(REWRITE_DONE, resultNode);
}
-RewriteResponse TheoryBVRewriter::RewriteUrem(TNode node, bool preregister) {
+RewriteResponse TheoryBVRewriter::RewriteUremTotal(TNode node, bool preregister) {
Node resultNode = node;
if(RewriteRule<UremPow2>::applies(node)) {
d_rewriteTable [ kind::BITVECTOR_PLUS ] = RewritePlus;
d_rewriteTable [ kind::BITVECTOR_SUB ] = RewriteSub;
d_rewriteTable [ kind::BITVECTOR_NEG ] = RewriteNeg;
- d_rewriteTable [ kind::BITVECTOR_UDIV ] = RewriteUdiv;
- d_rewriteTable [ kind::BITVECTOR_UREM ] = RewriteUrem;
+ // d_rewriteTable [ kind::BITVECTOR_UDIV ] = RewriteUdiv;
+ // d_rewriteTable [ kind::BITVECTOR_UREM ] = RewriteUrem;
+ d_rewriteTable [ kind::BITVECTOR_UDIV_TOTAL ] = RewriteUdivTotal;
+ d_rewriteTable [ kind::BITVECTOR_UREM_TOTAL ] = RewriteUremTotal;
d_rewriteTable [ kind::BITVECTOR_SMOD ] = RewriteSmod;
d_rewriteTable [ kind::BITVECTOR_SDIV ] = RewriteSdiv;
d_rewriteTable [ kind::BITVECTOR_SREM ] = RewriteSrem;
static void initializeRewrites();
- static RewriteResponse RewriteEqual(TNode node, bool prerewrite = false);
+ static RewriteResponse RewriteEqual(TNode node, bool prerewrite = false);
static RewriteResponse RewriteUlt(TNode node, bool prerewrite = false);
static RewriteResponse RewriteSlt(TNode node, bool prerewrite = false);
static RewriteResponse RewriteUle(TNode node, bool prerewrite = false);
static RewriteResponse RewriteNeg(TNode node, bool prerewrite = false);
static RewriteResponse RewriteUdiv(TNode node, bool prerewrite = false);
static RewriteResponse RewriteUrem(TNode node, bool prerewrite = false);
+ static RewriteResponse RewriteUdivTotal(TNode node, bool prerewrite = false);
+ static RewriteResponse RewriteUremTotal(TNode node, bool prerewrite = false);
static RewriteResponse RewriteSmod(TNode node, bool prerewrite = false);
static RewriteResponse RewriteSdiv(TNode node, bool prerewrite = false);
static RewriteResponse RewriteSrem(TNode node, bool prerewrite = false);
# If a test shouldn't be run in e.g. competition mode,
# put it below in "TESTS +="
# dejan: disable arith2.smt2, arith7.smt2 it's mixed arithmetic and it doesn't go well when changing theoryof
+# lianah: disabled bvdiv.smt2, bvconcat.smt2 as the unconstrained terms are no longer recognized after implementing
+# the divide-by-zero semantics for bv division.
TESTS = \
arith3.smt2 \
arith4.smt2 \
bvbool.smt2 \
bvcmp.smt2 \
bvconcat2.smt2 \
- bvconcat.smt2 \
bvdiv2.smt2 \
- bvdiv.smt2 \
bvext.smt2 \
bvite.smt2 \
bvmul2.smt2 \
(declare-fun v4 () (_ BitVec 1024))
(declare-fun v5 () (_ BitVec 1024))
(assert
- (not
- (= (bvudiv x0 x0) (_ bv1 10))
- )
-)
+ (and
+ (not (= x0 (_ bv0 10)))
+ (not (= (bvudiv x0 x0) (_ bv1 10)))
+))
(check-sat)
(exit)