Refactoring theory inference process (#5920)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Fri, 19 Feb 2021 15:26:36 +0000 (09:26 -0600)
committerGitHub <noreply@github.com>
Fri, 19 Feb 2021 15:26:36 +0000 (09:26 -0600)
This PR refactors TheoryInference so that it is not responsible for calling back into InferenceManager, instead it sets data so that InferenceManagerBuffered has enough information to do this itself. It also makes the decision of whether to cache lemmas in theory inference manager a global choice per-theory instead of per-lemma.

31 files changed:
src/theory/arith/arith_preprocess.cpp
src/theory/arith/nl/iand_solver.cpp
src/theory/arith/nl/nl_lemma_utils.cpp
src/theory/arith/nl/nl_lemma_utils.h
src/theory/arrays/inference_manager.cpp
src/theory/arrays/inference_manager.h
src/theory/bags/bag_solver.cpp
src/theory/bags/infer_info.cpp
src/theory/bags/infer_info.h
src/theory/bags/inference_generator.cpp
src/theory/bags/inference_generator.h
src/theory/bags/inference_manager.h
src/theory/bags/theory_bags.cpp
src/theory/datatypes/inference.cpp
src/theory/datatypes/inference.h
src/theory/datatypes/inference_manager.cpp
src/theory/datatypes/inference_manager.h
src/theory/datatypes/theory_datatypes.cpp
src/theory/inference_manager_buffered.cpp
src/theory/inference_manager_buffered.h
src/theory/sets/term_registry.cpp
src/theory/strings/infer_info.cpp
src/theory/strings/infer_info.h
src/theory/strings/inference_manager.cpp
src/theory/strings/inference_manager.h
src/theory/theory_inference.cpp
src/theory/theory_inference.h
src/theory/theory_inference_manager.cpp
src/theory/theory_inference_manager.h
src/theory/uf/cardinality_extension.cpp
src/theory/uf/theory_uf.cpp

index 3e0937e8b2fb7b6e27534c89c3a6e65e26bcbf5f..31eb8bb8f1227dd508c17c724088da1372e23966 100644 (file)
@@ -48,7 +48,7 @@ bool ArithPreprocess::reduceAssertion(TNode atom)
   Assert(tn.getKind() == TrustNodeKind::REWRITE);
   // tn is of kind REWRITE, turn this into a LEMMA here
   TrustNode tlem = TrustNode::mkTrustLemma(tn.getProven(), tn.getGenerator());
-  // must preprocess
+  // send the trusted lemma
   d_im.trustedLemma(tlem, InferenceId::ARITH_PP_ELIM_OPERATORS);
   // mark the atom as reduced
   d_reduced[atom] = true;
index 78ffb3c09bd5b9e1188cc927fc7875e1d4fd6ec8..a5b4e87bda5ae27c12cba2f84dac10d1e3f29b00 100644 (file)
@@ -171,12 +171,11 @@ void IAndSolver::checkFullRefine()
         Node lem = valueBasedLemma(i);
         Trace("iand-lemma")
             << "IAndSolver::Lemma: " << lem << " ; VALUE_REFINE" << std::endl;
-        // value lemmas should not contain div/mod so we don't need to tag it with PREPROCESS
+        // send the value lemma
         d_im.addPendingLemma(lem,
                              InferenceId::ARITH_NL_IAND_VALUE_REFINE,
                              nullptr,
-                             true,
-                             LemmaProperty::NONE);
+                             true);
       }
     }
   }
index 7cb1da728a353962527eedbb0aa0b9e00658a4f8..1589341ed8608e6f764610bb6c1fd85fbb1840d0 100644 (file)
@@ -22,14 +22,13 @@ namespace theory {
 namespace arith {
 namespace nl {
 
-bool NlLemma::process(TheoryInferenceManager* im, bool asLemma)
+TrustNode NlLemma::processLemma(LemmaProperty& p)
 {
-  bool res = SimpleTheoryLemma::process(im, asLemma);
   if (d_nlext != nullptr)
   {
     d_nlext->processSideEffect(*this);
   }
-  return res;
+  return SimpleTheoryLemma::processLemma(p);
 }
 
 std::ostream& operator<<(std::ostream& out, NlLemma& n)
index 277751fe8fc26a239f17be29522cb05d02df9bb3..b782b33d707fcc2e3c42e4ecda0cb51e4e80e3c6 100644 (file)
@@ -52,7 +52,7 @@ class NlLemma : public SimpleTheoryLemma
   }
   ~NlLemma() {}
 
-  bool process(TheoryInferenceManager* im, bool asLemma) override;
+  TrustNode processLemma(LemmaProperty& p) override;
 
   /** secant points to add
    *
index a4b8ecd4421ddfafb893ba0ccb8bb26eaf55ab08..96f2b02c39ec6d45c35218c80715df35e31c8f24 100644 (file)
@@ -27,9 +27,10 @@ namespace arrays {
 InferenceManager::InferenceManager(Theory& t,
                                    TheoryState& state,
                                    ProofNodeManager* pnm)
-    : TheoryInferenceManager(t, state, pnm, "theory::arrays"),
-      d_lemmaPg(pnm ? new EagerProofGenerator(
-                    pnm, state.getUserContext(), "ArrayLemmaProofGenerator")
+    : TheoryInferenceManager(t, state, pnm, "theory::arrays", false),
+      d_lemmaPg(pnm ? new EagerProofGenerator(pnm,
+                                              state.getUserContext(),
+                                              "ArrayLemmaProofGenerator")
                     : nullptr)
 {
 }
@@ -59,7 +60,7 @@ bool InferenceManager::assertInference(TNode atom,
 }
 
 bool InferenceManager::arrayLemma(
-    Node conc, InferenceId id, Node exp, PfRule pfr, LemmaProperty p, bool doCache)
+    Node conc, InferenceId id, Node exp, PfRule pfr, LemmaProperty p)
 {
   Trace("arrays-infer") << "TheoryArrays::arrayLemma: " << conc << " by " << exp
                         << "; " << id << std::endl;
@@ -72,11 +73,11 @@ bool InferenceManager::arrayLemma(
     convert(pfr, conc, exp, children, args);
     // make the trusted lemma based on the eager proof generator and send
     TrustNode tlem = d_lemmaPg->mkTrustNode(conc, pfr, children, args);
-    return trustedLemma(tlem, id, p, doCache);
+    return trustedLemma(tlem, id, p);
   }
   // send lemma without proofs
   Node lem = nm->mkNode(IMPLIES, exp, conc);
-  return lemma(lem, id, p, doCache);
+  return lemma(lem, id, p);
 }
 
 void InferenceManager::convert(PfRule& id,
index 96af0b6771857f16a0bac11a7963a0d41f79af72..99e586fe4b4e088c9546f151d82d92c73e0d09de 100644 (file)
@@ -47,15 +47,13 @@ class InferenceManager : public TheoryInferenceManager
    */
   bool assertInference(TNode atom, bool polarity, InferenceId id, TNode reason, PfRule pfr);
   /**
-   * Send lemma (exp => conc) based on proof rule id with properties p. Cache
-   * the lemma if doCache is true.
+   * Send lemma (exp => conc) based on proof rule id with properties p.
    */
   bool arrayLemma(Node conc,
                   InferenceId id,
                   Node exp,
                   PfRule pfr,
-                  LemmaProperty p = LemmaProperty::NONE,
-                  bool doCache = false);
+                  LemmaProperty p = LemmaProperty::NONE);
 
  private:
   /**
index bdd4a9b301be9ed6f688347f58a366ea6202b1c6..76c001ba299ae6146a0e4e8c71807f1629f6bac5 100644 (file)
@@ -27,7 +27,7 @@ namespace theory {
 namespace bags {
 
 BagSolver::BagSolver(SolverState& s, InferenceManager& im, TermRegistry& tr)
-    : d_state(s), d_ig(&d_state), d_im(im), d_termReg(tr)
+    : d_state(s), d_ig(&s, &im), d_im(im), d_termReg(tr)
 {
   d_zero = NodeManager::currentNM()->mkConst(Rational(0));
   d_one = NodeManager::currentNM()->mkConst(Rational(1));
@@ -102,7 +102,7 @@ void BagSolver::checkEmpty(const Node& n)
   for (const Node& e : d_state.getElements(n))
   {
     InferInfo i = d_ig.empty(n, e);
-    i.process(&d_im, true);
+    d_im.lemmaTheoryInference(&i);
   }
 }
 
@@ -113,7 +113,7 @@ void BagSolver::checkUnionDisjoint(const Node& n)
   for (const Node& e : elements)
   {
     InferInfo i = d_ig.unionDisjoint(n, e);
-    i.process(&d_im, true);
+    d_im.lemmaTheoryInference(&i);
   }
 }
 
@@ -124,7 +124,7 @@ void BagSolver::checkUnionMax(const Node& n)
   for (const Node& e : elements)
   {
     InferInfo i = d_ig.unionMax(n, e);
-    i.process(&d_im, true);
+    d_im.lemmaTheoryInference(&i);
   }
 }
 
@@ -135,7 +135,7 @@ void BagSolver::checkIntersectionMin(const Node& n)
   for (const Node& e : elements)
   {
     InferInfo i = d_ig.intersection(n, e);
-    i.process(&d_im, true);
+    d_im.lemmaTheoryInference(&i);
   }
 }
 
@@ -146,7 +146,7 @@ void BagSolver::checkDifferenceSubtract(const Node& n)
   for (const Node& e : elements)
   {
     InferInfo i = d_ig.differenceSubtract(n, e);
-    i.process(&d_im, true);
+    d_im.lemmaTheoryInference(&i);
   }
 }
 
@@ -159,13 +159,13 @@ void BagSolver::checkMkBag(const Node& n)
   for (const Node& e : d_state.getElements(n))
   {
     InferInfo i = d_ig.mkBag(n, e);
-    i.process(&d_im, true);
+    d_im.lemmaTheoryInference(&i);
   }
 }
 void BagSolver::checkNonNegativeCountTerms(const Node& bag, const Node& element)
 {
   InferInfo i = d_ig.nonNegativeCount(bag, element);
-  i.process(&d_im, true);
+  d_im.lemmaTheoryInference(&i);
 }
 
 void BagSolver::checkDifferenceRemove(const Node& n)
@@ -175,7 +175,7 @@ void BagSolver::checkDifferenceRemove(const Node& n)
   for (const Node& e : elements)
   {
     InferInfo i = d_ig.differenceRemove(n, e);
-    i.process(&d_im, true);
+    d_im.lemmaTheoryInference(&i);
   }
 }
 
@@ -192,7 +192,7 @@ void BagSolver::checkDuplicateRemoval(Node n)
   for (const Node& e : elements)
   {
     InferInfo i = d_ig.duplicateRemoval(n, e);
-    i.process(&d_im, true);
+    d_im.lemmaTheoryInference(&i);
   }
 }
 
@@ -201,7 +201,7 @@ void BagSolver::checkDisequalBagTerms()
   for (const Node& n : d_state.getDisequalBagTerms())
   {
     InferInfo info = d_ig.bagDisequality(n);
-    info.process(&d_im, true);
+    d_im.lemmaTheoryInference(&info);
   }
 }
 
index 0655b6bbfd7f272e924ef16628fb27abbd6908ce..969c6b3dee9fdc1102df36d6b7ffc1b3e8e3b73f 100644 (file)
@@ -20,39 +20,28 @@ namespace CVC4 {
 namespace theory {
 namespace bags {
 
-InferInfo::InferInfo(InferenceId id) : TheoryInference(id) {}
+InferInfo::InferInfo(TheoryInferenceManager* im, InferenceId id)
+    : TheoryInference(id), d_im(im)
+{
+}
 
-bool InferInfo::process(TheoryInferenceManager* im, bool asLemma)
+TrustNode InferInfo::processLemma(LemmaProperty& p)
 {
-  Node lemma = d_conclusion;
-  if (d_premises.size() >= 2)
-  {
-    Node andNode = NodeManager::currentNM()->mkNode(kind::AND, d_premises);
-    lemma = andNode.impNode(lemma);
-  }
-  else if (d_premises.size() == 1)
-  {
-    lemma = d_premises[0].impNode(lemma);
-  }
-  if (asLemma)
-  {
-    TrustNode trustedLemma = TrustNode::mkTrustLemma(lemma, nullptr);
-    im->trustedLemma(trustedLemma, getId());
-  }
-  else
-  {
-    Unimplemented();
-  }
+  NodeManager* nm = NodeManager::currentNM();
+  Node pnode = nm->mkAnd(d_premises);
+  Node lemma = nm->mkNode(kind::IMPLIES, pnode, d_conclusion);
+
+  // send lemmas corresponding to the skolems introduced
   for (const auto& pair : d_skolems)
   {
     Node n = pair.first.eqNode(pair.second);
     TrustNode trustedLemma = TrustNode::mkTrustLemma(n, nullptr);
-    im->trustedLemma(trustedLemma, getId());
+    d_im->trustedLemma(trustedLemma, getId(), p);
   }
 
   Trace("bags::InferInfo::process") << (*this) << std::endl;
 
-  return true;
+  return TrustNode::mkTrustLemma(lemma, nullptr);
 }
 
 bool InferInfo::isTrivial() const
index 66d75b5dc68808502a3116e5980b7a10e09f7a86..a533acf580458e2f5a60deb649125cdbdd8bcde7 100644 (file)
 
 namespace CVC4 {
 namespace theory {
+
+class TheoryInferenceManager;
+
 namespace bags {
 
-class InferenceManager;
 
 /**
  * An inference. This is a class to track an unprocessed call to either
@@ -38,10 +40,12 @@ class InferenceManager;
 class InferInfo : public TheoryInference
 {
  public:
-  InferInfo(InferenceId id);
+  InferInfo(TheoryInferenceManager* im, InferenceId id);
   ~InferInfo() {}
-  /** Process this inference */
-  bool process(TheoryInferenceManager* im, bool asLemma) override;
+  /** Process lemma */
+  TrustNode processLemma(LemmaProperty& p) override;
+  /** Pointer to the class used for processing this info */
+  TheoryInferenceManager* d_im;
   /** The conclusion */
   Node d_conclusion;
   /**
index 2d4a5afedfcf32b3cb42368af174154ab0172ce7..bc1ed771c92df5987ac8057815a0bd85068291ff 100644 (file)
@@ -23,7 +23,8 @@ namespace CVC4 {
 namespace theory {
 namespace bags {
 
-InferenceGenerator::InferenceGenerator(SolverState* state) : d_state(state)
+InferenceGenerator::InferenceGenerator(SolverState* state, InferenceManager* im)
+    : d_state(state), d_im(im)
 {
   d_nm = NodeManager::currentNM();
   d_sm = d_nm->getSkolemManager();
@@ -37,7 +38,7 @@ InferInfo InferenceGenerator::nonNegativeCount(Node n, Node e)
   Assert(n.getType().isBag());
   Assert(e.getType() == n.getType().getBagElementType());
 
-  InferInfo inferInfo(InferenceId::BAG_NON_NEGATIVE_COUNT);
+  InferInfo inferInfo(d_im, InferenceId::BAG_NON_NEGATIVE_COUNT);
   Node count = d_nm->mkNode(kind::BAG_COUNT, e, n);
 
   Node gte = d_nm->mkNode(kind::GEQ, count, d_zero);
@@ -54,7 +55,7 @@ InferInfo InferenceGenerator::mkBag(Node n, Node e)
   {
     // TODO issue #78: refactor this with BagRewriter
     // (=> true (= (bag.count e (bag e c)) c))
-    InferInfo inferInfo(InferenceId::BAG_MK_BAG_SAME_ELEMENT);
+    InferInfo inferInfo(d_im, InferenceId::BAG_MK_BAG_SAME_ELEMENT);
     Node skolem = getSkolem(n, inferInfo);
     Node count = getMultiplicityTerm(e, skolem);
     inferInfo.d_conclusion = count.eqNode(n[1]);
@@ -65,7 +66,7 @@ InferInfo InferenceGenerator::mkBag(Node n, Node e)
     // (=>
     //   true
     //   (= (bag.count e (bag x c)) (ite (= e x) c 0)))
-    InferInfo inferInfo(InferenceId::BAG_MK_BAG);
+    InferInfo inferInfo(d_im, InferenceId::BAG_MK_BAG);
     Node skolem = getSkolem(n, inferInfo);
     Node count = getMultiplicityTerm(e, skolem);
     Node same = d_nm->mkNode(kind::EQUAL, n[0], e);
@@ -88,7 +89,7 @@ InferInfo InferenceGenerator::bagDisequality(Node n)
   Node A = n[0];
   Node B = n[1];
 
-  InferInfo inferInfo(InferenceId::BAG_DISEQUALITY);
+  InferInfo inferInfo(d_im, InferenceId::BAG_DISEQUALITY);
 
   TypeNode elementType = A.getType().getBagElementType();
   BoundVarManager* bvm = d_nm->getBoundVarManager();
@@ -121,7 +122,7 @@ InferInfo InferenceGenerator::empty(Node n, Node e)
   Assert(n.getKind() == kind::EMPTYBAG);
   Assert(e.getType() == n.getType().getBagElementType());
 
-  InferInfo inferInfo(InferenceId::BAG_EMPTY);
+  InferInfo inferInfo(d_im, InferenceId::BAG_EMPTY);
   Node skolem = getSkolem(n, inferInfo);
   Node count = getMultiplicityTerm(e, skolem);
 
@@ -137,7 +138,7 @@ InferInfo InferenceGenerator::unionDisjoint(Node n, Node e)
 
   Node A = n[0];
   Node B = n[1];
-  InferInfo inferInfo(InferenceId::BAG_UNION_DISJOINT);
+  InferInfo inferInfo(d_im, InferenceId::BAG_UNION_DISJOINT);
 
   Node countA = getMultiplicityTerm(e, A);
   Node countB = getMultiplicityTerm(e, B);
@@ -159,7 +160,7 @@ InferInfo InferenceGenerator::unionMax(Node n, Node e)
 
   Node A = n[0];
   Node B = n[1];
-  InferInfo inferInfo(InferenceId::BAG_UNION_MAX);
+  InferInfo inferInfo(d_im, InferenceId::BAG_UNION_MAX);
 
   Node countA = getMultiplicityTerm(e, A);
   Node countB = getMultiplicityTerm(e, B);
@@ -182,7 +183,7 @@ InferInfo InferenceGenerator::intersection(Node n, Node e)
 
   Node A = n[0];
   Node B = n[1];
-  InferInfo inferInfo(InferenceId::BAG_INTERSECTION_MIN);
+  InferInfo inferInfo(d_im, InferenceId::BAG_INTERSECTION_MIN);
 
   Node countA = getMultiplicityTerm(e, A);
   Node countB = getMultiplicityTerm(e, B);
@@ -203,7 +204,7 @@ InferInfo InferenceGenerator::differenceSubtract(Node n, Node e)
 
   Node A = n[0];
   Node B = n[1];
-  InferInfo inferInfo(InferenceId::BAG_DIFFERENCE_SUBTRACT);
+  InferInfo inferInfo(d_im, InferenceId::BAG_DIFFERENCE_SUBTRACT);
 
   Node countA = getMultiplicityTerm(e, A);
   Node countB = getMultiplicityTerm(e, B);
@@ -225,7 +226,7 @@ InferInfo InferenceGenerator::differenceRemove(Node n, Node e)
 
   Node A = n[0];
   Node B = n[1];
-  InferInfo inferInfo(InferenceId::BAG_DIFFERENCE_REMOVE);
+  InferInfo inferInfo(d_im, InferenceId::BAG_DIFFERENCE_REMOVE);
 
   Node countA = getMultiplicityTerm(e, A);
   Node countB = getMultiplicityTerm(e, B);
@@ -246,7 +247,7 @@ InferInfo InferenceGenerator::duplicateRemoval(Node n, Node e)
   Assert(e.getType() == n[0].getType().getBagElementType());
 
   Node A = n[0];
-  InferInfo inferInfo(InferenceId::BAG_DUPLICATE_REMOVAL);
+  InferInfo inferInfo(d_im, InferenceId::BAG_DUPLICATE_REMOVAL);
 
   Node countA = getMultiplicityTerm(e, A);
   Node skolem = getSkolem(n, inferInfo);
index 4a852530ac2de20355507c23cf3b92ab4df84563..f10a1051f909516cfb2cbef30896d3da2de1fba3 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "expr/node.h"
 #include "infer_info.h"
+#include "theory/bags/inference_manager.h"
 #include "theory/bags/solver_state.h"
 
 namespace CVC4 {
@@ -35,7 +36,7 @@ namespace bags {
 class InferenceGenerator
 {
  public:
-  InferenceGenerator(SolverState* state);
+  InferenceGenerator(SolverState* state, InferenceManager* im);
 
   /**
    * @param A is a bag of type (Bag E)
@@ -179,6 +180,9 @@ class InferenceGenerator
   NodeManager* d_nm;
   SkolemManager* d_sm;
   SolverState* d_state;
+  /** Pointer to the inference manager */
+  InferenceManager* d_im;
+  /** Commonly used constants */
   Node d_true;
   Node d_zero;
   Node d_one;
index 71a014582452ac2bd8cd631f96a31cf3c62cf20c..1b132fc37f6712abfdb30f04d0467ad2ae2a51bb 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef CVC4__THEORY__BAGS__INFERENCE_MANAGER_H
 #define CVC4__THEORY__BAGS__INFERENCE_MANAGER_H
 
+#include "theory/bags/infer_info.h"
 #include "theory/bags/solver_state.h"
 #include "theory/inference_manager_buffered.h"
 
index 6df44295e7feb6b3e99deadfd8f7bd3dd89d4eb5..48fc38b8f8a1256bba0b09c6864553f0c478ed66 100644 (file)
@@ -31,7 +31,7 @@ TheoryBags::TheoryBags(context::Context* c,
     : Theory(THEORY_BAGS, c, u, out, valuation, logicInfo, pnm),
       d_state(c, u, valuation),
       d_im(*this, d_state, nullptr),
-      d_ig(&d_state),
+      d_ig(&d_state, &d_im),
       d_notify(*this, d_im),
       d_statistics(),
       d_rewriter(&d_statistics.d_rewrites),
index d03bb0f2f7d938fc033494b66c33b9d5ec74f762..04b1072c3f7078c046428f446bb1afc711be34bb 100644 (file)
@@ -61,16 +61,21 @@ bool DatatypesInference::mustCommunicateFact(Node n, Node exp)
   return false;
 }
 
-bool DatatypesInference::process(TheoryInferenceManager* im, bool asLemma)
+TrustNode DatatypesInference::processLemma(LemmaProperty& p)
 {
-  // Check to see if we have to communicate it to the rest of the system.
-  // The flag asLemma is true when the inference was marked that it must be
-  // sent as a lemma.
-  if (asLemma)
+  // we don't pass lemma property p currently, as it is always default
+  return d_im->processDtLemma(d_conc, d_exp, getId());
+}
+
+Node DatatypesInference::processFact(std::vector<Node>& exp,
+                                     ProofGenerator*& pg)
+{
+  // add to the explanation vector if applicable (when non-trivial)
+  if (!d_exp.isNull() && !d_exp.isConst())
   {
-    return d_im->processDtLemma(d_conc, d_exp, getId());
+    exp.push_back(d_exp);
   }
-  return d_im->processDtFact(d_conc, d_exp, getId());
+  return d_im->processDtFact(d_conc, d_exp, getId(), pg);
 }
 
 }  // namespace datatypes
index d31f7b8398e37233296e55c632261b23cdf5fb31..03fe7ad146d3b8d6e1744b14209cff748aaad52d 100644 (file)
@@ -57,11 +57,10 @@ class DatatypesInference : public SimpleTheoryInternalFact
    * set to true.
    */
   static bool mustCommunicateFact(Node n, Node exp);
-  /**
-   * Process this fact, possibly as a fact or as a lemma, depending on the
-   * above method.
-   */
-  bool process(TheoryInferenceManager* im, bool asLemma) override;
+  /** Process lemma */
+  TrustNode processLemma(LemmaProperty& p) override;
+  /** Process internal fact */
+  Node processFact(std::vector<Node>& exp, ProofGenerator*& pg) override;
 
  private:
   /** Pointer to the inference manager */
index b4a536b1429880834a5ea40bf22cd97773567ab5..cf93009bb57b97dd130bd2f9de64748a5ccf2c29 100644 (file)
@@ -79,10 +79,7 @@ void InferenceManager::process()
   doPendingFacts();
 }
 
-void InferenceManager::sendDtLemma(Node lem,
-                                   InferenceId id,
-                                   LemmaProperty p,
-                                   bool doCache)
+void InferenceManager::sendDtLemma(Node lem, InferenceId id, LemmaProperty p)
 {
   if (isProofEnabled())
   {
@@ -90,7 +87,7 @@ void InferenceManager::sendDtLemma(Node lem,
     return;
   }
   // otherwise send as a normal lemma
-  if (lemma(lem, id, p, doCache))
+  if (lemma(lem, id, p))
   {
     d_inferenceLemmas << id;
   }
@@ -122,8 +119,7 @@ bool InferenceManager::sendLemmas(const std::vector<Node>& lemmas)
 
 bool InferenceManager::isProofEnabled() const { return d_ipc != nullptr; }
 
-bool InferenceManager::processDtLemma(
-    Node conc, Node exp, InferenceId id, LemmaProperty p, bool doCache)
+TrustNode InferenceManager::processDtLemma(Node conc, Node exp, InferenceId id)
 {
   // set up a proof constructor
   std::shared_ptr<InferProofCons> ipcl;
@@ -156,38 +152,16 @@ bool InferenceManager::processDtLemma(
     d_lemPg->setProofFor(lem, pn);
   }
   // use trusted lemma
-  TrustNode tlem = TrustNode::mkTrustLemma(lem, d_lemPg.get());
-  if (!trustedLemma(tlem, id))
-  {
-    Trace("dt-lemma-debug") << "...duplicate lemma" << std::endl;
-    return false;
-  }
-  d_inferenceLemmas << id;
-  return true;
+  return TrustNode::mkTrustLemma(lem, d_lemPg.get());
 }
 
-bool InferenceManager::processDtFact(Node conc, Node exp, InferenceId id)
+Node InferenceManager::processDtFact(Node conc,
+                                     Node exp,
+                                     InferenceId id,
+                                     ProofGenerator*& pg)
 {
-  conc = prepareDtInference(conc, exp, id, d_ipc.get());
-  // assert the internal fact, which has the same issue as above
-  bool polarity = conc.getKind() != NOT;
-  TNode atom = polarity ? conc : conc[0];
-  if (isProofEnabled())
-  {
-    std::vector<Node> expv;
-    if (!exp.isNull() && !exp.isConst())
-    {
-      expv.push_back(exp);
-    }
-    assertInternalFact(atom, polarity, id, expv, d_ipc.get());
-  }
-  else
-  {
-    // use version without proofs
-    assertInternalFact(atom, polarity, id, exp);
-  }
-  d_inferenceFacts << id;
-  return true;
+  pg = d_ipc.get();
+  return prepareDtInference(conc, exp, id, d_ipc.get());
 }
 
 Node InferenceManager::prepareDtInference(Node conc,
index 683b696c9a044c51cbdfa45593dcff8bb2dc7af1..9c9a2bcb5fa2827c07903e34b3aa1ee61ba7ba03 100644 (file)
@@ -67,8 +67,7 @@ class InferenceManager : public InferenceManagerBuffered
    */
   void sendDtLemma(Node lem,
                    InferenceId i = InferenceId::UNKNOWN,
-                   LemmaProperty p = LemmaProperty::NONE,
-                   bool doCache = true);
+                   LemmaProperty p = LemmaProperty::NONE);
   /**
    * Send conflict immediately on the output channel
    */
@@ -85,15 +84,11 @@ class InferenceManager : public InferenceManagerBuffered
   /**
    * Process datatype inference as a lemma
    */
-  bool processDtLemma(Node conc,
-                      Node exp,
-                      InferenceId id,
-                      LemmaProperty p = LemmaProperty::NONE,
-                      bool doCache = true);
+  TrustNode processDtLemma(Node conc, Node exp, InferenceId id);
   /**
    * Process datatype inference as a fact
    */
-  bool processDtFact(Node conc, Node exp, InferenceId id);
+  Node processDtFact(Node conc, Node exp, InferenceId id, ProofGenerator*& pg);
   /**
    * Helper function for the above methods. Returns the conclusion, which
    * may be modified so that it is compatible with proofs. If proofs are
index dc7bdc369aa5bb93f1624a29444a274bc0ce27cb..8945fb7354494025bd2e778fa49d965646726845 100644 (file)
@@ -326,8 +326,7 @@ void TheoryDatatypes::postCheck(Effort level)
                     Trace("dt-split-debug") << "Split lemma is : " << lemma << std::endl;
                     d_im.sendDtLemma(lemma,
                                      InferenceId::DATATYPES_SPLIT,
-                                     LemmaProperty::SEND_ATOMS,
-                                     false);
+                                     LemmaProperty::SEND_ATOMS);
                   }
                   if( !options::dtBlastSplits() ){
                     break;
index f4ede969a9ddedd082903893b751136cd5901d1b..0c143f265fbcbe7ae560de9f46a865f52bb5cadd 100644 (file)
@@ -25,8 +25,9 @@ namespace theory {
 InferenceManagerBuffered::InferenceManagerBuffered(Theory& t,
                                                    TheoryState& state,
                                                    ProofNodeManager* pnm,
-                                                   const std::string& name)
-    : TheoryInferenceManager(t, state, pnm, name),
+                                                   const std::string& name,
+                                                   bool cacheLemmas)
+    : TheoryInferenceManager(t, state, pnm, name, cacheLemmas),
       d_processingPendingLemmas(false)
 {
 }
@@ -99,9 +100,9 @@ void InferenceManagerBuffered::doPendingFacts()
   size_t i = 0;
   while (!d_theoryState.isInConflict() && i < d_pendingFact.size())
   {
-    // process this fact, which notice may enqueue more pending facts in this
-    // loop.
-    d_pendingFact[i]->process(this, false);
+    // assert the internal fact, which notice may enqueue more pending facts in
+    // this loop, or result in a conflict.
+    assertInternalFactTheoryInference(d_pendingFact[i].get());
     i++;
   }
   d_pendingFact.clear();
@@ -120,7 +121,7 @@ void InferenceManagerBuffered::doPendingLemmas()
   {
     // process this lemma, which notice may enqueue more pending lemmas in this
     // loop, or clear the lemmas.
-    d_pendingLem[i]->process(this, true);
+    lemmaTheoryInference(d_pendingLem[i].get());
     i++;
   }
   d_pendingLem.clear();
@@ -149,13 +150,40 @@ void InferenceManagerBuffered::clearPendingPhaseRequirements()
   d_pendingReqPhase.clear();
 }
 
+std::size_t InferenceManagerBuffered::numPendingLemmas() const
+{
+  return d_pendingLem.size();
+}
+std::size_t InferenceManagerBuffered::numPendingFacts() const
+{
+  return d_pendingFact.size();
+}
 
-  std::size_t InferenceManagerBuffered::numPendingLemmas() const {
-    return d_pendingLem.size();
-  }
-  std::size_t InferenceManagerBuffered::numPendingFacts() const {
-    return d_pendingFact.size();
-  }
+void InferenceManagerBuffered::lemmaTheoryInference(TheoryInference* lem)
+{
+  // process this lemma
+  LemmaProperty p = LemmaProperty::NONE;
+  TrustNode tlem = lem->processLemma(p);
+  Assert(!tlem.isNull());
+  // send the lemma
+  trustedLemma(tlem, lem->getId(), p);
+}
+
+void InferenceManagerBuffered::assertInternalFactTheoryInference(
+    TheoryInference* fact)
+{
+  // process this fact
+  std::vector<Node> exp;
+  ProofGenerator* pg = nullptr;
+  Node lit = fact->processFact(exp, pg);
+  Assert(!lit.isNull());
+  bool pol = lit.getKind() != NOT;
+  TNode atom = pol ? lit : lit[0];
+  // no double negation or conjunctive conclusions
+  Assert(atom.getKind() != NOT && atom.getKind() != AND);
+  // assert the internal fact
+  assertInternalFact(atom, pol, fact->getId(), exp, pg);
+}
 
 }  // namespace theory
 }  // namespace CVC4
index d12bd40b3944e1a72904dbbe8a4739b49c997269..985bad3bc26b1ffbb291c517321bb7e074af5ce0 100644 (file)
@@ -35,7 +35,8 @@ class InferenceManagerBuffered : public TheoryInferenceManager
   InferenceManagerBuffered(Theory& t,
                            TheoryState& state,
                            ProofNodeManager* pnm,
-                           const std::string& name);
+                           const std::string& name,
+                           bool cacheLemmas = true);
   virtual ~InferenceManagerBuffered() {}
   /**
    * Do we have a pending fact or lemma?
@@ -145,6 +146,19 @@ class InferenceManagerBuffered : public TheoryInferenceManager
   /** Returns the number of pending facts. */
   std::size_t numPendingFacts() const;
 
+  /**
+   * Send the given theory inference as a lemma on the output channel of this
+   * inference manager. This calls TheoryInferenceManager::trustedLemma based
+   * on the provided theory inference.
+   */
+  void lemmaTheoryInference(TheoryInference* lem);
+  /**
+   * Add the given theory inference as an internal fact. This calls
+   * TheoryInferenceManager::assertInternalFact based on the provided theory
+   * inference.
+   */
+  void assertInternalFactTheoryInference(TheoryInference* fact);
+
  protected:
   /** A set of pending inferences to be processed as lemmas */
   std::vector<std::unique_ptr<TheoryInference>> d_pendingLem;
index 464846b1a865f486261132aefcbdcc1d63798d5e..777ca2d9e7dcea0b8bcb1289ab50f8e6e73ef5a0 100644 (file)
@@ -53,13 +53,13 @@ Node TermRegistry::getProxy(Node n)
   d_proxy_to_term[k] = n;
   Node eq = k.eqNode(n);
   Trace("sets-lemma") << "Sets::Lemma : " << eq << " by proxy" << std::endl;
-  d_im.lemma(eq, InferenceId::SETS_PROXY, LemmaProperty::NONE, false);
+  d_im.lemma(eq, InferenceId::SETS_PROXY);
   if (nk == SINGLETON)
   {
     Node slem = nm->mkNode(MEMBER, n[0], k);
     Trace("sets-lemma") << "Sets::Lemma : " << slem << " by singleton"
                         << std::endl;
-    d_im.lemma(slem, InferenceId::SETS_PROXY_SINGLETON, LemmaProperty::NONE, false);
+    d_im.lemma(slem, InferenceId::SETS_PROXY_SINGLETON);
   }
   return k;
 }
@@ -104,7 +104,7 @@ Node TermRegistry::getUnivSet(TypeNode tn)
       Node ulem = nm->mkNode(SUBSET, n1, n2);
       Trace("sets-lemma") << "Sets::Lemma : " << ulem << " by univ-type"
                           << std::endl;
-      d_im.lemma(ulem, InferenceId::SETS_UNIV_TYPE, LemmaProperty::NONE, false);
+      d_im.lemma(ulem, InferenceId::SETS_UNIV_TYPE);
     }
   }
   d_univset[tn] = n;
index 7242c58bc2d2191a6a4bc8e7440dbdf830b6209e..6d87aa94490fa1ca35341901a6a3a2499221ead2 100644 (file)
@@ -25,13 +25,19 @@ InferInfo::InferInfo(InferenceId id): TheoryInference(id), d_sim(nullptr), d_idR
 {
 }
 
-bool InferInfo::process(TheoryInferenceManager* im, bool asLemma)
+TrustNode InferInfo::processLemma(LemmaProperty& p)
 {
-  if (asLemma)
+  return d_sim->processLemma(*this, p);
+}
+
+Node InferInfo::processFact(std::vector<Node>& exp, ProofGenerator*& pg)
+{
+  for (const Node& ec : d_premises)
   {
-    return d_sim->processLemma(*this);
+    utils::flattenOp(kind::AND, ec, exp);
   }
-  return d_sim->processFact(*this);
+  d_sim->processFact(*this, pg);
+  return d_conc;
 }
 
 bool InferInfo::isTrivial() const
index d697f42ae56ccd9c45586ba223907ad7c055f856..176d32e5bc066bc45c11d18b15035fe33f9f4e71 100644 (file)
@@ -74,8 +74,10 @@ class InferInfo : public TheoryInference
  public:
   InferInfo(InferenceId id);
   ~InferInfo() {}
-  /** Process this inference */
-  bool process(TheoryInferenceManager* im, bool asLemma) override;
+  /** Process lemma */
+  TrustNode processLemma(LemmaProperty& p) override;
+  /** Process internal fact */
+  Node processFact(std::vector<Node>& exp, ProofGenerator*& pg) override;
   /** Pointer to the class used for processing this info */
   InferenceManager* d_sim;
   /** Whether it is the reverse form of the above id */
index a161c7854191fb025fc49040c9b326a6015c6f6d..242bf3ab1830703eafd5de92d8c9eefdc081fb2b 100644 (file)
@@ -34,7 +34,7 @@ InferenceManager::InferenceManager(Theory& t,
                                    ExtTheory& e,
                                    SequencesStatistics& statistics,
                                    ProofNodeManager* pnm)
-    : InferenceManagerBuffered(t, s, pnm, "theory::strings"),
+    : InferenceManagerBuffered(t, s, pnm, "theory::strings", false),
       d_state(s),
       d_termReg(tr),
       d_extt(e),
@@ -301,64 +301,23 @@ void InferenceManager::processConflict(const InferInfo& ii)
   trustedConflict(tconf, ii.getId());
 }
 
-bool InferenceManager::processFact(InferInfo& ii)
+void InferenceManager::processFact(InferInfo& ii, ProofGenerator*& pg)
 {
-  // Get the fact(s). There are multiple facts if the conclusion is an AND
-  std::vector<Node> facts;
-  if (ii.d_conc.getKind() == AND)
-  {
-    for (const Node& cc : ii.d_conc)
-    {
-      facts.push_back(cc);
-    }
-  }
-  else
-  {
-    facts.push_back(ii.d_conc);
-  }
   Trace("strings-assert") << "(assert (=> " << ii.getPremises() << " "
                           << ii.d_conc << ")) ; fact " << ii.getId() << std::endl;
   Trace("strings-lemma") << "Strings::Fact: " << ii.d_conc << " from "
                          << ii.getPremises() << " by " << ii.getId()
                          << std::endl;
-  std::vector<Node> exp;
-  for (const Node& ec : ii.d_premises)
-  {
-    utils::flattenOp(AND, ec, exp);
-  }
-  bool ret = false;
-  // convert for each fact
-  for (const Node& fact : facts)
+  if (d_ipc != nullptr)
   {
-    ii.d_conc = fact;
-    bool polarity = fact.getKind() != NOT;
-    TNode atom = polarity ? fact : fact[0];
-    bool curRet = false;
-    if (d_ipc != nullptr)
-    {
-      // ensure the proof generator is ready to explain this fact in the
-      // current SAT context
-      d_ipc->notifyFact(ii);
-      // now, assert the internal fact with d_ipc as proof generator
-      curRet = assertInternalFact(atom, polarity, ii.getId(), exp, d_ipc.get());
-    }
-    else
-    {
-      Node cexp = utils::mkAnd(exp);
-      // without proof generator
-      curRet = assertInternalFact(atom, polarity, ii.getId(), cexp);
-    }
-    ret = ret || curRet;
-    // may be in conflict
-    if (d_state.isInConflict())
-    {
-      break;
-    }
+    // ensure the proof generator is ready to explain this fact in the
+    // current SAT context
+    d_ipc->notifyFact(ii);
+    pg = d_ipc.get();
   }
-  return ret;
 }
 
-bool InferenceManager::processLemma(InferInfo& ii)
+TrustNode InferenceManager::processLemma(InferInfo& ii, LemmaProperty& p)
 {
   Assert(!ii.isTrivial());
   Assert(!ii.isConflict());
@@ -405,7 +364,6 @@ bool InferenceManager::processLemma(InferInfo& ii)
       d_termReg.registerTermAtomic(n, sks.first);
     }
   }
-  LemmaProperty p = LemmaProperty::NONE;
   if (ii.getId() == InferenceId::STRINGS_REDUCTION)
   {
     p |= LemmaProperty::NEEDS_JUSTIFY;
@@ -416,8 +374,7 @@ bool InferenceManager::processLemma(InferInfo& ii)
                          << ii.getId() << std::endl;
   ++(d_statistics.d_lemmasInfer);
 
-  // call the trusted lemma, without caching
-  return trustedLemma(tlem, ii.getId(), p, false);
+  return tlem;
 }
 
 }  // namespace strings
index f16ce718340975cd66c6c2aea481d78cff5f150b..6d2d7f41906bbe2a3664292d24edeecbcfb82ab4 100644 (file)
@@ -249,9 +249,9 @@ class InferenceManager : public InferenceManagerBuffered
 
  private:
   /** Called when ii is ready to be processed as a fact */
-  bool processFact(InferInfo& ii);
+  void processFact(InferInfo& ii, ProofGenerator*& pg);
   /** Called when ii is ready to be processed as a lemma */
-  bool processLemma(InferInfo& ii);
+  TrustNode processLemma(InferInfo& ii, LemmaProperty& p);
   /** Reference to the solver state of the theory of strings. */
   SolverState& d_state;
   /** Reference to the term registry of theory of strings */
index 8ccbb7e1f416e995820c18a6783741b3a475b47f..1089cdff3d7643f2dd932623888b1e16a5e80bc1 100644 (file)
@@ -29,12 +29,11 @@ SimpleTheoryLemma::SimpleTheoryLemma(InferenceId id,
 {
 }
 
-bool SimpleTheoryLemma::process(TheoryInferenceManager* im, bool asLemma)
+TrustNode SimpleTheoryLemma::processLemma(LemmaProperty& p)
 {
   Assert(!d_node.isNull());
-  Assert(asLemma);
-  // send (trusted) lemma on the output channel with property p
-  return im->trustedLemma(TrustNode::mkTrustLemma(d_node, d_pg), getId(), d_property);
+  p = d_property;
+  return TrustNode::mkTrustLemma(d_node, d_pg);
 }
 
 SimpleTheoryInternalFact::SimpleTheoryInternalFact(InferenceId id,
@@ -45,22 +44,12 @@ SimpleTheoryInternalFact::SimpleTheoryInternalFact(InferenceId id,
 {
 }
 
-bool SimpleTheoryInternalFact::process(TheoryInferenceManager* im, bool asLemma)
+Node SimpleTheoryInternalFact::processFact(std::vector<Node>& exp,
+                                           ProofGenerator*& pg)
 {
-  Assert(!asLemma);
-  bool polarity = d_conc.getKind() != NOT;
-  TNode atom = polarity ? d_conc : d_conc[0];
-  // no double negation or conjunctive conclusions
-  Assert(atom.getKind() != NOT && atom.getKind() != AND);
-  if (d_pg != nullptr)
-  {
-    im->assertInternalFact(atom, polarity, getId(), {d_exp}, d_pg);
-  }
-  else
-  {
-    im->assertInternalFact(atom, polarity, getId(), d_exp);
-  }
-  return true;
+  exp.push_back(d_exp);
+  pg = d_pg;
+  return d_conc;
 }
 
 }  // namespace theory
index 9cf787886573759027aad28c8122ff4ce009ceef..847b61786db0249d833ef5c91796db517ad0adad 100644 (file)
@@ -37,31 +37,33 @@ class TheoryInference
  public:
   TheoryInference(InferenceId id) : d_id(id) {}
   virtual ~TheoryInference() {}
+
+  /**
+   * Process lemma, return the trust node to pass to
+   * TheoryInferenceManager::trustedLemma. In addition, the inference should
+   * process any internal side effects of the lemma.
+   *
+   * @param p The property of the lemma which will be passed to trustedLemma
+   * for this inference. If this call does not update p, the default value will
+   * be used.
+   * @return The trust node (of kind TrustNodeKind::LEMMA) corresponding to the
+   * lemma and its proof generator.
+   */
+  virtual TrustNode processLemma(LemmaProperty& p) { return TrustNode::null(); }
   /**
-   * Called by the provided inference manager to process this inference. This
-   * method should make call(s) to inference manager to process this
-   * inference, as well as processing any specific side effects. This method
-   * typically makes a single call to the provided inference manager e.g.
-   * d_im->trustedLemma or d_im->assertInternalFact. Notice it is the sole
-   * responsibility of this class to make this call; the inference manager
-   * does not call itself otherwise when processing pending inferences.
+   * Process internal fact, return the conclusion to pass to
+   * TheoryInferenceManager::assertInternalFact. In addition, the inference
+   * should process any internal side effects of the fact.
    *
-   * @param im The inference manager to use
-   * @param asLemma Whether this inference is being processed as a lemma
-   * during doPendingLemmas (otherwise it is being processed in doPendingFacts).
-   * Typically, this method calls lemma or conflict when asLemma is
-   * true, and assertInternalFact when this flag is false, although this
-   * behavior is (intentionally) not strictly enforced. In particular, the
-   * choice to send a conflict, lemma or fact may depend on local state of the
-   * theory, which may change while the inference is pending. Hence the
-   * implementation of this method may choose to implement any call to the
-   * inference manager. This flag simply serves to track whether the inference
-   * initially was added a pending lemma or not.
-   * @return true if the inference was successfully processed by the inference
-   * manager. This method for instance returns false if it corresponds to a
-   * lemma that was already cached by im and hence was discarded.
+   * @param exp The explanation for the returned conclusion. Each node added to
+   * exp should be a (conjunction of) literals that hold in the current equality
+   * engine.
+   * @return The (possibly negated) conclusion.
    */
-  virtual bool process(TheoryInferenceManager* im, bool asLemma) = 0;
+  virtual Node processFact(std::vector<Node>& exp, ProofGenerator*& pg)
+  {
+    return Node::null();
+  }
 
   /** Get the InferenceId of this theory inference. */
   InferenceId getId() const { return d_id; }
@@ -81,12 +83,8 @@ class SimpleTheoryLemma : public TheoryInference
  public:
   SimpleTheoryLemma(InferenceId id, Node n, LemmaProperty p, ProofGenerator* pg);
   virtual ~SimpleTheoryLemma() {}
-  /**
-   * Send the lemma using inference manager im, return true if the lemma was
-   * sent. It should be the case that asLemma = true or an assertion failure
-   * is thrown.
-   */
-  virtual bool process(TheoryInferenceManager* im, bool asLemma) override;
+  /** Process lemma */
+  TrustNode processLemma(LemmaProperty& p) override;
   /** The lemma to send */
   Node d_node;
   /** The lemma property (see OutputChannel::lemma) */
@@ -109,12 +107,8 @@ class SimpleTheoryInternalFact : public TheoryInference
  public:
   SimpleTheoryInternalFact(InferenceId id, Node conc, Node exp, ProofGenerator* pg);
   virtual ~SimpleTheoryInternalFact() {}
-  /**
-   * Send the lemma using inference manager im, return true if the lemma was
-   * sent. It should be the case that asLemma = false or an assertion failure
-   * is thrown.
-   */
-  virtual bool process(TheoryInferenceManager* im, bool asLemma) override;
+  /** Process internal fact */
+  Node processFact(std::vector<Node>& exp, ProofGenerator*& pg) override;
   /** The lemma to send */
   Node d_conc;
   /** The explanation */
index a1c1545bff1bb7532777b471540ac1407680d701..53a812653d02cc6bd7e9f5c54fcc38a592dbc4c2 100644 (file)
@@ -26,12 +26,14 @@ namespace theory {
 TheoryInferenceManager::TheoryInferenceManager(Theory& t,
                                                TheoryState& state,
                                                ProofNodeManager* pnm,
-                                               const std::string& name)
+                                               const std::string& name,
+                                               bool cacheLemmas)
     : d_theory(t),
       d_theoryState(state),
       d_out(t.getOutputChannel()),
       d_ee(nullptr),
       d_pnm(pnm),
+      d_cacheLemmas(cacheLemmas),
       d_keep(t.getSatContext()),
       d_lemmasSent(t.getUserContext()),
       d_numConflicts(0),
@@ -226,21 +228,19 @@ TrustNode TheoryInferenceManager::explainConflictEqConstantMerge(TNode a,
                   << " mkTrustedConflictEqConstantMerge";
 }
 
-bool TheoryInferenceManager::lemma(TNode lem,
-                                   InferenceId id,
-                                   LemmaProperty p,
-                                   bool doCache)
+bool TheoryInferenceManager::lemma(TNode lem, InferenceId id, LemmaProperty p)
 {
   TrustNode tlem = TrustNode::mkTrustLemma(lem, nullptr);
-  return trustedLemma(tlem, id, p, doCache);
+  return trustedLemma(tlem, id, p);
 }
 
 bool TheoryInferenceManager::trustedLemma(const TrustNode& tlem,
                                           InferenceId id,
-                                          LemmaProperty p,
-                                          bool doCache)
+                                          LemmaProperty p)
 {
-  if (doCache)
+  // if the policy says to cache lemmas, check the cache and return false if
+  // we are a duplicate
+  if (d_cacheLemmas)
   {
     if (!cacheLemma(tlem.getNode(), p))
     {
@@ -259,13 +259,12 @@ bool TheoryInferenceManager::lemmaExp(Node conc,
                                       const std::vector<Node>& exp,
                                       const std::vector<Node>& noExplain,
                                       const std::vector<Node>& args,
-                                      LemmaProperty p,
-                                      bool doCache)
+                                      LemmaProperty p)
 {
   // make the trust node
   TrustNode trn = mkLemmaExp(conc, pfr, exp, noExplain, args);
   // send it on the output channel
-  return trustedLemma(trn, id, p, doCache);
+  return trustedLemma(trn, id, p);
 }
 
 TrustNode TheoryInferenceManager::mkLemmaExp(Node conc,
@@ -290,13 +289,12 @@ bool TheoryInferenceManager::lemmaExp(Node conc,
                                       const std::vector<Node>& exp,
                                       const std::vector<Node>& noExplain,
                                       ProofGenerator* pg,
-                                      LemmaProperty p,
-                                      bool doCache)
+                                      LemmaProperty p)
 {
   // make the trust node
   TrustNode trn = mkLemmaExp(conc, exp, noExplain, pg);
   // send it on the output channel
-  return trustedLemma(trn, id, p, doCache);
+  return trustedLemma(trn, id, p);
 }
 
 TrustNode TheoryInferenceManager::mkLemmaExp(Node conc,
@@ -358,7 +356,6 @@ bool TheoryInferenceManager::assertInternalFact(TNode atom,
                                                 const std::vector<Node>& exp,
                                                 ProofGenerator* pg)
 {
-  Assert(pg != nullptr);
   d_factIdStats << id;
   return processInternalFact(atom, pol, PfRule::ASSUME, exp, {}, pg);
 }
index 0142f814a300da86558959204a6ebc95eaf8ddaa..d3a317cbcf2b1c06b84ac1ea39c52b0e81f0e8d9 100644 (file)
@@ -69,11 +69,23 @@ class TheoryInferenceManager
  public:
   /**
    * Constructor, note that state should be the official state of theory t.
+   *
+   * @param t The theory this inference manager is for
+   * @param state The state of the theory
+   * @param pnm The proof node manager, which if non-null, enables proofs for
+   * this inference manager
+   * @param name The name of the inference manager, which is used for giving
+   * unique names for statistics,
+   * @param cacheLemmas Whether all lemmas sent using this theory inference
+   * manager are added to a user-context dependent cache. This means that
+   * only lemmas that are unique after rewriting are sent to the theory engine
+   * from this inference manager.
    */
   TheoryInferenceManager(Theory& t,
                          TheoryState& state,
                          ProofNodeManager* pnm,
-                         const std::string& name);
+                         const std::string& name,
+                         bool cacheLemmas = true);
   virtual ~TheoryInferenceManager();
   /**
    * Set equality engine, ee is a pointer to the official equality engine
@@ -183,22 +195,16 @@ class TheoryInferenceManager
    *
    * @param tlem The trust node containing the lemma and its proof generator.
    * @param p The property of the lemma
-   * @param doCache If true, we send the lemma only if it has not already been
-   * cached (see cacheLemma), and add it to the cache during this call.
    * @return true if the lemma was sent on the output channel.
    */
   bool trustedLemma(const TrustNode& tlem,
                     InferenceId id,
-                    LemmaProperty p = LemmaProperty::NONE,
-                    bool doCache = true);
+                    LemmaProperty p = LemmaProperty::NONE);
   /**
    * Send lemma lem with property p on the output channel. Same as above, with
    * a node instead of a trust node.
    */
-  bool lemma(TNode lem,
-             InferenceId id,
-             LemmaProperty p = LemmaProperty::NONE,
-             bool doCache = true);
+  bool lemma(TNode lem, InferenceId id, LemmaProperty p = LemmaProperty::NONE);
   /**
    * Explained lemma. This should be called when
    *   ( exp => conc )
@@ -219,7 +225,6 @@ class TheoryInferenceManager
    * equality engine
    * @param args The arguments to the proof step concluding conc
    * @param p The property of the lemma
-   * @param doCache Whether to check and add the lemma to the cache
    * @return true if the lemma was sent on the output channel.
    */
   bool lemmaExp(Node conc,
@@ -228,8 +233,7 @@ class TheoryInferenceManager
                 const std::vector<Node>& exp,
                 const std::vector<Node>& noExplain,
                 const std::vector<Node>& args,
-                LemmaProperty p = LemmaProperty::NONE,
-                bool doCache = true);
+                LemmaProperty p = LemmaProperty::NONE);
   /**
    * Make the trust node for the above method. It is responsibility of the
    * caller to subsequently call trustedLemma with the returned trust node.
@@ -251,7 +255,6 @@ class TheoryInferenceManager
    * equality engine
    * @param pg If non-null, the proof generator who can provide a proof of conc.
    * @param p The property of the lemma
-   * @param doCache Whether to check and add the lemma to the cache
    * @return true if the lemma was sent on the output channel.
    */
   bool lemmaExp(Node conc,
@@ -259,8 +262,7 @@ class TheoryInferenceManager
                 const std::vector<Node>& exp,
                 const std::vector<Node>& noExplain,
                 ProofGenerator* pg = nullptr,
-                LemmaProperty p = LemmaProperty::NONE,
-                bool doCache = true);
+                LemmaProperty p = LemmaProperty::NONE);
   /**
    * Make the trust node for the above method. It is responsibility of the
    * caller to subsequently call trustedLemma with the returned trust node.
@@ -417,6 +419,8 @@ class TheoryInferenceManager
   std::unique_ptr<eq::ProofEqEngine> d_pfee;
   /** The proof node manager of the theory */
   ProofNodeManager* d_pnm;
+  /** Whether this manager caches lemmas */
+  bool d_cacheLemmas;
   /**
    * The keep set of this class. This set is maintained to ensure that
    * facts and their explanations are ref-counted. Since facts and their
index 861da355895a4a601ed00fd3a616a2cda4fdabbe..aa73e34192fc44d60f0a6f52d71f67e6ca503550 100644 (file)
@@ -1179,7 +1179,7 @@ bool SortModel::checkLastCall()
         Node lem = NodeManager::currentNM()->mkNode(
             OR, cl, NodeManager::currentNM()->mkAnd(force_cl));
         Trace("uf-ss-lemma") << "*** Enforce negative cardinality constraint lemma : " << lem << std::endl;
-        d_im.lemma(lem, InferenceId::UF_CARD_ENFORCE_NEGATIVE, LemmaProperty::NONE, false);
+        d_im.lemma(lem, InferenceId::UF_CARD_ENFORCE_NEGATIVE);
         return false;
       }
     }
@@ -1399,7 +1399,7 @@ void CardinalityExtension::assertNode(Node n, bool isDecision)
           Node eqv_lit = NodeManager::currentNM()->mkNode( CARDINALITY_CONSTRAINT, ct, lit[1] );
           eqv_lit = lit.eqNode( eqv_lit );
           Trace("uf-ss-lemma") << "*** Cardinality equiv lemma : " << eqv_lit << std::endl;
-          d_im.lemma(eqv_lit, InferenceId::UF_CARD_EQUIV, LemmaProperty::NONE, false);
+          d_im.lemma(eqv_lit, InferenceId::UF_CARD_EQUIV);
           d_card_assertions_eqv_lemma[lit] = true;
         }
       }
@@ -1528,7 +1528,7 @@ void CardinalityExtension::check(Theory::Effort level)
                     Node eq = Rewriter::rewrite( a.eqNode( b ) );
                     Node lem = NodeManager::currentNM()->mkNode( kind::OR, eq, eq.negate() );
                     Trace("uf-ss-lemma") << "*** Split (no-minimal) : " << lem << std::endl;
-                    d_im.lemma(lem, InferenceId::UF_CARD_SPLIT, LemmaProperty::NONE, false);
+                    d_im.lemma(lem, InferenceId::UF_CARD_SPLIT);
                     d_im.requirePhase(eq, true);
                     type_proc[tn] = true;
                     break;
index 0328080eee267658178ff01a43d6f527716778f6..db8b89d895e9cd2f5258de98842b1daac82f5caa 100644 (file)
@@ -51,7 +51,7 @@ TheoryUF::TheoryUF(context::Context* c,
       d_functionsTerms(c),
       d_symb(u, instanceName),
       d_state(c, u, valuation),
-      d_im(*this, d_state, pnm, "theory::uf"),
+      d_im(*this, d_state, pnm, "theory::uf", false),
       d_notify(d_im, *this)
 {
   d_true = NodeManager::currentNM()->mkConst( true );