Integrate new int-blaster (#7781)
authoryoni206 <yoni206@users.noreply.github.com>
Mon, 13 Dec 2021 16:16:08 +0000 (18:16 +0200)
committerGitHub <noreply@github.com>
Mon, 13 Dec 2021 16:16:08 +0000 (16:16 +0000)
This PR removes the code that translates from bit-vectors to integers from the bv_to_int preprocessing pass, and replaces it with a call to the IntBlaster module.

Tests are updated and added, as well as other minor changes.

Solves the following issues (and contains corresponding tests):
cvc5/cvc5-projects#345
cvc5/cvc5-projects#344
cvc5/cvc5-projects#343

@mpreiner FYI

35 files changed:
src/preprocessing/passes/bv_to_int.cpp
src/preprocessing/passes/bv_to_int.h
src/theory/arith/arith_rewriter.cpp
src/theory/arith/nl/iand_solver.cpp
src/theory/bv/int_blaster.cpp
src/theory/bv/int_blaster.h
src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
test/api/cpp/CMakeLists.txt
test/api/cpp/proj-issue344.cpp [new file with mode: 0644]
test/api/cpp/proj-issue345.cpp [new file with mode: 0644]
test/regress/CMakeLists.txt
test/regress/regress0/bv/bv_to_int1.smt2
test/regress/regress0/bv/bv_to_int_bvmul2.smt2
test/regress/regress0/bv/bv_to_int_bvuf_to_intuf.smt2
test/regress/regress0/bv/bv_to_int_bvuf_to_intuf_sorts.smt2
test/regress/regress0/bv/bv_to_int_elim_err.smt2
test/regress/regress0/bv/bv_to_int_int1.smt2 [new file with mode: 0644]
test/regress/regress0/bv/bv_to_int_zext.smt2
test/regress/regress0/bv/proj-issue343.smt2 [new file with mode: 0644]
test/regress/regress2/bv_to_int2.smt2
test/regress/regress2/bv_to_int_ashr.smt2
test/regress/regress2/bv_to_int_bitwise.smt2
test/regress/regress2/bv_to_int_bvmul1.smt2
test/regress/regress2/bv_to_int_bvuf_to_intuf_smtlib.smt2
test/regress/regress2/bv_to_int_inc1.smt2
test/regress/regress2/bv_to_int_mask_array_1.smt2
test/regress/regress2/bv_to_int_mask_array_2.smt2
test/regress/regress2/bv_to_int_mask_array_3.smt2
test/regress/regress2/bv_to_int_quantifiers_bvand.smt2 [new file with mode: 0644]
test/regress/regress2/bv_to_int_shifts.smt2
test/regress/regress3/bv_to_int_and_or.smt2
test/regress/regress3/bv_to_int_bench_9839.smt2.minimized.smt2
test/regress/regress3/bv_to_int_check_bvsgt_bvlshr0_4bit.smt2.minimized.smt2
test/regress/regress3/bv_to_int_input_mouser_detect.c.smt2.minimized.smt2
test/unit/theory/theory_bv_int_blaster_white.cpp

index f106f1ccf461de69284466506397e47e9ed6b5d1..ac1edeb96c1a80bb7178f97558bbad0726dcf154 100644 (file)
 #include "preprocessing/passes/bv_to_int.h"
 
 #include <cmath>
-#include <sstream>
 #include <string>
 #include <unordered_map>
 #include <vector>
 
 #include "expr/node.h"
 #include "expr/node_traversal.h"
-#include "expr/skolem_manager.h"
-#include "options/option_exception.h"
 #include "options/smt_options.h"
 #include "options/uf_options.h"
-#include "preprocessing/assertion_pipeline.h"
-#include "preprocessing/preprocessing_pass_context.h"
 #include "theory/bv/theory_bv_rewrite_rules_operator_elimination.h"
+#include "preprocessing/assertion_pipeline.h"
 #include "theory/bv/theory_bv_rewrite_rules_simplification.h"
 #include "theory/rewriter.h"
-#include "util/bitvector.h"
-#include "util/iand.h"
-#include "util/rational.h"
 
 namespace cvc5 {
 namespace preprocessing {
 namespace passes {
 
 using namespace std;
-using namespace cvc5::kind;
 using namespace cvc5::theory;
 using namespace cvc5::theory::bv;
 
-namespace {
-
-Rational intpow2(uint64_t b)
-{
-  return Rational(Integer(2).pow(b), Integer(1));
-}
-
-} //end empty namespace
-
-Node BVToInt::mkRangeConstraint(Node newVar, uint64_t k)
-{
-  Node lower = d_nm->mkNode(kind::LEQ, d_zero, newVar);
-  Node upper = d_nm->mkNode(kind::LT, newVar, pow2(k));
-  Node result = d_nm->mkNode(kind::AND, lower, upper);
-  return rewrite(result);
-}
-
-Node BVToInt::maxInt(uint64_t k)
-{
-  Assert(k > 0);
-  Rational max_value = intpow2(k) - 1;
-  return d_nm->mkConst(CONST_RATIONAL, max_value);
-}
-
-Node BVToInt::pow2(uint64_t k)
-{
-  Assert(k >= 0);
-  return d_nm->mkConst(CONST_RATIONAL, Rational(intpow2(k)));
-}
-
-Node BVToInt::modpow2(Node n, uint64_t exponent)
-{
-  Node p2 = d_nm->mkConst(CONST_RATIONAL, Rational(intpow2(exponent)));
-  return d_nm->mkNode(kind::INTS_MODULUS_TOTAL, n, p2);
-}
-
-/**
- * Binarizing n via post-order traversal.
- */
-Node BVToInt::makeBinary(Node n)
-{
-  for (TNode current : NodeDfsIterable(n,
-                                       VisitOrder::POSTORDER,
-                                       // skip visited nodes
-                                       [this](TNode tn) {
-                                         return d_binarizeCache.find(tn)
-                                                != d_binarizeCache.end();
-                                       }))
-  {
-    uint64_t numChildren = current.getNumChildren();
-    /*
-     * We already visited the sub-dag rooted at the current node,
-     * and binarized all its children.
-     * Now we binarize the current node itself.
-     */
-    kind::Kind_t k = current.getKind();
-    if ((numChildren > 2)
-        && (k == kind::BITVECTOR_ADD || k == kind::BITVECTOR_MULT
-            || k == kind::BITVECTOR_AND || k == kind::BITVECTOR_OR
-            || k == kind::BITVECTOR_XOR || k == kind::BITVECTOR_CONCAT))
-    {
-      // We only binarize bvadd, bvmul, bvand, bvor, bvxor, bvconcat
-      Assert(d_binarizeCache.find(current[0]) != d_binarizeCache.end());
-      Node result = d_binarizeCache[current[0]];
-      for (uint64_t i = 1; i < numChildren; i++)
-      {
-        Assert(d_binarizeCache.find(current[i]) != d_binarizeCache.end());
-        Node child = d_binarizeCache[current[i]];
-        result = d_nm->mkNode(current.getKind(), result, child);
-      }
-      d_binarizeCache[current] = result;
-    }
-    else if (numChildren > 0)
-    {
-      // current has children, but we do not binarize it
-      NodeBuilder builder(k);
-      if (current.getMetaKind() == kind::metakind::PARAMETERIZED)
-      {
-        builder << current.getOperator();
-      }
-      for (Node child : current)
-      {
-        builder << d_binarizeCache[child].get();
-      }
-      d_binarizeCache[current] = builder.constructNode();
-    }
-    else
-    {
-      // current has no children
-      d_binarizeCache[current] = current;
-    }
-  }
-  return d_binarizeCache[n];
-}
-
-/**
- * We traverse n and perform rewrites both on the way down and on the way up.
- * On the way down we rewrite the node but not it's children.
- * On the way up, we update the node's children to the rewritten ones.
- * For each sub-node, we perform rewrites to eliminate operators.
- * Then, the original children are added to toVisit stack so that we rewrite
- * them as well.
- */
-Node BVToInt::eliminationPass(Node n)
-{
-  std::vector<Node> toVisit;
-  toVisit.push_back(n);
-  Node current;
-  while (!toVisit.empty())
-  {
-    current = toVisit.back();
-    // assert that the node is binarized
-    // The following variable is only used in assertions
-    CVC5_UNUSED kind::Kind_t k = current.getKind();
-    uint64_t numChildren = current.getNumChildren();
-    Assert((numChildren == 2)
-           || !(k == kind::BITVECTOR_ADD || k == kind::BITVECTOR_MULT
-                || k == kind::BITVECTOR_AND || k == kind::BITVECTOR_OR
-                || k == kind::BITVECTOR_XOR || k == kind::BITVECTOR_CONCAT));
-    toVisit.pop_back();
-    bool inEliminationCache =
-        (d_eliminationCache.find(current) != d_eliminationCache.end());
-    bool inRebuildCache =
-        (d_rebuildCache.find(current) != d_rebuildCache.end());
-    if (!inEliminationCache)
-    {
-      // current is not the elimination of any previously-visited node
-      // current hasn't been eliminated yet.
-      // eliminate operators from it using rewrite rules
-      Node currentEliminated =
-          FixpointRewriteStrategy<RewriteRule<UdivZero>,
-                                  RewriteRule<SdivEliminateFewerBitwiseOps>,
-                                  RewriteRule<SremEliminateFewerBitwiseOps>,
-                                  RewriteRule<SmodEliminateFewerBitwiseOps>,
-                                  RewriteRule<XnorEliminate>,
-                                  RewriteRule<NandEliminate>,
-                                  RewriteRule<NorEliminate>,
-                                  RewriteRule<NegEliminate>,
-                                  RewriteRule<XorEliminate>,
-                                  RewriteRule<OrEliminate>,
-                                  RewriteRule<SubEliminate>,
-                                  RewriteRule<RepeatEliminate>,
-                                  RewriteRule<RotateRightEliminate>,
-                                  RewriteRule<RotateLeftEliminate>,
-                                  RewriteRule<CompEliminate>,
-                                  RewriteRule<SleEliminate>,
-                                  RewriteRule<SltEliminate>,
-                                  RewriteRule<SgtEliminate>,
-                                  RewriteRule<SgeEliminate>>::apply(current);
-
-      // save in the cache
-      d_eliminationCache[current] = currentEliminated;
-      // also assign the eliminated now to itself to avoid revisiting.
-      d_eliminationCache[currentEliminated] = currentEliminated;
-      // put the eliminated node in the rebuild cache, but mark that it hasn't
-      // yet been rebuilt by assigning null.
-      d_rebuildCache[currentEliminated] = Node();
-      // Push the eliminated node to the stack
-      toVisit.push_back(currentEliminated);
-      // Add the children to the stack for future processing.
-      toVisit.insert(
-          toVisit.end(), currentEliminated.begin(), currentEliminated.end());
-    }
-    if (inRebuildCache)
-    {
-      // current was already added to the rebuild cache.
-      if (d_rebuildCache[current].get().isNull())
-      {
-        // current wasn't rebuilt yet.
-        numChildren = current.getNumChildren();
-        if (numChildren == 0)
-        {
-          // We only eliminate operators that are not nullary.
-          d_rebuildCache[current] = current;
-        }
-        else
-        {
-          // The main operator is replaced, and the children
-          // are replaced with their eliminated counterparts.
-          NodeBuilder builder(current.getKind());
-          if (current.getMetaKind() == kind::metakind::PARAMETERIZED)
-          {
-            builder << current.getOperator();
-          }
-          for (Node child : current)
-          {
-            Assert(d_eliminationCache.find(child) != d_eliminationCache.end());
-            Node eliminatedChild = d_eliminationCache[child];
-            Assert(d_rebuildCache.find(eliminatedChild) != d_eliminationCache.end());
-            Assert(!d_rebuildCache[eliminatedChild].get().isNull());
-            builder << d_rebuildCache[eliminatedChild].get();
-          }
-          d_rebuildCache[current] = builder.constructNode();
-        }
-      }
-    }
-  }
-  Assert(d_eliminationCache.find(n) != d_eliminationCache.end());
-  Node eliminated = d_eliminationCache[n];
-  Assert(d_rebuildCache.find(eliminated) != d_rebuildCache.end());
-  Assert(!d_rebuildCache[eliminated].get().isNull());
-  return d_rebuildCache[eliminated];
-}
-
-/**
- * Translate n to Integers via post-order traversal.
- */
-Node BVToInt::bvToInt(Node n)
-{
-  // make sure the node is re-written before processing it.
-  n = rewrite(n);
-  n = makeBinary(n);
-  n = eliminationPass(n);
-  // binarize again, in case the elimination pass introduced
-  // non-binary terms (as can happen by RepeatEliminate, for example).
-  n = makeBinary(n);
-  vector<Node> toVisit;
-  toVisit.push_back(n);
-
-  while (!toVisit.empty())
-  {
-    Node current = toVisit.back();
-    uint64_t currentNumChildren = current.getNumChildren();
-    if (d_bvToIntCache.find(current) == d_bvToIntCache.end())
-    {
-      // This is the first time we visit this node and it is not in the cache.
-      // We mark this node as visited but not translated by assiging
-      // a null node to it.
-      d_bvToIntCache[current] = Node();
-      // all the node's children are added to the stack to be visited
-      // before visiting this node again.
-      toVisit.insert(toVisit.end(), current.begin(), current.end());
-      // If this is a UF applicatinon, we also add the function to
-      // toVisit.
-      if (current.getKind() == kind::APPLY_UF)
-      {
-        toVisit.push_back(current.getOperator());
-      }
-    }
-    else
-    {
-      // We already visited and translated this node
-      if (!d_bvToIntCache[current].get().isNull())
-      {
-        // We are done computing the translation for current
-        toVisit.pop_back();
-      }
-      else
-      {
-        // We are now visiting current on the way back up.
-        // This is when we do the actual translation.
-        Node translation;
-        if (currentNumChildren == 0)
-        {
-          translation = translateNoChildren(current);
-        }
-        else
-        {
-          /**
-           * The current node has children.
-           * Since we are on the way back up,
-           * these children were already translated.
-           * We save their translation for easy access.
-           * If the node's kind is APPLY_UF,
-           * we also need to include the translated uninterpreted function in
-           * this list.
-           */
-          vector<Node> translated_children;
-          if (current.getKind() == kind::APPLY_UF)
-          {
-            translated_children.push_back(
-                d_bvToIntCache[current.getOperator()]);
-          }
-          for (uint64_t i = 0; i < currentNumChildren; i++)
-          {
-            translated_children.push_back(d_bvToIntCache[current[i]]);
-          }
-          translation = translateWithChildren(current, translated_children);
-        }
-        // Map the current node to its translation in the cache.
-        d_bvToIntCache[current] = translation;
-        // Also map the translation to itself.
-        d_bvToIntCache[translation] = translation;
-        toVisit.pop_back();
-      }
-    }
-  }
-  return d_bvToIntCache[n].get();
-}
-
-Node BVToInt::translateWithChildren(Node original,
-                                    const vector<Node>& translated_children)
-{
-  // The translation of the original node is determined by the kind of
-  // the node.
-  kind::Kind_t oldKind = original.getKind();
-  // ultbv and sltbv were supposed to be eliminated before this point.
-  Assert(oldKind != kind::BITVECTOR_ULTBV);
-  Assert(oldKind != kind::BITVECTOR_SLTBV);
-  // The following variable will only be used in assertions.
-  CVC5_UNUSED uint64_t originalNumChildren = original.getNumChildren();
-  Node returnNode;
-  switch (oldKind)
-  {
-    case kind::BITVECTOR_ADD:
-    {
-      Assert(originalNumChildren == 2);
-      uint64_t bvsize = original[0].getType().getBitVectorSize();
-      Node plus = d_nm->mkNode(kind::PLUS, translated_children);
-      Node p2 = pow2(bvsize);
-      returnNode = d_nm->mkNode(kind::INTS_MODULUS_TOTAL, plus, p2);
-      break;
-    }
-    case kind::BITVECTOR_MULT:
-    {
-      Assert(originalNumChildren == 2);
-      uint64_t bvsize = original[0].getType().getBitVectorSize();
-      Node mult = d_nm->mkNode(kind::MULT, translated_children);
-      Node p2 = pow2(bvsize);
-      returnNode = d_nm->mkNode(kind::INTS_MODULUS_TOTAL, mult, p2);
-      break;
-    }
-    case kind::BITVECTOR_UDIV:
-    {
-      uint64_t bvsize = original[0].getType().getBitVectorSize();
-      // we use an ITE for the case where the second operand is 0.
-      Node pow2BvSize = pow2(bvsize);
-      Node divNode =
-          d_nm->mkNode(kind::INTS_DIVISION_TOTAL, translated_children);
-      returnNode = d_nm->mkNode(
-          kind::ITE,
-          d_nm->mkNode(kind::EQUAL, translated_children[1], d_zero),
-          d_nm->mkNode(kind::MINUS, pow2BvSize, d_one),
-          divNode);
-      break;
-    }
-    case kind::BITVECTOR_UREM:
-    {
-      // we use an ITE for the case where the second operand is 0.
-      Node modNode =
-          d_nm->mkNode(kind::INTS_MODULUS_TOTAL, translated_children);
-      returnNode = d_nm->mkNode(
-          kind::ITE,
-          d_nm->mkNode(kind::EQUAL, translated_children[1], d_zero),
-          translated_children[0],
-          modNode);
-      break;
-    }
-    case kind::BITVECTOR_NOT:
-    {
-      uint64_t bvsize = original[0].getType().getBitVectorSize();
-      // we use a specified function to generate the node.
-      returnNode = createBVNotNode(translated_children[0], bvsize);
-      break;
-    }
-    case kind::BITVECTOR_TO_NAT:
-    {
-      // In this case, we already translated the child to integer.
-      // So the result is the translated child.
-      returnNode = translated_children[0];
-      break;
-    }
-    case kind::INT_TO_BITVECTOR:
-    {
-      // ((_ int2bv n) t) ---> (mod t 2^n)
-      size_t sz = original.getOperator().getConst<IntToBitVector>().d_size;
-      returnNode = d_nm->mkNode(
-          kind::INTS_MODULUS_TOTAL, translated_children[0], pow2(sz));
-    }
-    break;
-    case kind::BITVECTOR_AND:
-    {
-      // We support three configurations:
-      // 1. translating to IAND
-      // 2. translating back to BV (using BITVECTOR_TO_NAT and INT_TO_BV
-      // operators)
-      // 3. translating into a sum
-      uint64_t bvsize = original[0].getType().getBitVectorSize();
-      if (options().smt.solveBVAsInt == options::SolveBVAsIntMode::IAND)
-      {
-        Node iAndOp = d_nm->mkConst(IntAnd(bvsize));
-        returnNode = d_nm->mkNode(
-            kind::IAND, iAndOp, translated_children[0], translated_children[1]);
-      }
-      else if (options().smt.solveBVAsInt == options::SolveBVAsIntMode::BV)
-      {
-        // translate the children back to BV
-        Node intToBVOp = d_nm->mkConst<IntToBitVector>(IntToBitVector(bvsize));
-        Node x = translated_children[0];
-        Node y = translated_children[1];
-        Node bvx = d_nm->mkNode(intToBVOp, x);
-        Node bvy = d_nm->mkNode(intToBVOp, y);
-        // perform bvand on the bit-vectors
-        Node bvand = d_nm->mkNode(kind::BITVECTOR_AND, bvx, bvy);
-        // translate the result to integers
-        returnNode = d_nm->mkNode(kind::BITVECTOR_TO_NAT, bvand);
-      }
-      else
-      {
-        Assert(options().smt.solveBVAsInt == options::SolveBVAsIntMode::SUM);
-        // Construct a sum of ites, based on granularity.
-        Assert(translated_children.size() == 2);
-        returnNode =
-            d_iandUtils.createSumNode(translated_children[0],
-                                      translated_children[1],
-                                      bvsize,
-                                      options().smt.BVAndIntegerGranularity);
-      }
-      break;
-    }
-    case kind::BITVECTOR_SHL:
-    {
-      /**
-       * a << b is a*2^b.
-       * The exponentiation is simulated by an ite.
-       * Only cases where b <= bit width are considered.
-       * Otherwise, the result is 0.
-       */
-      uint64_t bvsize = original[0].getType().getBitVectorSize();
-      returnNode = createShiftNode(translated_children, bvsize, true);
-      break;
-    }
-    case kind::BITVECTOR_LSHR:
-    {
-      /**
-       * a >> b is a div 2^b.
-       * The exponentiation is simulated by an ite.
-       * Only cases where b <= bit width are considered.
-       * Otherwise, the result is 0.
-       */
-      uint64_t bvsize = original[0].getType().getBitVectorSize();
-      returnNode = createShiftNode(translated_children, bvsize, false);
-      break;
-    }
-    case kind::BITVECTOR_ASHR:
-    {
-      /*  From SMT-LIB2:
-       *  (bvashr s t) abbreviates
-       *     (ite (= ((_ extract |m-1| |m-1|) s) #b0)
-       *          (bvlshr s t)
-       *          (bvnot (bvlshr (bvnot s) t)))
-       *
-       *  Equivalently:
-       *  (bvashr s t) abbreviates
-       *      (ite (bvult s 100000...)
-       *           (bvlshr s t)
-       *           (bvnot (bvlshr (bvnot s) t)))
-       *
-       */
-      uint64_t bvsize = original[0].getType().getBitVectorSize();
-      // signed_min is 100000...
-      Node signed_min = pow2(bvsize - 1);
-      Node condition =
-          d_nm->mkNode(kind::LT, translated_children[0], signed_min);
-      Node thenNode = createShiftNode(translated_children, bvsize, false);
-      vector<Node> children = {createBVNotNode(translated_children[0], bvsize),
-                               translated_children[1]};
-      Node elseNode =
-          createBVNotNode(createShiftNode(children, bvsize, false), bvsize);
-      returnNode = d_nm->mkNode(kind::ITE, condition, thenNode, elseNode);
-      break;
-    }
-    case kind::BITVECTOR_ITE:
-    {
-      // Lifted to a boolean ite.
-      Node cond = d_nm->mkNode(kind::EQUAL, translated_children[0], d_one);
-      returnNode = d_nm->mkNode(
-          kind::ITE, cond, translated_children[1], translated_children[2]);
-      break;
-    }
-    case kind::BITVECTOR_ZERO_EXTEND:
-    {
-      returnNode = translated_children[0];
-      break;
-    }
-    case kind::BITVECTOR_SIGN_EXTEND:
-    {
-      uint64_t bvsize = original[0].getType().getBitVectorSize();
-      Node arg = translated_children[0];
-      if (arg.isConst())
-      {
-        Rational c(arg.getConst<Rational>());
-        Rational twoToKMinusOne(intpow2(bvsize - 1));
-        uint64_t amount = bv::utils::getSignExtendAmount(original);
-        /* if the msb is 0, this is like zero_extend.
-         *  msb is 0 <-> the value is less than 2^{bvsize-1}
-         */
-        if (c < twoToKMinusOne || amount == 0)
-        {
-          returnNode = arg;
-        }
-        else
-        {
-          /* otherwise, we add the integer equivalent of
-           * 11....1 `amount` times
-           */
-          Rational max_of_amount = intpow2(amount) - 1;
-          Rational mul = max_of_amount * intpow2(bvsize);
-          Rational sum = mul + c;
-          returnNode = d_nm->mkConst(CONST_RATIONAL, sum);
-        }
-      }
-      else
-      {
-        uint64_t amount = bv::utils::getSignExtendAmount(original);
-        if (amount == 0)
-        {
-          returnNode = translated_children[0];
-        }
-        else
-        {
-          Rational twoToKMinusOne(intpow2(bvsize - 1));
-          Node minSigned = d_nm->mkConst(CONST_RATIONAL, twoToKMinusOne);
-          /* condition checks whether the msb is 1.
-           * This holds when the integer value is smaller than
-           * 100...0, which is 2^{bvsize-1}.
-           */
-          Node condition = d_nm->mkNode(kind::LT, arg, minSigned);
-          Node thenResult = arg;
-          Node left = maxInt(amount);
-          Node mul = d_nm->mkNode(kind::MULT, left, pow2(bvsize));
-          Node sum = d_nm->mkNode(kind::PLUS, mul, arg);
-          Node elseResult = sum;
-          Node ite = d_nm->mkNode(kind::ITE, condition, thenResult, elseResult);
-          returnNode = ite;
-        }
-      }
-      break;
-    }
-    case kind::BITVECTOR_CONCAT:
-    {
-      // (concat a b) translates to a*2^k+b, k being the bitwidth of b.
-      uint64_t bvsizeRight = original[1].getType().getBitVectorSize();
-      Node pow2BvSizeRight = pow2(bvsizeRight);
-      Node a =
-          d_nm->mkNode(kind::MULT, translated_children[0], pow2BvSizeRight);
-      Node b = translated_children[1];
-      returnNode = d_nm->mkNode(kind::PLUS, a, b);
-      break;
-    }
-    case kind::BITVECTOR_EXTRACT:
-    {
-      // ((_ extract i j) a) is a / 2^j mod 2^{i-j+1}
-      // original = a[i:j]
-      uint64_t i = bv::utils::getExtractHigh(original);
-      uint64_t j = bv::utils::getExtractLow(original);
-      Assert(i >= j);
-      Node div = d_nm->mkNode(
-          kind::INTS_DIVISION_TOTAL, translated_children[0], pow2(j));
-      returnNode = modpow2(div, i - j + 1);
-      break;
-    }
-    case kind::EQUAL:
-    {
-      returnNode = d_nm->mkNode(kind::EQUAL, translated_children);
-      break;
-    }
-    case kind::BITVECTOR_ULT:
-    {
-      returnNode = d_nm->mkNode(kind::LT, translated_children);
-      break;
-    }
-    case kind::BITVECTOR_ULE:
-    {
-      returnNode = d_nm->mkNode(kind::LEQ, translated_children);
-      break;
-    }
-    case kind::BITVECTOR_UGT:
-    {
-      returnNode = d_nm->mkNode(kind::GT, translated_children);
-      break;
-    }
-    case kind::BITVECTOR_UGE:
-    {
-      returnNode = d_nm->mkNode(kind::GEQ, translated_children);
-      break;
-    }
-    case kind::LT:
-    {
-      returnNode = d_nm->mkNode(kind::LT, translated_children);
-      break;
-    }
-    case kind::LEQ:
-    {
-      returnNode = d_nm->mkNode(kind::LEQ, translated_children);
-      break;
-    }
-    case kind::GT:
-    {
-      returnNode = d_nm->mkNode(kind::GT, translated_children);
-      break;
-    }
-    case kind::GEQ:
-    {
-      returnNode = d_nm->mkNode(kind::GEQ, translated_children);
-      break;
-    }
-    case kind::ITE:
-    {
-      returnNode = d_nm->mkNode(oldKind, translated_children);
-      break;
-    }
-    case kind::APPLY_UF:
-    {
-      /**
-       * higher order logic allows comparing between functions
-       * The translation does not support this,
-       * as the translated functions may be different outside
-       * of the bounds that were relevant for the original
-       * bit-vectors.
-       */
-      if (childrenTypesChanged(original) && logicInfo().isHigherOrder())
-      {
-        throw TypeCheckingExceptionPrivate(
-            original,
-            string("Cannot translate to Int: ") + original.toString());
-      }
-      // Insert the translated application term to the cache
-      returnNode = d_nm->mkNode(kind::APPLY_UF, translated_children);
-      // Add range constraints if necessary.
-      // If the original range was a BV sort, the original application of
-      // the function Must be within the range determined by the
-      // bitwidth.
-      if (original.getType().isBitVector())
-      {
-        d_rangeAssertions.insert(mkRangeConstraint(
-            returnNode, original.getType().getBitVectorSize()));
-      }
-      break;
-    }
-    case kind::BOUND_VAR_LIST:
-    {
-      returnNode = d_nm->mkNode(oldKind, translated_children);
-      break;
-    }
-    case kind::FORALL:
-    {
-      returnNode = translateQuantifiedFormula(original);
-      break;
-    }
-    default:
-    {
-      Assert(oldKind != kind::EXISTS);  // Exists is eliminated by the rewriter.
-      // In the default case, we have reached an operator that we do not
-      // translate directly to integers. The children whose types have
-      // changed from bv to int should be adjusted back to bv and then
-      // this term is reconstructed.
-      TypeNode resultingType;
-      if (original.getType().isBitVector())
-      {
-        resultingType = d_nm->integerType();
-      }
-      else
-      {
-        resultingType = original.getType();
-      }
-      Node reconstruction =
-          reconstructNode(original, resultingType, translated_children);
-      returnNode = reconstruction;
-      break;
-    }
-  }
-  Trace("bv-to-int-debug") << "original: " << original << endl;
-  Trace("bv-to-int-debug") << "returnNode: " << returnNode << endl;
-  return returnNode;
-}
-
-Node BVToInt::translateNoChildren(Node original)
-{
-  SkolemManager* sm = d_nm->getSkolemManager();
-  Node translation;
-  Assert(original.isVar() || original.isConst());
-  if (original.isVar())
-  {
-    if (original.getType().isBitVector())
-    {
-      // For bit-vector variables, we create fresh integer variables.
-      if (original.getKind() == kind::BOUND_VARIABLE)
-      {
-        // Range constraints for the bound integer variables are not added now.
-        // they will be added once the quantifier itself is handled.
-        std::stringstream ss;
-        ss << original;
-        translation = d_nm->mkBoundVar(ss.str() + "_int", d_nm->integerType());
-      }
-      else
-      {
-        // New integer variables  that are not bound (symbolic constants)
-        // are added together with range constraints induced by the 
-        // bit-width of the original bit-vector variables.
-        Node newVar = sm->mkDummySkolem("__bvToInt_var",
-                                        d_nm->integerType(),
-                                        "Variable introduced in bvToInt "
-                                        "pass instead of original variable "
-                                            + original.toString());
-        uint64_t bvsize = original.getType().getBitVectorSize();
-        translation = newVar;
-        d_rangeAssertions.insert(mkRangeConstraint(newVar, bvsize));
-        defineBVUFAsIntUF(original, newVar);
-      }
-    }
-    else if (original.getType().isFunction())
-    {
-      translation = translateFunctionSymbol(original);
-    }
-    else
-    {
-      // variables other than bit-vector variables and function symbols
-      // are left intact
-      translation = original;
-    }
-  }
-  else
-  {
-    // original is a const
-    if (original.getKind() == kind::CONST_BITVECTOR)
-    {
-      // Bit-vector constants are transformed into their integer value.
-      BitVector constant(original.getConst<BitVector>());
-      Integer c = constant.toInteger();
-      translation = d_nm->mkConst(CONST_RATIONAL, Rational(c));
-    }
-    else
-    {
-      // Other constants stay the same.
-      translation = original;
-    }
-  }
-  return translation;
-}
-
-Node BVToInt::translateFunctionSymbol(Node bvUF)
-{
-  // construct the new function symbol.
-  Node intUF;
-  TypeNode tn = bvUF.getType();
-  TypeNode bvRange = tn.getRangeType();
-  // The function symbol has not been converted yet
-  vector<TypeNode> bvDomain = tn.getArgTypes();
-  vector<TypeNode> intDomain;
-  /**
-   * if the original range is a bit-vector sort,
-   * the new range should be an integer sort.
-   * Otherwise, we keep the original range.
-   * Similarly for the domains.
-   */
-  TypeNode intRange = bvRange.isBitVector() ? d_nm->integerType() : bvRange;
-  for (TypeNode d : bvDomain)
-  {
-    intDomain.push_back(d.isBitVector() ? d_nm->integerType() : d);
-  }
-  SkolemManager* sm = d_nm->getSkolemManager();
-  ostringstream os;
-  os << "__bvToInt_fun_" << bvUF << "_int";
-  intUF = sm->mkDummySkolem(
-      os.str(), d_nm->mkFunctionType(intDomain, intRange), "bv2int function");
-  // introduce a `define-fun` in the smt-engine to keep
-  // the correspondence between the original
-  // function symbol and the new one.
-  defineBVUFAsIntUF(bvUF, intUF);
-  return intUF;
-}
-
-void BVToInt::defineBVUFAsIntUF(Node bvUF, Node intUF)
-{
-  // The resulting term
-  Node result;
-  // The type of the resulting term
-  TypeNode resultType;
-  // symbolic arguments of original function
-  vector<Node> args;
-  if (!bvUF.getType().isFunction()) {
-    // bvUF is a variable.
-    // in this case, the result is just the original term
-    // (it will be casted later if needed)
-    result = intUF;
-    resultType = bvUF.getType();
-  } else {
-    // bvUF is a function with arguments
-    // The arguments need to be casted as well.
-    TypeNode tn = bvUF.getType();
-    resultType = tn.getRangeType();
-    vector<TypeNode> bvDomain = tn.getArgTypes();
-    // children of the new symbolic application
-    vector<Node> achildren;
-    achildren.push_back(intUF);
-    int i = 0;
-    for (const TypeNode& d : bvDomain)
-    {
-      // Each bit-vector argument is casted to a natural number
-      // Other arguments are left intact.
-      Node fresh_bound_var = d_nm->mkBoundVar(d);
-      args.push_back(fresh_bound_var);
-      Node castedArg = args[i];
-      if (d.isBitVector())
-      {
-        castedArg = castToType(castedArg, d_nm->integerType());
-      }
-      achildren.push_back(castedArg);
-      i++;
-    }
-    result = d_nm->mkNode(kind::APPLY_UF, achildren);
-  }
-  // If the result is BV, it needs to be casted back.
-  result = castToType(result, resultType);
-  // add the substitution to the preprocessing context, which ensures the
-  // model for bvUF is correct, as well as substituting it in the input
-  // assertions when necessary.
-  if (!args.empty())
-  {
-    result = d_nm->mkNode(
-        kind::LAMBDA, d_nm->mkNode(kind::BOUND_VAR_LIST, args), result);
-  }
-  d_preprocContext->addSubstitution(bvUF, result);
-}
-
-bool BVToInt::childrenTypesChanged(Node n)
-{
-  bool result = false;
-  for (const Node& child : n)
-  {
-    TypeNode originalType = child.getType();
-    TypeNode newType = d_bvToIntCache[child].get().getType();
-    if (!newType.isSubtypeOf(originalType))
-    {
-      result = true;
-      break;
-    }
-  }
-  return result;
-}
-
-Node BVToInt::castToType(Node n, TypeNode tn)
-{
-  // If there is no reason to cast, return the
-  // original node.
-  if (n.getType().isSubtypeOf(tn))
-  {
-    return n;
-  }
-  // We only case int to bv or vice verse.
-  Assert((n.getType().isBitVector() && tn.isInteger())
-         || (n.getType().isInteger() && tn.isBitVector()));
-  if (n.getType().isInteger())
-  {
-    Assert(tn.isBitVector());
-    unsigned bvsize = tn.getBitVectorSize();
-    Node intToBVOp = d_nm->mkConst<IntToBitVector>(IntToBitVector(bvsize));
-    return d_nm->mkNode(intToBVOp, n);
-  }
-  Assert(n.getType().isBitVector());
-  Assert(tn.isInteger());
-  return d_nm->mkNode(kind::BITVECTOR_TO_NAT, n);
-}
-
-Node BVToInt::reconstructNode(Node originalNode,
-                              TypeNode resultType,
-                              const vector<Node>& translated_children)
-{
-  // first, we adjust the children of the node as needed.
-  // re-construct the term with the adjusted children.
-  kind::Kind_t oldKind = originalNode.getKind();
-  NodeBuilder builder(oldKind);
-  if (originalNode.getMetaKind() == kind::metakind::PARAMETERIZED)
-  {
-    builder << originalNode.getOperator();
-  }
-  for (size_t i = 0; i < originalNode.getNumChildren(); i++)
-  {
-    Node originalChild = originalNode[i];
-    Node translatedChild = translated_children[i];
-    Node adjustedChild = castToType(translatedChild, originalChild.getType());
-    builder << adjustedChild;
-  }
-  Node reconstruction = builder.constructNode();
-  // cast to tn in case the reconstruction is a bit-vector.
-  reconstruction = castToType(reconstruction, resultType);
-  return reconstruction;
-}
-
 BVToInt::BVToInt(PreprocessingPassContext* preprocContext)
     : PreprocessingPass(preprocContext, "bv-to-int"),
-      d_binarizeCache(userContext()),
-      d_eliminationCache(userContext()),
-      d_rebuildCache(userContext()),
-      d_bvToIntCache(userContext()),
-      d_rangeAssertions(userContext())
-{
-  d_nm = NodeManager::currentNM();
-  d_zero = d_nm->mkConst(CONST_RATIONAL, Rational(0));
-  d_one = d_nm->mkConst(CONST_RATIONAL, Rational(1));
-
-  if (options().smt.solveBVAsInt == options::SolveBVAsIntMode::BITWISE)
-  {
-    throw OptionException("bitwise option is not supported currently");
-  }
-};
+      d_intBlaster(preprocContext->getEnv(),
+                   options::solveBVAsInt(),
+                   options::BVAndIntegerGranularity()) {}
 
 PreprocessingPassResult BVToInt::applyInternal(
     AssertionPipeline* assertionsToPreprocess)
 {
+  // vector of boolean nodes for additional constraints
+  // this will always contain range constraints
+  // and for options::SolveBVAsIntMode::BITWISE, it will
+  // also include bitwise assertion constraints
+  std::vector<Node> additionalConstraints;
+  std::map<Node, Node> skolems;
   for (uint64_t i = 0; i < assertionsToPreprocess->size(); ++i)
   {
     Node bvNode = (*assertionsToPreprocess)[i];
-    Node intNode = bvToInt(bvNode);
+    Node intNode =
+        d_intBlaster.intBlast(bvNode, additionalConstraints, skolems);
     Node rwNode = rewrite(intNode);
     Trace("bv-to-int-debug") << "bv node: " << bvNode << std::endl;
     Trace("bv-to-int-debug") << "int node: " << intNode << std::endl;
     Trace("bv-to-int-debug") << "rw node: " << rwNode << std::endl;
     assertionsToPreprocess->replace(i, rwNode);
   }
-  addFinalizeRangeAssertions(assertionsToPreprocess);
+  addFinalizeAssertions(assertionsToPreprocess, additionalConstraints);
+  addSkolemDefinitions(skolems);
   return PreprocessingPassResult::NO_CONFLICT;
 }
 
-void BVToInt::addFinalizeRangeAssertions(
-    AssertionPipeline* assertionsToPreprocess)
-{
-  // collect the range assertions from d_rangeAssertions
-  // (which is a context-dependent set)
-  // into a vector.
-  vector<Node> vec_range;
-  vec_range.assign(d_rangeAssertions.key_begin(), d_rangeAssertions.key_end());
-  // conjoin all range assertions and add the conjunction
-  // as a new assertion
-  Node rangeAssertions = rewrite(d_nm->mkAnd(vec_range));
-  assertionsToPreprocess->push_back(rangeAssertions);
-  Trace("bv-to-int-debug") << "range constraints: "
-                           << rangeAssertions.toString() << std::endl;
-}
-
-Node BVToInt::createShiftNode(vector<Node> children,
-                              uint64_t bvsize,
-                              bool isLeftShift)
-{
-  /**
-   * from SMT-LIB:
-   * [[(bvshl s t)]] := nat2bv[m](bv2nat([[s]]) * 2^(bv2nat([[t]])))
-   * [[(bvlshr s t)]] := nat2bv[m](bv2nat([[s]]) div 2^(bv2nat([[t]])))
-   * Since we don't have exponentiation, we use an ite.
-   * Important note: below we use INTS_DIVISION_TOTAL, which is safe here
-   * because we divide by 2^... which is never 0.
-   */
-  Node x = children[0];
-  Node y = children[1];
-  // shifting by const is eliminated by the theory rewriter
-  Assert(!y.isConst());
-  Node ite = d_zero;
-  Node body;
-  for (uint64_t i = 0; i < bvsize; i++)
-  {
-    if (isLeftShift)
-    {
-      body = d_nm->mkNode(kind::INTS_MODULUS_TOTAL,
-                          d_nm->mkNode(kind::MULT, x, pow2(i)),
-                          pow2(bvsize));
-    }
-    else
-    {
-      body = d_nm->mkNode(kind::INTS_DIVISION_TOTAL, x, pow2(i));
-    }
-    ite = d_nm->mkNode(
-        kind::ITE,
-        d_nm->mkNode(
-            kind::EQUAL, y, d_nm->mkConst(CONST_RATIONAL, Rational(i))),
-        body,
-        ite);
-  }
-  return ite;
-}
-
-Node BVToInt::translateQuantifiedFormula(Node quantifiedNode)
+void BVToInt::addSkolemDefinitions(const std::map<Node, Node>& skolems)
 {
-  kind::Kind_t k = quantifiedNode.getKind();
-  Node boundVarList = quantifiedNode[0];
-  Assert(boundVarList.getKind() == kind::BOUND_VAR_LIST);
-  // Since bit-vector variables are being translated to
-  // integer variables, we need to substitute the new ones
-  // for the old ones.
-  vector<Node> oldBoundVars;
-  vector<Node> newBoundVars;
-  vector<Node> rangeConstraints;
-  for (Node bv : quantifiedNode[0])
+  map<Node, Node>::const_iterator it;
+  for (it = skolems.begin(); it != skolems.end(); it++)
   {
-    oldBoundVars.push_back(bv);
-    if (bv.getType().isBitVector())
+    Node originalSkolem = it->first;
+    Node definition = it->second;
+    std::vector<Node> args;
+    Node body;
+    if (definition.getType().isFunction())
     {
-      // bit-vector variables are replaced by integer ones.
-      // the new variables induce range constraints based on the
-      // original bit-width.
-      Node newBoundVar = d_bvToIntCache[bv];
-      newBoundVars.push_back(newBoundVar);
-      rangeConstraints.push_back(
-          mkRangeConstraint(newBoundVar, bv.getType().getBitVectorSize()));
+      args.insert(args.end(), definition[0].begin(), definition[0].end());
+      body = definition[1];
     }
     else
     {
-      // variables that are not bit-vectors are not changed
-      newBoundVars.push_back(bv);
+      body = definition;
     }
+    Trace("bv-to-int-debug") << "adding substitution: " << "[" << originalSkolem  << "] ----> [" << definition << "]"  << std::endl; 
+    d_preprocContext->addSubstitution(originalSkolem, definition);
   }
-
-  // the body of the quantifier
-  Node matrix = d_bvToIntCache[quantifiedNode[1]];
-  // make the substitution
-  matrix = matrix.substitute(oldBoundVars.begin(),
-                             oldBoundVars.end(),
-                             newBoundVars.begin(),
-                             newBoundVars.end());
-  // A node to represent all the range constraints.
-  Node ranges = d_nm->mkAnd(rangeConstraints);
-  // Add the range constraints to the body of the quantifier.
-  // For "exists", this is added conjunctively
-  // For "forall", this is added to the left side of an implication.
-  matrix = d_nm->mkNode(
-      k == kind::FORALL ? kind::IMPLIES : kind::AND, ranges, matrix);
-  // create the new quantified formula and return it.
-  Node newBoundVarsList = d_nm->mkNode(kind::BOUND_VAR_LIST, newBoundVars);
-  Node result = d_nm->mkNode(kind::FORALL, newBoundVarsList, matrix);
-  return result;
 }
 
-Node BVToInt::createBVNotNode(Node n, uint64_t bvsize)
+void BVToInt::addFinalizeAssertions(
+    AssertionPipeline* assertionsToPreprocess,
+    const std::vector<Node>& additionalConstraints)
 {
-  return d_nm->mkNode(kind::MINUS, maxInt(bvsize), n);
+  NodeManager* nm = NodeManager::currentNM();
+  Node lemmas = nm->mkAnd(additionalConstraints);
+  assertionsToPreprocess->push_back(lemmas);
+  Trace("bv-to-int-debug") << "range constraints: " << lemmas.toString()
+                           << std::endl;
 }
 
 }  // namespace passes
index d09f9e738d769b13cd5b33fc808f4d380c4b71b0..24fc185b589eb471891890fdecb8b5c2bfd97363 100644 (file)
@@ -1,6 +1,7 @@
+
 /******************************************************************************
  * Top contributors (to current version):
- *   Yoni Zohar, Gereon Kremer, Makai Mann
+ *   Yoni Zohar
  *
  * This file is part of the cvc5 project.
  *
  * directory for licensing information.
  * ****************************************************************************
  *
- * The BVToInt preprocessing pass
- *
- * Converts bit-vector formulas to integer formulas.
- * The conversion is implemented using a translation function Tr,
- * roughly described as follows:
- *
- * Tr(x) = fresh_x for every bit-vector variable x, where fresh_x is a fresh
- *         integer variable.
- * Tr(c) = the integer value of c, for any bit-vector constant c.
- * Tr((bvadd s t)) = Tr(s) + Tr(t) mod 2^k, where k is the bit width of
- *         s and t.
- * Similar transformations are done for bvmul, bvsub, bvudiv, bvurem, bvneg,
- *         bvnot, bvconcat, bvextract
- * Tr((_ zero_extend m) x) = Tr(x)
- * Tr((_ sign_extend m) x) = ite(msb(x)=0, x, 2^k*(2^m-1) + x))
- * explanation: if the msb is 0, this is the same as zero_extend,
- * which does not change the integer value.
- * If the msb is 1, then the result should correspond to
- * concat(1...1, x), with m 1's.
- * m 1's is 2^m-1, and multiplying it by x's width (k) moves it
- * to the front.
- *
- * Tr((bvand s t)) depends on the granularity, which is provided by the user
- * when enabling this preprocessing pass.
- * We divide s and t to blocks.
- * The size of each block is the granularity, and so the number of
- * blocks is:
- * bit width/granularity (rounded down).
- * We create an ITE that represents an arbitrary block,
- * and then create a sum by mutiplying each block by the
- * appropriate power of two.
- * More formally:
- * Let g denote the granularity.
- * Let k denote the bit width of s and t.
- * Let b denote floor(k/g) if k >= g, or just k otherwise.
- * Tr((bvand s t)) =
- * Sigma_{i=0}^{b-1}(bvand s[(i+1)*g, i*g] t[(i+1)*g, i*g])*2^(i*g)
- *
- * Similar transformations are done for bvor, bvxor, bvxnor, bvnand, bvnor.
- *
- * Tr((bvshl a b)) = ite(Tr(b) >= k, 0, Tr(a)*ITE), where k is the bit width of
- *         a and b, and ITE represents exponentiation up to k, that is:
- * ITE = ite(Tr(b)=0, 1, ite(Tr(b)=1), 2, ite(Tr(b)=2, 4, ...))
- * Similar transformations are done for bvlshr.
- *
- * Tr(a=b) = Tr(a)=Tr(b)
- * Tr((bvult a b)) = Tr(a) < Tr(b)
- * Similar transformations are done for bvule, bvugt, and bvuge.
- *
- * Bit-vector operators that are not listed above are either eliminated using
- * the function eliminationPass, or are not supported.
- *
+ * The bv-to-int preprocessing pass.
  */
 
-#include "cvc5_private.h"
-
 #ifndef __CVC5__PREPROCESSING__PASSES__BV_TO_INT_H
 #define __CVC5__PREPROCESSING__PASSES__BV_TO_INT_H
 
 #include "context/cdhashmap.h"
-#include "context/cdhashset.h"
+#include "context/cdo.h"
+#include "context/context.h"
 #include "preprocessing/preprocessing_pass.h"
-#include "theory/arith/nl/iand_utils.h"
+#include "preprocessing/preprocessing_pass_context.h"
+#include "theory/bv/int_blaster.h"
 
 namespace cvc5 {
 namespace preprocessing {
@@ -88,200 +38,15 @@ class BVToInt : public PreprocessingPass
  protected:
   PreprocessingPassResult applyInternal(
       AssertionPipeline* assertionsToPreprocess) override;
-  /**
-   * A generic function that creates a logical shift node (either left or
-   * right). a << b gets translated to a * 2^b mod 2^k, where k is the bit
-   * width. a >> b gets translated to a div 2^b mod 2^k, where k is the bit
-   * width. The exponentiation operation is translated to an ite for possible
-   * values of the exponent, from 0 to k-1.
-   * If the right operand of the shift is greater than k-1,
-   * the result is 0.
-   * @param children the two operands for the shift
-   * @param bvsize the original bit widths of the operands
-   *                (before translation to integers)
-   * @param  isLeftShift true iff the desired operation is a left shift.
-   * @return a node representing the shift.
-   *
-   */
-  Node createShiftNode(std::vector<Node> children,
-                       uint64_t bvsize,
-                       bool isLeftShift);
-
-  /**
-   * Returns a node that represents the bitwise negation of n.
-   */
-  Node createBVNotNode(Node n, uint64_t bvsize);
-
-  /**
-   * The result is an integer term and is computed
-   * according to the translation specified above.
-   * @param n is a bit-vector term or formula to be translated.
-   * @return integer node that corresponds to n.
-   */
-  Node bvToInt(Node n);
-
-  /**
-   * Whenever we introduce an integer variable that represents a bit-vector
-   * variable, we need to guard the range of the newly introduced variable.
-   * For bit width k, the constraint is 0 <= newVar < 2^k.
-   * @param newVar the newly introduced integer variable
-   * @param k the bit width of the original bit-vector variable.
-   * @return a node representing the range constraint.
-   */
-  Node mkRangeConstraint(Node newVar, uint64_t k);
-
-  /**
-   * In the translation to integers, it is convenient to assume that certain
-   * bit-vector operators do not occur in the original formula (e.g., repeat).
-   * This function eliminates all these operators.
-   */
-  Node eliminationPass(Node n);
-
-  /**
-   * Some bit-vector operators (e.g., bvadd, bvand) are binary, but allow more
-   * than two arguments as a syntactic sugar.
-   * For example, we can have a node for (bvand x y z), 
-   * that represents (bvand (x (bvand y z))).
-   * This function makes all such operators strictly binary.
-   */
-  Node makeBinary(Node n);
-
-  /**
-   * @param k A non-negative integer
-   * @return A node that represents the constant 2^k
-   */
-  Node pow2(uint64_t k);
-
-  /**
-   * @param k A positive integer k
-   * @return A node that represent the constant 2^k-1
-   * For example, if k is 4, the result is a node representing the
-   * constant 15.
-   */
-  Node maxInt(uint64_t k);
-
-  /**
-   * @param n A node representing an integer term
-   * @param exponent A non-negative integer
-   * @return A node representing (n mod (2^exponent))
-   */
-  Node modpow2(Node n, uint64_t exponent);
-
-  bool childrenTypesChanged(Node n);
-
-  /**
-   * Add the range assertions collected in d_rangeAssertions
-   * (using mkRangeConstraint) to the assertion pipeline.
-   * If there are no range constraints, do nothing.
-   * If there is a single range constraint, add it to the pipeline.
-   * Otherwise, add all of them as a single conjunction
-   */
-  void addFinalizeRangeAssertions(AssertionPipeline* assertionsToPreprocess);
-
-  /**
-   * @param quantifiedNode a node whose main operator is forall/exists.
-   * @return a node opbtained from quantifiedNode by:
-   * 1. Replacing all bound BV variables by new bound integer variables.
-   * 2. Add range constraints for the new variables, induced by the original
-   * bit-width. These range constraints are added with "AND" in case of exists
-   * and with "IMPLIES" in case of forall.
-   */
-  Node translateQuantifiedFormula(Node quantifiedNode);
-
-  /**
-   * Reconstructs a node whose main operator cannot be
-   * translated to integers.
-   * Reconstruction is done by casting to integers/bit-vectors
-   * as needed.
-   * For example, if node is (select A x) where A
-   * is a bit-vector array, we do not change A to be
-   * an integer array, even though x was translated
-   * to integers.
-   * In this case we cast x to (bv2nat x) during
-   * the reconstruction.
-   *
-   * @param originalNode the node that we are reconstructing
-   * @param resultType the desired type for the reconstruction
-   * @param translated_children the children of originalNode
-   *        after their translation to integers.
-   * @return A node with originalNode's operator that has type resultType.
-   */
-  Node reconstructNode(Node originalNode,
-                       TypeNode resultType,
-                       const std::vector<Node>& translated_children);
-
-  /**
-   * A useful utility function.
-   * if n is an integer and tn is bit-vector,
-   * applies the IntToBitVector operator on n.
-   * if n is a vit-vector and tn is integer,
-   * applies BitVector_TO_NAT operator.
-   * Otherwise, keeps n intact.
-   */
-  Node castToType(Node n, TypeNode tn);
-
-  /**
-   * When a UF f is translated to a UF g,
-   * we add a define-fun command to the smt-engine
-   * to relate between f and g.
-   * We do the same when f and g are just variables.
-   * This is useful, for example, when asking
-   * for a model-value of a term that includes the
-   * original UF f.
-   * @param bvUF the original function or variable
-   * @param intUF the translated function or variable
-   */
-  void defineBVUFAsIntUF(Node bvUF, Node intUF);
-
-  /**
-   * @param bvUF is an uninterpreted function symbol from the original formula
-   * @return a fresh uninterpreted function symbol, obtained from bvUF
-     by replacing every argument of type BV to an argument of type Integer,
-     and the return type becomes integer in case it was BV.
-   */
-  Node translateFunctionSymbol(Node bvUF);
-
-  /**
-   * Performs the actual translation to integers for nodes
-   * that have children.
-   */
-  Node translateWithChildren(Node original,
-                             const std::vector<Node>& translated_children);
-
-  /**
-   * Performs the actual translation to integers for nodes
-   * that don't have children (variables, constants, uninterpreted function
-   * symbols).
-   */
-  Node translateNoChildren(Node original);
-
-  /**
-   * Caches for the different functions
-   */
-  CDNodeMap d_binarizeCache;
-  CDNodeMap d_eliminationCache;
-  CDNodeMap d_rebuildCache;
-  CDNodeMap d_bvToIntCache;
 
-  /**
-   * Node manager that is used throughout the pass
-   */
-  NodeManager* d_nm;
+  // Add the lemmas in `additionalConstraints` to the assertions pipeline.
+  void addFinalizeAssertions(AssertionPipeline* assertionsToPreprocess,
+                             const std::vector<Node>& additionalConstraints);
 
-  /**
-   * A set of constraints of the form 0 <= x < 2^k
-   * These are added for every new integer variable that we introduce.
-   */
-  context::CDHashSet<Node> d_rangeAssertions;
+  // include the skolem map as substitutions
+  void addSkolemDefinitions(const std::map<Node, Node>& skolems);
 
-  /**
-   * Useful constants
-   */
-  Node d_zero;
-  Node d_one;
-  
-  /** helper class for handeling bvand translation */
-  theory::arith::nl::IAndUtils d_iandUtils;
+  IntBlaster d_intBlaster;
 };
 
 }  // namespace passes
index f5e7b427e90a1723d7b99d41aac08115f8b04f4a..4c01f25f3e3c759d1ffef7c09a8282d18833c66d 100644 (file)
@@ -402,11 +402,11 @@ RewriteResponse ArithRewriter::postRewritePow2(TNode t)
 RewriteResponse ArithRewriter::postRewriteIAnd(TNode t)
 {
   Assert(t.getKind() == kind::IAND);
+  size_t bsize = t.getOperator().getConst<IntAnd>().d_size;
   NodeManager* nm = NodeManager::currentNM();
   // if constant, we eliminate
   if (t[0].isConst() && t[1].isConst())
   {
-    size_t bsize = t.getOperator().getConst<IntAnd>().d_size;
     Node iToBvop = nm->mkConst(IntToBitVector(bsize));
     Node arg1 = nm->mkNode(kind::INT_TO_BITVECTOR, iToBvop, t[0]);
     Node arg2 = nm->mkNode(kind::INT_TO_BITVECTOR, iToBvop, t[1]);
@@ -437,6 +437,11 @@ RewriteResponse ArithRewriter::postRewriteIAnd(TNode t)
       // ((_ iand k) 0 y) ---> 0
       return RewriteResponse(REWRITE_DONE, t[i]);
     }
+    if (t[i].getConst<Rational>().getNumerator() == Integer(2).pow(bsize) - 1)
+    {
+      // ((_ iand k) 111...1 y) ---> y
+      return RewriteResponse(REWRITE_DONE, t[i == 0 ? 1 : 0]);
+    }
   }
   return RewriteResponse(REWRITE_DONE, t);
 }
index 90a9c5f784964578ce49eb97e4f97035a4b53499..92ecaf4e8de22cf4c8981537fa7b325c65a216e3 100644 (file)
@@ -280,8 +280,8 @@ Node IAndSolver::bitwiseLemma(Node i)
   // compare each bit to bvI
   Node cond;
   Node bitIAnd;
-  unsigned high_bit;
-  for (unsigned j = 0; j < bvsize; j += granularity)
+  uint64_t high_bit;
+  for (uint64_t j = 0; j < bvsize; j += granularity)
   {
     high_bit = j + granularity - 1;
     // don't let high_bit pass bvsize
index 692fdc1b39bbfb20de1dd32ecf2b343c44cf5945..60bb0a9bc7d92f211f2bdc44c48b10a3369fce7f 100644 (file)
@@ -48,8 +48,7 @@ Rational intpow2(uint64_t b) { return Rational(Integer(2).pow(b), Integer(1)); }
 
 IntBlaster::IntBlaster(Env& env,
                        options::SolveBVAsIntMode mode,
-                       uint64_t granularity,
-                       bool introduceFreshIntVars)
+                       uint64_t granularity)
     : EnvObj(env),
       d_binarizeCache(userContext()),
       d_intblastCache(userContext()),
@@ -57,8 +56,7 @@ IntBlaster::IntBlaster(Env& env,
       d_bitwiseAssertions(userContext()),
       d_mode(mode),
       d_granularity(granularity),
-      d_context(userContext()),
-      d_introduceFreshIntVars(introduceFreshIntVars)
+      d_context(userContext())
 {
   d_nm = NodeManager::currentNM();
   d_zero = d_nm->mkConst(CONST_RATIONAL, Rational(0));
@@ -678,38 +676,18 @@ Node IntBlaster::translateNoChildren(Node original,
       }
       else
       {
-        // original is a bit-vector variable (symbolic constant).
-        // Either we translate it to a fresh integer variable,
-        // or we translate it to (bv2nat original).
-        // In the former case, we must include range lemmas, while in the
-        // latter we don't.
-        // This is determined by the option bv-to-int-fresh-vars.
-        // The variables intCast and bvCast are used for models:
-        // even if we introduce a fresh variable,
-        // it is associated with intCast (which is (bv2nat original)).
-        // bvCast is either ( (_ nat2bv k) original) or just original.
         Node intCast = castToType(original, d_nm->integerType());
         Node bvCast;
-        if (d_introduceFreshIntVars)
-        {
-          // we introduce a fresh variable, add range constraints, and save the
-          // connection between original and the new variable via intCast
-          translation = d_nm->getSkolemManager()->mkPurifySkolem(
-              intCast,
-              "__intblast__var",
-              "Variable introduced in intblasting for " + original.toString());
-          uint64_t bvsize = original.getType().getBitVectorSize();
-          addRangeConstraint(translation, bvsize, lemmas);
-          // put new definition of old variable in skolems
-          bvCast = castToType(translation, original.getType());
-        }
-        else
-        {
-          // we just translate original to (bv2nat original)
-          translation = intCast;
-          // no need to do any casting back to bit-vector in this case.
-          bvCast = original;
-        }
+        // we introduce a fresh variable, add range constraints, and save the
+        // connection between original and the new variable via intCast
+        translation = d_nm->getSkolemManager()->mkPurifySkolem(
+            intCast,
+            "__intblast__var",
+            "Variable introduced in intblasting for " + original.toString());
+        uint64_t bvsize = original.getType().getBitVectorSize();
+        addRangeConstraint(translation, bvsize, lemmas);
+        // put new definition of old variable in skolems
+        bvCast = castToType(translation, original.getType());
 
         // add bvCast to skolems if it is not already there.
         if (skolems.find(original) == skolems.end())
index ed8ed10c652a29a54b072f5268817563c9aad21f..fb7291f6e79720a9624c49f53b60a4837a3239aa 100644 (file)
@@ -101,14 +101,12 @@ class IntBlaster : protected EnvObj
    * @param context user context
    * @param mode bv-to-int translation mode
    * @param granularity bv-to-int translation granularity
-   * @param introduceFreshIntVars determines whether bit-vector variables are
    * translated to integer variables, or are directly casted using `bv2nat`
    * operator. not purely bit-vector nodes.
    */
   IntBlaster(Env& env,
              options::SolveBVAsIntMode mode,
-             uint64_t granluarity = 1,
-             bool introduceFreshIntVars = true);
+             uint64_t granluarity = 1);
 
   ~IntBlaster();
 
@@ -371,11 +369,6 @@ class IntBlaster : protected EnvObj
   /** an SolverEngine for context */
   context::Context* d_context;
 
-  /** true iff the translator should introduce
-   * fresh integer variables for bit-vector variables.
-   * Otherwise, we introduce a nat2bv term.
-   */
-  bool d_introduceFreshIntVars;
 };
 
 }  // namespace cvc5
index 496a625ee9e0c6008135b52fd75311ee9aa2d3b6..a8ac27a8128ba3534a7810e2a6b19cef9725f6f3 100644 (file)
@@ -29,84 +29,6 @@ namespace cvc5 {
 namespace theory {
 namespace bv {
 
-/*
- * This rewrite is not meant to be used by the BV rewriter.
- * It is specifically designed for the bv-to-int preprocessing pass.
- * Based on Hacker's Delight section 2-2 equation a:
- * -x = ~x+1
- */
-template <>
-inline bool RewriteRule<NegEliminate>::applies(TNode node)
-{
-  return (node.getKind() == kind::BITVECTOR_NEG);
-}
-
-template <>
-inline Node RewriteRule<NegEliminate>::apply(TNode node)
-{
-  Debug("bv-rewrite") << "RewriteRule<NegEliminate>(" << node << ")"
-                      << std::endl;
-  NodeManager* nm = NodeManager::currentNM();
-  TNode a = node[0];
-  unsigned size = utils::getSize(a);
-  Node one = utils::mkOne(size);
-  Node nota = nm->mkNode(kind::BITVECTOR_NOT, a);
-  Node bvadd = nm->mkNode(kind::BITVECTOR_ADD, nota, one);
-  return bvadd;
-}
-
-/*
- * This rewrite is not meant to be used by the BV rewriter.
- * It is specifically designed for the bv-to-int preprocessing pass.
- * Based on Hacker's Delight section 2-2 equation h:
- * x+y = x|y + x&y
- */
-template <>
-inline bool RewriteRule<OrEliminate>::applies(TNode node)
-{
-  return (node.getKind() == kind::BITVECTOR_OR);
-}
-
-template <>
-inline Node RewriteRule<OrEliminate>::apply(TNode node)
-{
-  Debug("bv-rewrite") << "RewriteRule<OrEliminate>(" << node << ")"
-                      << std::endl;
-  NodeManager* nm = NodeManager::currentNM();
-  TNode a = node[0];
-  TNode b = node[1];
-  Node bvadd = nm->mkNode(kind::BITVECTOR_ADD, a, b);
-  Node bvand = nm->mkNode(kind::BITVECTOR_AND, a, b);
-  Node result =
-      nm->mkNode(kind::BITVECTOR_SUB, bvadd, bvand);
-  return result;
-}
-
-/*
- * This rewrite is not meant to be used by the BV rewriter.
- * It is specifically designed for the bv-to-int preprocessing pass.
- * Based on Hacker's Delight section 2-2 equation n:
- * x xor y = x|y - x&y
- */
-template <>
-inline bool RewriteRule<XorEliminate>::applies(TNode node)
-{
-  return (node.getKind() == kind::BITVECTOR_XOR);
-}
-
-template <>
-inline Node RewriteRule<XorEliminate>::apply(TNode node)
-{
-  Debug("bv-rewrite") << "RewriteRule<XorEliminate>(" << node << ")"
-                      << std::endl;
-  NodeManager* nm = NodeManager::currentNM();
-  TNode a = node[0];
-  TNode b = node[1];
-  Node bvor = nm->mkNode(kind::BITVECTOR_OR, a, b);
-  Node bvand = nm->mkNode(kind::BITVECTOR_AND, a, b);
-  Node result = nm->mkNode(kind::BITVECTOR_SUB, bvor, bvand);
-  return result;
-}
 
 template <>
 inline bool RewriteRule<UgtEliminate>::applies(TNode node)
index eae57f3b956925cd943b2047c73e3667bdfba471..929c5bef2b885753a95572fb2400e0604b045ad4 100644 (file)
@@ -54,3 +54,5 @@ cvc5_add_api_test(issue4889)
 cvc5_add_api_test(issue6111)
 cvc5_add_api_test(proj-issue306)
 cvc5_add_api_test(proj-issue334)
+cvc5_add_api_test(proj-issue344)
+cvc5_add_api_test(proj-issue345)
diff --git a/test/api/cpp/proj-issue344.cpp b/test/api/cpp/proj-issue344.cpp
new file mode 100644 (file)
index 0000000..5f48670
--- /dev/null
@@ -0,0 +1,33 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ *   Yoni Zohar
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved.  See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Test for project issue #345
+ *
+ */
+
+
+#include "api/cpp/cvc5.h"
+#include <cassert>
+
+using namespace cvc5::api;
+
+int main(void)
+{
+  Solver slv;
+  slv.setOption("solve-bv-as-int", "iand");
+  Sort s12 = slv.getIntegerSort();
+  Term t13 = slv.mkConst(s12, "_x11");
+  Term t25 = slv.mkTerm(slv.mkOp(Kind::INT_TO_BITVECTOR, 4124876294), {t13});
+  Term t66 = slv.mkTerm(Kind::BITVECTOR_ULTBV, {t25, t25});
+  Term t154 = slv.mkTerm(Kind::BITVECTOR_SGT, {t66, t66});
+  slv.checkEntailed({t154, t154, t154, t154});
+}
diff --git a/test/api/cpp/proj-issue345.cpp b/test/api/cpp/proj-issue345.cpp
new file mode 100644 (file)
index 0000000..c33e9e5
--- /dev/null
@@ -0,0 +1,34 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ *   Yoni Zohar
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved.  See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Test for project issue #345
+ *
+ */
+
+
+#include "api/cpp/cvc5.h"
+#include <cassert>
+
+using namespace cvc5::api;
+
+int main(void)
+{
+  Solver slv;
+  slv.setOption("solve-bv-as-int", "iand");
+  Sort s12 = slv.getIntegerSort();
+  Term t13 = slv.mkConst(s12, "_x11");
+  Term t25 = slv.mkTerm(slv.mkOp(Kind::INT_TO_BITVECTOR, 4124876294), {t13});
+  Term t66 = slv.mkTerm(Kind::BITVECTOR_SLTBV, {t25, t25});
+  Term t154 = slv.mkTerm(Kind::BITVECTOR_SGT, {t66, t66});
+  slv.checkEntailed({t154, t154, t154, t154});
+}
+
index 6b8debc880cd3abf576899f4d424f3a3c266596c..3be63c46db295754a3b6face0e5bb44d9745ec3e 100644 (file)
@@ -257,6 +257,7 @@ set(regress_0_tests
   regress0/bv/bv_to_int_bvuf_to_intuf.smt2
   regress0/bv/bv_to_int_bvuf_to_intuf_sorts.smt2
   regress0/bv/bv_to_int_elim_err.smt2
+  regress0/bv/bv_to_int_int1.smt2
   regress0/bv/bv_to_int_zext.smt2
   regress0/bv/bvcomp.cvc.smt2
   regress0/bv/bvmul-pow2-only.smt2
@@ -434,6 +435,7 @@ set(regress_0_tests
   regress0/bv/mult-pow2-negative.smt2
   regress0/bv/pr4993-bvugt-bvurem-a.smt2
   regress0/bv/pr4993-bvugt-bvurem-b.smt2
+  regress0/bv/proj-issue343.smt2
   regress0/bv/reset-assertions-assert-input.smt2
   regress0/bv/sizecheck.cvc.smt2
   regress0/bv/smtcompbug.smtv1.smt2
@@ -2627,6 +2629,7 @@ set(regress_2_tests
   regress2/bv_to_int_mask_array_2.smt2
   regress2/bv_to_int_mask_array_3.smt2
   regress2/bv_to_int_shifts.smt2
+  regress2/bv_to_int_quantifiers_bvand.smt2
   regress2/error1.smtv1.smt2
   regress2/fp/issue7056.smt2
   regress2/fuzz_2.smtv1.smt2
index 3908cdb162801e8213aae257ba0cd2d598e68737..eb8e7580380e257aa048d87e416bdb67815ef8b5 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; EXPECT: unsat
 (set-logic QF_BV)
 (declare-fun x () (_ BitVec 4))
index 91e0c45fd9df805524a4f5e162c68da32aa98e72..eced6e0e96a549078a7b36897c888d3f4765c2e4 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores
 ; EXPECT: unsat
 (set-logic QF_BV)
 (declare-fun T4_180 () (_ BitVec 32))
index 3e545ef03372c884ec91f4a8b9d946ba57133924..45d539f04aa07c8452f7c95b055f744a3bc39364 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; EXPECT: sat
 (set-logic QF_UFBV)
 (declare-fun a () (_ BitVec 4))
index 0a0ec7b2013d68e3191fe2aebeb3a8959d7dfaea..ae77380dd1ca46e4487366c202858b88b03cd0b7 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; EXPECT: sat
 (set-logic QF_UFBV)
 (declare-sort S 0)
index 01ee5dad8b24757816b7715da1c88d4d3c411bf4..cb7eefbb20415ac94e4dcbb3c1d392c8d7be1458 100644 (file)
@@ -1,4 +1,5 @@
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1  
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; EXPECT: sat
 (set-logic QF_BV)
 (declare-fun _substvar_183_ () (_ BitVec 32))
diff --git a/test/regress/regress0/bv/bv_to_int_int1.smt2 b/test/regress/regress0/bv/bv_to_int_int1.smt2
new file mode 100644 (file)
index 0000000..3295d34
--- /dev/null
@@ -0,0 +1,11 @@
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; EXPECT: sat
+(set-logic QF_ALL)
+(declare-fun x () (_ BitVec 4))
+(declare-fun y () (_ BitVec 4))
+(declare-fun z () Int)
+(declare-fun w () Int)
+(assert (= x (_ bv3 4)))
+(assert (= y (_ bv3 4)))
+(assert (> z w))
+(check-sat)
index 8bf4a825d07692048407e70860941386b83c5f97..4fd6109f479c9f6117e7c1eda5d7e4f21312ba44 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; EXPECT: unsat
 (set-logic QF_BV)
 (declare-fun T1_31078 () (_ BitVec 8))
diff --git a/test/regress/regress0/bv/proj-issue343.smt2 b/test/regress/regress0/bv/proj-issue343.smt2
new file mode 100644 (file)
index 0000000..6d2971a
--- /dev/null
@@ -0,0 +1,7 @@
+; EXPECT: sat
+; COMMAND-LINE: --no-check-models
+(set-logic ALL)
+(set-option :solve-bv-as-int bv)
+(declare-const _x8 Real)
+(assert (distinct real.pi _x8))
+(check-sat)
index 424e95b27b9550f18ad227a77d4339970fbd1e81..b9c27c6b893ea54d0c1205d11c85f4695db48ddd 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; EXPECT: sat
 (set-logic QF_BV)
 (declare-fun a () (_ BitVec 8))
index 0c67685464608080ecc0acd15f562e90672c7d66..1f5df2c3183f4c7f1d08c071b65d86ba8cb9ddb4 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; EXPECT: unsat
 (set-logic QF_BV)
 (declare-fun a () (_ BitVec 8))
index 23624e12c3aa6a0f273621c928c20ee9f4c0427b..4dc37a94c89edee3290d156347b8d3fd21eb328d 100644 (file)
@@ -1,8 +1,10 @@
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=5
-; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value
-; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum
-; COMMAND-LINE: --solve-bv-as-int=bv
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=5 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=5 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=bv --no-check-unsat-cores
 ; EXPECT: unsat
 (set-logic QF_BV)
 (declare-fun s () (_ BitVec 4))
index 232959f33322404d1c1ae8e8bfc72d50f9494120..bf6f2cfc45fb28995e36116098d383a2b5673b6e 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; EXPECT: sat
 (set-logic QF_BV)
 (declare-fun a () (_ BitVec 8))
index babf9af3238c738ea97a56f9265fab23e7fd6663..2ecd0fe6cd80df6822263182dcd5151228eaa227 100644 (file)
@@ -1,4 +1,5 @@
-;COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-produce-unsat-cores
+;COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-check-unsat-cores
+;COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores
 ;EXPECT: unsat
 (set-logic QF_UFBV)
 (declare-fun z$n0s32 () (_ BitVec 32))
index 4b22c8ed80e6bc3da3f2456000dd3d33a1d571bf..28fb86f765ab5243f86488b700a717a206d1e7ec 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --incremental --solve-bv-as-int=sum
+; COMMAND-LINE: --incremental --solve-bv-as-int=bitwise
 ; COMMAND-LINE: --incremental --solve-bv-as-int=iand
 ; COMMAND-LINE: --incremental --solve-bv-as-int=bv
 ; EXPECT sat
index 3b55c035d47a17258f48d12d1304f13257b544f5..c1213809163e2fee54256259942732f7a89c6a75 100644 (file)
@@ -1,5 +1,6 @@
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
-; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value --no-check-unsat-cores
 ; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum --no-check-unsat-cores
 ; COMMAND-LINE: --solve-bv-as-int=bv --no-check-unsat-cores
 ; EXPECT: unsat
index edcc14149b8f22e88259b8bc84d199c915cfb1d1..17a113f85d3fc96fec440a5fe5fb960b79eb27cd 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value
 ; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum
 ; COMMAND-LINE: --solve-bv-as-int=bv
index 74e5ca95a46f21430b611078558ad63669aad4ce..2b411209d5e7f3649a7a4caa8729bc8f05948abd 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; EXPECT: sat
 (set-logic ALL)
 (declare-fun A () (Array (_ BitVec 4) (_ BitVec 4)))
diff --git a/test/regress/regress2/bv_to_int_quantifiers_bvand.smt2 b/test/regress/regress2/bv_to_int_quantifiers_bvand.smt2
new file mode 100644 (file)
index 0000000..d454ad6
--- /dev/null
@@ -0,0 +1,9 @@
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores
+; EXPECT: (error "Error in option parsing: --solve-bv-as-int=bitwise does not support quantifiers")
+; EXIT: 1
+(set-logic BV)
+(declare-const x (_ BitVec 8))
+(assert (forall ((y (_ BitVec 8)))
+               (distinct #b00000000
+                         (bvand x y))))
+(check-sat)
index bcc31c38c4534b21df16a4502f350c5f61a54c8c..173f1a552e928f7cf835fd2a207308d13921cd37 100644 (file)
@@ -1,4 +1,5 @@
 ; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
 ; EXPECT: sat
 (set-logic QF_BV)
 (declare-fun s () (_ BitVec 4))
index 2c728417d27dc33d26e0371da8d5fabd479e7d19..8ae10a04f95f48d42af9b5ca41aca0600b0cb2b4 100644 (file)
@@ -1,5 +1,7 @@
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1  
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=2  
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1   --no-check-unsat-cores --no-check-proofs
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1   --no-check-unsat-cores --no-check-proofs
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=2   --no-check-unsat-cores --no-check-proofs
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=2   --no-check-unsat-cores --no-check-proofs
 ; EXPECT: unsat
 (set-logic QF_BV)
 (declare-fun a () (_ BitVec 4))
index aeacda35e088e43f291283383df6d383a30f8a11..3a0320119b3fb275c17df38b1a295d0161492a48 100644 (file)
@@ -1,5 +1,6 @@
-; COMMAND-LINE:  --solve-bv-as-int=bv 
-; COMMAND-LINE:  --bvand-integer-granularity=1 --solve-bv-as-int=sum     
+; COMMAND-LINE:  --solve-bv-as-int=bv
+; COMMAND-LINE:  --bvand-integer-granularity=1 --solve-bv-as-int=sum
+; COMMAND-LINE:  --bvand-integer-granularity=1 --solve-bv-as-int=bitwise
 ; EXPECT: sat
 (set-logic QF_BV)
 (declare-fun _substvar_1171_ () (_ BitVec 32))
index c4988e3c6cac877c9bf14e2fc88a67db11e44b5e..3c50acc1cd94c697eb40b81c3b9225304982380a 100644 (file)
@@ -1,6 +1,6 @@
-; COMMAND-LINE:  --solve-bv-as-int=bv 
-; COMMAND-LINE:  --solve-bv-as-int=sum     
-; COMMAND-LINE:  --solve-bv-as-int=iand --iand-mode=sum    
+; COMMAND-LINE:  --solve-bv-as-int=bv
+; COMMAND-LINE:  --solve-bv-as-int=sum
+; COMMAND-LINE:  --solve-bv-as-int=iand --iand-mode=sum
 ; COMMAND-LINE:  --solve-bv-as-int=iand --iand-mode=bitwise
 ; COMMAND-LINE:  --solve-bv-as-int=iand --iand-mode=value
 ; EXPECT: unsat
index dd7e11a5097364b2992e7a7d9ada3451f9511c88..b37dc371d5f5dd1f54793780344728cc3e41b450 100644 (file)
@@ -1,5 +1,5 @@
 ; COMMAND-LINE:  --solve-bv-as-int=bv  --no-check-models
-; COMMAND-LINE:  --bvand-integer-granularity=1 --solve-bv-as-int=sum --full-saturate-quant --cegqi-all  --no-check-models  
+; COMMAND-LINE:  --bvand-integer-granularity=1 --solve-bv-as-int=sum --full-saturate-quant --cegqi-all  --no-check-models
 ;EXPECT: sat
 (set-logic BV)
 (assert (exists ((c__detect__main__1__i_36_C (_ BitVec 32))) (bvslt ((_ sign_extend 32) c__detect__main__1__i_36_C) (_ bv0 64))))
index 0412fdabb98c540c074de4175f72d02ce2de0ddb..e8238ecbba0e63cb8c57fdeced65a6fbbfb6bd85 100644 (file)
@@ -61,7 +61,7 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_constants)
   Env env(d_nodeManager, &opts);
   env.d_logic.setLogicString("QF_UFBV");
   env.d_logic.lock();
-  IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1, false);
+  IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1);
   Node result = intBlaster.translateNoChildren(bv7_4, lemmas, skolems);
   Node seven = d_nodeManager->mkConst(CONST_RATIONAL, Rational(7));
   ASSERT_EQ(seven, result);
@@ -86,7 +86,7 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_symbolic_constant)
   Env env(d_nodeManager, &opts);
   env.d_logic.setLogicString("QF_UFBV");
   env.d_logic.lock();
-  IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1, true);
+  IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1);
   Node result = intBlaster.translateNoChildren(bv, lemmas, skolems);
   ASSERT_TRUE(result.isVar() && result.getType().isInteger());
 
@@ -116,7 +116,7 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_uf)
   Env env(d_nodeManager, &opts);
   env.d_logic.setLogicString("QF_UFBV");
   env.d_logic.lock();
-  IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1, true);
+  IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1);
   Node result = intBlaster.translateNoChildren(f, lemmas, skolems);
   TypeNode resultType = result.getType();
   std::vector<TypeNode> resultDomain = resultType.getArgTypes();
@@ -143,7 +143,7 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_with_children)
   Env env(d_nodeManager, &opts);
   env.d_logic.setLogicString("QF_UFBV");
   env.d_logic.lock();
-  IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1, true);
+  IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1);
 
   // bit-vector variables
   TypeNode bvType = d_nodeManager->mkBitVectorType(4);
@@ -294,7 +294,7 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_bitwise)
   Env env(d_nodeManager, &opts);
   env.d_logic.setLogicString("QF_UFBV");
   env.d_logic.lock();
-  IntBlaster intBlaster(env, options::SolveBVAsIntMode::BITWISE, 1, true);
+  IntBlaster intBlaster(env, options::SolveBVAsIntMode::BITWISE, 1);
 
   // bit-vector variables
   TypeNode bvType = d_nodeManager->mkBitVectorType(4);