Add BV solver bitblast. (#5851)
authorMathias Preiner <mathias.preiner@gmail.com>
Wed, 3 Feb 2021 20:38:09 +0000 (12:38 -0800)
committerGitHub <noreply@github.com>
Wed, 3 Feb 2021 20:38:09 +0000 (12:38 -0800)
This PR adds a new bit-blasting BV solver, which can be enabled via --bv-solver=bitblast. The new bit-blast solver can be used instead of the lazy BV solver and currently supports CaDiCaL and CryptoMiniSat as SAT back end.

16 files changed:
src/CMakeLists.txt
src/options/bv_options.toml
src/options/options_handler.cpp
src/prop/cadical.cpp
src/prop/cadical.h
src/prop/cryptominisat.cpp
src/prop/cryptominisat.h
src/prop/sat_solver.h
src/smt/set_defaults.cpp
src/theory/bv/bitblast/bitblast_strategies_template.h
src/theory/bv/bitblast/simple_bitblaster.cpp
src/theory/bv/bitblast/simple_bitblaster.h
src/theory/bv/bv_solver_bitblast.cpp [new file with mode: 0644]
src/theory/bv/bv_solver_bitblast.h [new file with mode: 0644]
src/theory/bv/theory_bv.cpp
src/theory/bv/theory_bv.h

index 0929b66251ae29d84d6295e57a9218a18ab4f4cb..c5673a396e26ac7d0ec75e447f979b188e42e1ac 100644 (file)
@@ -525,6 +525,8 @@ libcvc4_add_sources(
   theory/bv/bv_quick_check.cpp
   theory/bv/bv_quick_check.h
   theory/bv/bv_solver.h
+  theory/bv/bv_solver_bitblast.cpp
+  theory/bv/bv_solver_bitblast.h
   theory/bv/bv_solver_lazy.cpp
   theory/bv/bv_solver_lazy.h
   theory/bv/bv_solver_simple.cpp
index 6a0ca913b8381d07e54191c7797e7038e0b7c123..acb010a2e234576e23a0d0334bdaef1e35b7be02 100644 (file)
@@ -236,6 +236,9 @@ header = "options/bv_options.h"
   default    = "LAZY"
   help       = "choose bit-vector solver, see --bv-solver=help"
   help_mode  = "Bit-vector solvers."
+[[option.mode.BITBLAST]]
+  name = "bitblast"
+  help = "Enables bitblasting solver."
 [[option.mode.LAZY]]
   name = "lazy"
   help = "Enables the lazy BV solver infrastructure."
index fe37e9363fc16df11a2bb25369441859979edda0..ac33d9c516c63e8559f9621387c1d66951048e54 100644 (file)
@@ -145,8 +145,9 @@ void OptionsHandler::checkBvSatSolver(std::string option, SatSolverMode m)
     throw OptionException(ss.str());
   }
 
-  if (m == SatSolverMode::CRYPTOMINISAT || m == SatSolverMode::CADICAL
-      || m == SatSolverMode::KISSAT)
+  if (options::bvSolver() != options::BVSolver::BITBLAST
+      && (m == SatSolverMode::CRYPTOMINISAT || m == SatSolverMode::CADICAL
+          || m == SatSolverMode::KISSAT))
   {
     if (options::bitblastMode() == options::BitblastMode::LAZY
         && options::bitblastMode.wasSetByUser())
index 6410552ba1b34b14830232c32bef64872b6941f3..b3563bf28adbdbff05c20f42bb963ef8a5b51a1d 100644 (file)
@@ -111,6 +111,7 @@ SatVariable CadicalSolver::falseVar() { return d_false; }
 
 SatValue CadicalSolver::solve()
 {
+  d_assumptions.clear();
   TimerStat::CodeTimer codeTimer(d_statistics.d_solveTime);
   SatValue res = toSatValue(d_solver->solve());
   d_okay = (res == SAT_VALUE_TRUE);
@@ -125,10 +126,12 @@ SatValue CadicalSolver::solve(long unsigned int&)
 
 SatValue CadicalSolver::solve(const std::vector<SatLiteral>& assumptions)
 {
+  d_assumptions.clear();
   TimerStat::CodeTimer codeTimer(d_statistics.d_solveTime);
   for (const SatLiteral& lit : assumptions)
   {
     d_solver->assume(toCadicalLit(lit));
+    d_assumptions.push_back(lit);
   }
   SatValue res = toSatValue(d_solver->solve());
   d_okay = (res == SAT_VALUE_TRUE);
@@ -136,6 +139,17 @@ SatValue CadicalSolver::solve(const std::vector<SatLiteral>& assumptions)
   return res;
 }
 
+void CadicalSolver::getUnsatAssumptions(std::vector<SatLiteral>& assumptions)
+{
+  for (const SatLiteral& lit : d_assumptions)
+  {
+    if (d_solver->failed(toCadicalLit(lit)))
+    {
+      assumptions.push_back(lit);
+    }
+  }
+}
+
 void CadicalSolver::interrupt() { d_solver->terminate(); }
 
 SatValue CadicalSolver::value(SatLiteral l)
index bb7b7aa9f1140b85403c13ef1de37532a70a90af..6a7258091ba40cde333a62daed0914b5adf03566 100644 (file)
@@ -50,6 +50,7 @@ class CadicalSolver : public SatSolver
   SatValue solve() override;
   SatValue solve(long unsigned int&) override;
   SatValue solve(const std::vector<SatLiteral>& assumptions) override;
+  void getUnsatAssumptions(std::vector<SatLiteral>& assumptions) override;
 
   void interrupt() override;
 
@@ -74,6 +75,11 @@ class CadicalSolver : public SatSolver
   void init();
 
   std::unique_ptr<CaDiCaL::Solver> d_solver;
+  /**
+   * Stores the current set of assumptions provided via solve() and is used to
+   * query the solver if a given assumption is false.
+   */
+  std::vector<SatLiteral> d_assumptions;
 
   unsigned d_nextVarIdx;
   bool d_okay;
index 1072003d2f6d90bd1705749915b05c8e458adc75..d375388efab2b3ae473dde669911ddf224101f9b 100644 (file)
@@ -39,6 +39,15 @@ CMSat::Lit toInternalLit(SatLiteral lit)
   return CMSat::Lit(lit.getSatVariable(), lit.isNegated());
 }
 
+SatLiteral toSatLiteral(CMSat::Lit lit)
+{
+  if (lit == CMSat::lit_Undef)
+  {
+    return undefSatLiteral;
+  }
+  return SatLiteral(lit.var(), lit.sign());
+}
+
 SatValue toSatLiteralValue(CMSat::lbool res)
 {
   if (res == CMSat::l_True) return SAT_VALUE_TRUE;
@@ -181,6 +190,15 @@ SatValue CryptoMinisatSolver::solve(const std::vector<SatLiteral>& assumptions)
   return toSatLiteralValue(d_solver->solve(&assumpts));
 }
 
+void CryptoMinisatSolver::getUnsatAssumptions(
+    std::vector<SatLiteral>& assumptions)
+{
+  for (const CMSat::Lit& lit : d_solver->get_conflict())
+  {
+    assumptions.push_back(toSatLiteral(~lit));
+  }
+}
+
 SatValue CryptoMinisatSolver::value(SatLiteral l){
   const std::vector<CMSat::lbool> model = d_solver->get_model();
   CMSatVar var = l.getSatVariable();
index 8861daf6133feba26750bc39ab067618cc82c723..eebe4de29d02080e26b14570bb6573166a21d61d 100644 (file)
@@ -61,6 +61,7 @@ class CryptoMinisatSolver : public SatSolver
   SatValue solve() override;
   SatValue solve(long unsigned int&) override;
   SatValue solve(const std::vector<SatLiteral>& assumptions) override;
+  void getUnsatAssumptions(std::vector<SatLiteral>& assumptions) override;
 
   bool ok() const override;
   SatValue value(SatLiteral l) override;
index 10ee843df6118c59ddfa0020d2017443f795a872..896233f413bf31102f7a773a0ae3d5b98213df9e 100644 (file)
@@ -96,6 +96,19 @@ public:
   /** Check if the solver is in an inconsistent state */
   virtual bool ok() const = 0;
 
+  /**
+   * Get list of unsatisfiable assumptions.
+   *
+   * The returned assumptions are a subset of the assumptions provided to
+   * the solve method.
+   * Can only be called if satisfiability check under assumptions was used and
+   * if it returned SAT_VALUE_FALSE.
+   */
+  virtual void getUnsatAssumptions(std::vector<SatLiteral>& unsat_assumptions)
+  {
+    Unimplemented() << "getUnsatAssumptions not implemented";
+  }
+
 };/* class SatSolver */
 
 
index 26f5745ca5ed720c5d2ac9ef78ded5cbf3b16bbe..cb4c99a2e3a6591ab1fec381317daed8ce98d063 100644 (file)
@@ -117,11 +117,16 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
           "Incremental eager bit-blasting is currently "
           "only supported for QF_BV. Try --bitblast=lazy.");
     }
+
+    // Force lazy solver since we don't handle EAGER_ATOMS in the
+    // BVSolver::BITBLAST solver.
+    options::bvSolver.set(options::BVSolver::LAZY);
   }
 
-  /* BVSolver::SIMPLE does not natively support int2bv and nat2bv, they need to
-   * to be eliminated eagerly. */
-  if (options::bvSolver() == options::BVSolver::SIMPLE)
+  /* Only BVSolver::LAZY natively supports int2bv and nat2bv, for other solvers
+   * we need to eagerly eliminate the operators. */
+  if (options::bvSolver() == options::BVSolver::SIMPLE
+      || options::bvSolver() == options::BVSolver::BITBLAST)
   {
     options::bvLazyReduceExtf.set(false);
     options::bvLazyRewriteExtf.set(false);
index a4e1757e289c4b8a4d02c7af446cb95d9ac3bc9c..8bab969c50d342cb9a85817f2062932f43f7a81b 100644 (file)
@@ -611,11 +611,11 @@ void DefaultShlBB(TNode node, std::vector<T>& res, TBitblaster<T>* bb)
   unsigned size = utils::getSize(node);
   unsigned log2_size = std::ceil(log2((double)size));
   Node a_size = utils::mkConst(size, size);
-  Node b_ult_a_size_node = Rewriter::rewrite(
-      NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT, node[1], a_size));
-  // ensure that the inequality is bit-blasted
-  bb->bbAtom(b_ult_a_size_node);
-  T b_ult_a_size = bb->getBBAtom(b_ult_a_size_node);
+
+  std::vector<T> a_size_bits;
+  DefaultConstBB(a_size, a_size_bits, bb);
+  T b_ult_a_size = uLessThanBB(b, a_size_bits, false);
+
   std::vector<T> prev_res;
   res = a;
   // we only need to look at the bits bellow log2_a_size
@@ -669,11 +669,11 @@ void DefaultLshrBB(TNode node, std::vector<T>& res, TBitblaster<T>* bb)
   unsigned size = utils::getSize(node);
   unsigned log2_size = std::ceil(log2((double)size));
   Node a_size = utils::mkConst(size, size);
-  Node b_ult_a_size_node = Rewriter::rewrite(
-      NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT, node[1], a_size));
-  // ensure that the inequality is bit-blasted
-  bb->bbAtom(b_ult_a_size_node);
-  T b_ult_a_size = bb->getBBAtom(b_ult_a_size_node);
+
+  std::vector<T> a_size_bits;
+  DefaultConstBB(a_size, a_size_bits, bb);
+  T b_ult_a_size = uLessThanBB(b, a_size_bits, false);
+
   res = a;
   std::vector<T> prev_res;
 
@@ -727,11 +727,10 @@ void DefaultAshrBB(TNode node, std::vector<T>& res, TBitblaster<T>* bb)
   unsigned size = utils::getSize(node);
   unsigned log2_size = std::ceil(log2((double)size));
   Node a_size = utils::mkConst(size, size);
-  Node b_ult_a_size_node = Rewriter::rewrite(
-      NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT, node[1], a_size));
-  // ensure that the inequality is bit-blasted
-  bb->bbAtom(b_ult_a_size_node);
-  T b_ult_a_size = bb->getBBAtom(b_ult_a_size_node);
+
+  std::vector<T> a_size_bits;
+  DefaultConstBB(a_size, a_size_bits, bb);
+  T b_ult_a_size = uLessThanBB(b, a_size_bits, false);
 
   res = a;
   T sign_bit = a.back();
index 36e115e5e161aca1c9f45d8db837b9bceb40523d..8eb209b53c14cadbf01c7c446253d6d8368a3960 100644 (file)
@@ -51,9 +51,13 @@ void BBSimple::storeBBTerm(TNode node, const Bits& bits)
   d_termCache.emplace(node, bits);
 }
 
-bool BBSimple::hasBBAtom(TNode atom) const
+bool BBSimple::hasBBAtom(TNode lit) const
 {
-  return d_bbAtoms.find(atom) != d_bbAtoms.end();
+  if (lit.getKind() == kind::NOT)
+  {
+    lit = lit[0];
+  }
+  return d_bbAtoms.find(lit) != d_bbAtoms.end();
 }
 
 void BBSimple::makeVariable(TNode var, Bits& bits)
@@ -143,6 +147,11 @@ bool BBSimple::collectModelValues(TheoryModel* m,
   return true;
 }
 
+bool BBSimple::isVariable(TNode node)
+{
+  return d_variables.find(node) != d_variables.end();
+}
+
 }  // namespace bv
 }  // namespace theory
 }  // namespace CVC4
index 8a625b5e194a900cd60583f8d206be691d93f78e..72a2fb0d8d4525314d8122682cd746125544fd50 100644 (file)
@@ -58,6 +58,9 @@ class BBSimple : public TBitblaster<Node>
 
   prop::SatSolver* getSatSolver() override { Unreachable(); }
 
+  /** Checks whether node is a variable introduced via `makeVariable`.*/
+  bool isVariable(TNode node);
+
  private:
   /** Query SAT solver for assignment of node 'a'. */
   Node getModelFromSatSolver(TNode a, bool fullModel) override;
diff --git a/src/theory/bv/bv_solver_bitblast.cpp b/src/theory/bv/bv_solver_bitblast.cpp
new file mode 100644 (file)
index 0000000..68192e1
--- /dev/null
@@ -0,0 +1,161 @@
+/*********************                                                        */
+/*! \file bv_solver_bitblast.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ **   Mathias Preiner
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 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.\endverbatim
+ **
+ ** \brief Bit-blasting solver
+ **
+ ** Bit-blasting solver that supports multiple SAT backends.
+ **/
+
+#include "theory/bv/bv_solver_bitblast.h"
+
+#include "options/bv_options.h"
+#include "prop/sat_solver_factory.h"
+#include "smt/smt_statistics_registry.h"
+#include "theory/bv/theory_bv.h"
+#include "theory/bv/theory_bv_utils.h"
+#include "theory/theory_model.h"
+
+namespace CVC4 {
+namespace theory {
+namespace bv {
+
+BVSolverBitblast::BVSolverBitblast(TheoryState* s,
+                                   TheoryInferenceManager& inferMgr,
+                                   ProofNodeManager* pnm)
+    : BVSolver(*s, inferMgr),
+      d_bitblaster(new BBSimple(s)),
+      d_nullRegistrar(new prop::NullRegistrar()),
+      d_nullContext(new context::Context()),
+      d_facts(s->getSatContext()),
+      d_epg(pnm ? new EagerProofGenerator(pnm, s->getUserContext(), "")
+                : nullptr)
+{
+  if (pnm != nullptr)
+  {
+    d_bvProofChecker.registerTo(pnm->getChecker());
+  }
+
+  switch (options::bvSatSolver())
+  {
+    case options::SatSolverMode::CRYPTOMINISAT:
+      d_satSolver.reset(prop::SatSolverFactory::createCryptoMinisat(
+          smtStatisticsRegistry(), "BVSolverBitblast"));
+      break;
+    default:
+      d_satSolver.reset(prop::SatSolverFactory::createCadical(
+          smtStatisticsRegistry(), "BVSolverBitblast"));
+  }
+  d_cnfStream.reset(new prop::CnfStream(d_satSolver.get(),
+                                        d_nullRegistrar.get(),
+                                        d_nullContext.get(),
+                                        nullptr,
+                                        smt::currentResourceManager()));
+}
+
+void BVSolverBitblast::postCheck(Theory::Effort level)
+{
+  if (level != Theory::Effort::EFFORT_FULL)
+  {
+    return;
+  }
+
+  std::vector<prop::SatLiteral> assumptions;
+  std::unordered_map<prop::SatLiteral, TNode, prop::SatLiteralHashFunction>
+      node_map;
+  for (const TNode fact : d_facts)
+  {
+    /* Bitblast fact */
+    d_bitblaster->bbAtom(fact);
+    Node bb_fact = Rewriter::rewrite(d_bitblaster->getStoredBBAtom(fact));
+    d_cnfStream->ensureLiteral(bb_fact);
+
+    prop::SatLiteral lit = d_cnfStream->getLiteral(bb_fact);
+    assumptions.push_back(lit);
+    node_map.emplace(lit, fact);
+  }
+
+  prop::SatValue val = d_satSolver->solve(assumptions);
+
+  if (val == prop::SatValue::SAT_VALUE_FALSE)
+  {
+    std::vector<prop::SatLiteral> unsat_assumptions;
+    d_satSolver->getUnsatAssumptions(unsat_assumptions);
+    Assert(unsat_assumptions.size() > 0);
+
+    std::vector<Node> conflict;
+    for (const prop::SatLiteral& lit : unsat_assumptions)
+    {
+      conflict.push_back(node_map[lit]);
+    }
+
+    NodeManager* nm = NodeManager::currentNM();
+    d_inferManager.conflict(nm->mkAnd(conflict));
+  }
+}
+
+bool BVSolverBitblast::preNotifyFact(
+    TNode atom, bool pol, TNode fact, bool isPrereg, bool isInternal)
+{
+  d_facts.push_back(fact);
+  return false;  // Return false to enable equality engine reasoning in Theory.
+}
+
+bool BVSolverBitblast::collectModelValues(TheoryModel* m,
+                                          const std::set<Node>& termSet)
+{
+  for (const auto& term : termSet)
+  {
+    if (!d_bitblaster->isVariable(term))
+    {
+      continue;
+    }
+
+    Node value = getValueFromSatSolver(term);
+    Assert(value.isConst());
+    if (!m->assertEquality(term, value, true))
+    {
+      return false;
+    }
+  }
+  return true;
+}
+
+Node BVSolverBitblast::getValueFromSatSolver(TNode node)
+{
+  /* If node was not bit-blasted return zero-initialized bit-vector. */
+  if (!d_bitblaster->hasBBTerm(node))
+  {
+    return utils::mkConst(utils::getSize(node), 0u);
+  }
+
+  std::vector<Node> bits;
+  d_bitblaster->getBBTerm(node, bits);
+  Integer value(0), one(1), zero(0), bit;
+  for (size_t i = 0, size = bits.size(), j = size - 1; i < size; ++i, --j)
+  {
+    if (d_cnfStream->hasLiteral(bits[j]))
+    {
+      prop::SatLiteral lit = d_cnfStream->getLiteral(bits[j]);
+      prop::SatValue val = d_satSolver->modelValue(lit);
+      bit = val == prop::SatValue::SAT_VALUE_TRUE ? one : zero;
+    }
+    else
+    {
+      bit = zero;
+    }
+    value = value * 2 + bit;
+  }
+  return utils::mkConst(bits.size(), value);
+}
+
+}  // namespace bv
+}  // namespace theory
+}  // namespace CVC4
diff --git a/src/theory/bv/bv_solver_bitblast.h b/src/theory/bv/bv_solver_bitblast.h
new file mode 100644 (file)
index 0000000..df0f2e0
--- /dev/null
@@ -0,0 +1,99 @@
+/*********************                                                        */
+/*! \file bv_solver_bitblast.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ **   Mathias Preiner
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 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.\endverbatim
+ **
+ ** \brief Bit-blasting solver
+ **
+ ** Bit-blasting solver that supports multiple SAT back ends.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__THEORY__BV__BV_SOLVER_BITBLAST_H
+#define CVC4__THEORY__BV__BV_SOLVER_BITBLAST_H
+
+#include <unordered_map>
+
+#include "prop/cnf_stream.h"
+#include "prop/sat_solver.h"
+#include "theory/bv/bitblast/simple_bitblaster.h"
+#include "theory/bv/bv_solver.h"
+#include "theory/bv/proof_checker.h"
+#include "theory/eager_proof_generator.h"
+
+namespace CVC4 {
+
+namespace theory {
+namespace bv {
+
+/**
+ * Bit-blasting solver with support for different SAT back ends.
+ */
+class BVSolverBitblast : public BVSolver
+{
+ public:
+  BVSolverBitblast(TheoryState* state,
+                   TheoryInferenceManager& inferMgr,
+                   ProofNodeManager* pnm);
+  ~BVSolverBitblast() = default;
+
+  bool needsEqualityEngine(EeSetupInfo& esi) override { return true; }
+
+  void preRegisterTerm(TNode n) override {}
+
+  void postCheck(Theory::Effort level) override;
+
+  bool preNotifyFact(TNode atom,
+                     bool pol,
+                     TNode fact,
+                     bool isPrereg,
+                     bool isInternal) override;
+
+  std::string identify() const override { return "BVSolverBitblast"; };
+
+  Theory::PPAssertStatus ppAssert(
+      TrustNode in, TrustSubstitutionMap& outSubstitutions) override
+  {
+    return Theory::PPAssertStatus::PP_ASSERT_STATUS_UNSOLVED;
+  }
+
+  bool collectModelValues(TheoryModel* m,
+                          const std::set<Node>& termSet) override;
+
+ private:
+  /** Get value of `node` from SAT solver. */
+  Node getValueFromSatSolver(TNode node);
+
+  /** Bit-blaster used to bit-blast atoms/terms. */
+  std::unique_ptr<BBSimple> d_bitblaster;
+
+  /** Used for initializing CnfStream> */
+  std::unique_ptr<prop::NullRegistrar> d_nullRegistrar;
+  std::unique_ptr<context::Context> d_nullContext;
+
+  /** SAT solver back end (configured via options::bvSatSolver. */
+  std::unique_ptr<prop::SatSolver> d_satSolver;
+  /** CNF stream. */
+  std::unique_ptr<prop::CnfStream> d_cnfStream;
+
+  /** Facts sent to this solver. */
+  context::CDList<Node> d_facts;
+
+  /** Proof generator that manages proofs for lemmas generated by this class. */
+  std::unique_ptr<EagerProofGenerator> d_epg;
+
+  BVProofRuleChecker d_bvProofChecker;
+};
+
+}  // namespace bv
+}  // namespace theory
+}  // namespace CVC4
+
+#endif
index 227df458a7d8140ddb9b6bbbfc1483dddbd2ca49..b27bd04e1d9eee063e0085e0d0c315bbed87c93b 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "options/bv_options.h"
 #include "options/smt_options.h"
+#include "theory/bv/bv_solver_bitblast.h"
 #include "theory/bv/bv_solver_lazy.h"
 #include "theory/bv/bv_solver_simple.h"
 #include "theory/bv/theory_bv_utils.h"
@@ -42,6 +43,10 @@ TheoryBV::TheoryBV(context::Context* c,
 {
   switch (options::bvSolver())
   {
+    case options::BVSolver::BITBLAST:
+      d_internal.reset(new BVSolverBitblast(&d_state, d_inferMgr, pnm));
+      break;
+
     case options::BVSolver::LAZY:
       d_internal.reset(new BVSolverLazy(*this, c, u, pnm, name));
       break;
@@ -70,6 +75,44 @@ void TheoryBV::finishInit()
   getValuation().setSemiEvaluatedKind(kind::BITVECTOR_ACKERMANNIZE_UDIV);
   getValuation().setSemiEvaluatedKind(kind::BITVECTOR_ACKERMANNIZE_UREM);
   d_internal->finishInit();
+
+  eq::EqualityEngine* ee = getEqualityEngine();
+  if (ee)
+  {
+    // The kinds we are treating as function application in congruence
+    ee->addFunctionKind(kind::BITVECTOR_CONCAT, true);
+    //    ee->addFunctionKind(kind::BITVECTOR_AND);
+    //    ee->addFunctionKind(kind::BITVECTOR_OR);
+    //    ee->addFunctionKind(kind::BITVECTOR_XOR);
+    //    ee->addFunctionKind(kind::BITVECTOR_NOT);
+    //    ee->addFunctionKind(kind::BITVECTOR_NAND);
+    //    ee->addFunctionKind(kind::BITVECTOR_NOR);
+    //    ee->addFunctionKind(kind::BITVECTOR_XNOR);
+    //    ee->addFunctionKind(kind::BITVECTOR_COMP);
+    ee->addFunctionKind(kind::BITVECTOR_MULT, true);
+    ee->addFunctionKind(kind::BITVECTOR_PLUS, true);
+    ee->addFunctionKind(kind::BITVECTOR_EXTRACT, true);
+    //    ee->addFunctionKind(kind::BITVECTOR_SUB);
+    //    ee->addFunctionKind(kind::BITVECTOR_NEG);
+    //    ee->addFunctionKind(kind::BITVECTOR_UDIV);
+    //    ee->addFunctionKind(kind::BITVECTOR_UREM);
+    //    ee->addFunctionKind(kind::BITVECTOR_SDIV);
+    //    ee->addFunctionKind(kind::BITVECTOR_SREM);
+    //    ee->addFunctionKind(kind::BITVECTOR_SMOD);
+    //    ee->addFunctionKind(kind::BITVECTOR_SHL);
+    //    ee->addFunctionKind(kind::BITVECTOR_LSHR);
+    //    ee->addFunctionKind(kind::BITVECTOR_ASHR);
+    //    ee->addFunctionKind(kind::BITVECTOR_ULT);
+    //    ee->addFunctionKind(kind::BITVECTOR_ULE);
+    //    ee->addFunctionKind(kind::BITVECTOR_UGT);
+    //    ee->addFunctionKind(kind::BITVECTOR_UGE);
+    //    ee->addFunctionKind(kind::BITVECTOR_SLT);
+    //    ee->addFunctionKind(kind::BITVECTOR_SLE);
+    //    ee->addFunctionKind(kind::BITVECTOR_SGT);
+    //    ee->addFunctionKind(kind::BITVECTOR_SGE);
+    ee->addFunctionKind(kind::BITVECTOR_TO_NAT);
+    ee->addFunctionKind(kind::INT_TO_BITVECTOR);
+  }
 }
 
 Node TheoryBV::getUFDivByZero(Kind k, unsigned width)
@@ -199,6 +242,11 @@ TrustNode TheoryBV::ppRewrite(TNode t)
 
 void TheoryBV::presolve() { d_internal->presolve(); }
 
+EqualityStatus TheoryBV::getEqualityStatus(TNode a, TNode b)
+{
+  return d_internal->getEqualityStatus(a, b);
+}
+
 TrustNode TheoryBV::explain(TNode node) { return d_internal->explain(node); }
 
 void TheoryBV::notifySharedTerm(TNode t)
index 093a35a1b69c4681b0a0e24a040e596636e3197d..306b1ff937eb0331e61a69a5c839eb3d4626527b 100644 (file)
@@ -96,6 +96,8 @@ class TheoryBV : public Theory
 
   void presolve() override;
 
+  EqualityStatus getEqualityStatus(TNode a, TNode b) override;
+
   /** Called by abstraction preprocessing pass. */
   bool applyAbstraction(const std::vector<Node>& assertions,
                         std::vector<Node>& new_assertions);