More updates to arithmetic in preparation for central equality engine (#6927)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Mon, 26 Jul 2021 18:26:55 +0000 (13:26 -0500)
committerGitHub <noreply@github.com>
Mon, 26 Jul 2021 18:26:55 +0000 (13:26 -0500)
Makes arithEqSolver more robust to propagations from multiple sources, changes the default relationship to congruence manager based on preliminary results on SMT-LIB.

src/options/arith_options.toml
src/smt/set_defaults.cpp
src/theory/arith/equality_solver.cpp
src/theory/arith/inference_manager.cpp
src/theory/arith/inference_manager.h
src/theory/arith/theory_arith_private.cpp
src/theory/theory_inference_manager.h

index 8766672a597a0d4d27318a5c9481ecb69416f9e6..26b1cfecb566bcfa8337a1af75ab65d0988b5869 100644 (file)
@@ -595,3 +595,11 @@ name   = "Arithmetic Theory"
   type       = "bool"
   default    = "false"
   help       = "whether to use the equality solver in the theory of arithmetic"
+
+[[option]]
+  name       = "arithCongMan"
+  category   = "regular"
+  long       = "arith-cong-man"
+  type       = "bool"
+  default    = "true"
+  help       = "(experimental) whether to use the congruence manager when the equality solver is enabled"
index d5b3b7929b75c7035b49b4b975a40b886da109f7..e12d3eb1dffb6872283055ab9c1cf7f05aae1969 100644 (file)
@@ -968,6 +968,18 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
     Trace("smt") << "setting decision mode to " << opts.decision.decisionMode
                  << std::endl;
   }
+
+  // set up of central equality engine
+  if (opts.arith.arithEqSolver)
+  {
+    if (!opts.arith.arithCongManWasSetByUser)
+    {
+      // if we are using the arithmetic equality solver, do not use the
+      // arithmetic congruence manager by default
+      opts.arith.arithCongMan = false;
+    }
+  }
+
   if (options::incrementalSolving())
   {
     // disable modes not supported by incremental
index 58793c654d776691b4c8b739071ee63cf42057b4..8b4e1b8dd877ce9d15bc809552b82fd035f28c7b 100644 (file)
@@ -80,6 +80,11 @@ TrustNode EqualitySolver::explain(TNode lit)
 }
 bool EqualitySolver::propagateLit(Node lit)
 {
+  // if we've already propagated, ignore
+  if (d_aim.hasPropagated(lit))
+  {
+    return true;
+  }
   // notice this is only used when ee-mode=distributed
   // remember that this was a literal we propagated
   Trace("arith-eq-solver-debug") << "propagate lit " << lit << std::endl;
index 90c17be4a8b87ef67c389bb267d333407b58c4d1..9cb23290874288155c4a5220364a1a16d002607a 100644 (file)
@@ -27,7 +27,10 @@ namespace arith {
 InferenceManager::InferenceManager(TheoryArith& ta,
                                    ArithState& astate,
                                    ProofNodeManager* pnm)
-    : InferenceManagerBuffered(ta, astate, pnm, "theory::arith::")
+    : InferenceManagerBuffered(ta, astate, pnm, "theory::arith::"),
+      // currently must track propagated literals if using the equality solver
+      d_trackPropLits(options::arithEqSolver()),
+      d_propLits(astate.getSatContext())
 {
 }
 
@@ -146,6 +149,21 @@ bool InferenceManager::isEntailedFalse(const SimpleTheoryLemma& lem)
   return false;
 }
 
+bool InferenceManager::propagateLit(TNode lit)
+{
+  if (d_trackPropLits)
+  {
+    d_propLits.insert(lit);
+  }
+  return TheoryInferenceManager::propagateLit(lit);
+}
+
+bool InferenceManager::hasPropagated(TNode lit) const
+{
+  Assert(d_trackPropLits);
+  return d_propLits.find(lit) != d_propLits.end();
+}
+
 }  // namespace arith
 }  // namespace theory
 }  // namespace cvc5
index 7e103797e21bcfa6a1af8877bad42bf9fd8ff2a0..eeb9d096f8abd3dfb4750055384cdcc7a67086eb 100644 (file)
@@ -97,6 +97,13 @@ class InferenceManager : public InferenceManagerBuffered
 
   /** Checks whether the given lemma is already present in the cache. */
   virtual bool hasCachedLemma(TNode lem, LemmaProperty p) override;
+  /** overrides propagateLit to track which literals have been propagated */
+  bool propagateLit(TNode lit) override;
+  /**
+   * Return true if we have propagated lit already. This call is only valid if
+   * d_trackPropLits is true.
+   */
+  bool hasPropagated(TNode lit) const;
 
  protected:
   /**
@@ -111,9 +118,12 @@ class InferenceManager : public InferenceManagerBuffered
    * conflict.
    */
   bool isEntailedFalse(const SimpleTheoryLemma& lem);
-
   /** The waiting lemmas. */
   std::vector<std::unique_ptr<SimpleTheoryLemma>> d_waitingLem;
+  /** Whether we are tracking the set of propagated literals */
+  bool d_trackPropLits;
+  /** The literals we have propagated */
+  NodeSet d_propLits;
 };
 
 }  // namespace arith
index d7ae08379396addefce25710ea66d4a0000c57b4..053b91d906e9f9e398f13decd4ed685880235fbf 100644 (file)
@@ -137,7 +137,7 @@ TheoryArithPrivate::TheoryArithPrivate(TheoryArith& containing,
                           d_partialModel,
                           RaiseEqualityEngineConflict(*this),
                           d_pnm),
-      d_cmEnabled(c, true),
+      d_cmEnabled(c, options::arithCongMan()),
 
       d_dualSimplex(
           d_linEq, d_errorSet, RaiseConflict(*this), TempVarMalloc(*this)),
index c61f4311b39de861b5d26a7ae9adafb08c88fa13..b11f21f1e08a3d335d3d0afc1f12eff359dc52d8 100644 (file)
@@ -132,7 +132,7 @@ class TheoryInferenceManager
    * EqualityEngineNotify::eqNotifyTriggerPredicate and
    * EqualityEngineNotify::eqNotifyTriggerTermEquality.
    */
-  bool propagateLit(TNode lit);
+  virtual bool propagateLit(TNode lit);
   /**
    * Return an explanation for the literal represented by parameter lit
    * (which was previously propagated by this theory). By default, this