Simplify lemma interface (#5819)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Thu, 28 Jan 2021 20:01:26 +0000 (14:01 -0600)
committerGitHub <noreply@github.com>
Thu, 28 Jan 2021 20:01:26 +0000 (14:01 -0600)
This makes it so that TheoryEngine::lemma returns void not LemmaStatus.

Currently, there was only one use of LemmaStatus by theory solvers, which was CEGQI using it as a way of getting the preprocessed form of a lemma. This makes it so that there is an explicit method in Valuation for getting the preprocessed form of a term + its skolems and their definition assertions.

It also simplifies a few things, e.g. Valuation calls are forwarded to PropEngine instead of going through TheoryEngine. It fixes a few issues in TermFormulaRemoval related to getSkolems.

22 files changed:
src/prop/prop_engine.cpp
src/prop/prop_engine.h
src/prop/theory_proxy.cpp
src/prop/theory_proxy.h
src/smt/term_formula_removal.cpp
src/smt/term_formula_removal.h
src/theory/combination_care_graph.cpp
src/theory/combination_engine.cpp
src/theory/combination_engine.h
src/theory/engine_output_channel.cpp
src/theory/engine_output_channel.h
src/theory/fp/theory_fp.cpp
src/theory/output_channel.cpp
src/theory/output_channel.h
src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp
src/theory/theory_engine.cpp
src/theory/theory_engine.h
src/theory/theory_test_utils.h
src/theory/valuation.cpp
src/theory/valuation.h
test/unit/theory/theory_engine_white.h
test/unit/theory/theory_white.h

index fb43ebe73d8ecd0633483be9847b7ab06c61e2e1..28159c229b14bfa200fd613917ca047ae30c1e35 100644 (file)
@@ -36,6 +36,7 @@
 #include "prop/theory_proxy.h"
 #include "smt/smt_statistics_registry.h"
 #include "theory/output_channel.h"
+#include "theory/rewriter.h"
 #include "theory/theory_engine.h"
 #include "util/resource_manager.h"
 #include "util/result.h"
@@ -206,7 +207,7 @@ void PropEngine::assertFormula(TNode node) {
   }
 }
 
-Node PropEngine::assertLemma(theory::TrustNode tlemma, theory::LemmaProperty p)
+void PropEngine::assertLemma(theory::TrustNode tlemma, theory::LemmaProperty p)
 {
   bool removable = isLemmaPropertyRemovable(p);
 
@@ -261,20 +262,6 @@ Node PropEngine::assertLemma(theory::TrustNode tlemma, theory::LemmaProperty p)
     }
     d_decisionEngine->addAssertions(assertions, ppLemmasF, ppSkolems);
   }
-
-  // make the return lemma, which the theory engine will use
-  Node retLemma = tplemma.getProven();
-  if (!ppLemmas.empty())
-  {
-    std::vector<Node> lemmas{retLemma};
-    for (const theory::TrustNode& tnl : ppLemmas)
-    {
-      lemmas.push_back(tnl.getProven());
-    }
-    // the returned lemma is the conjunction of all additional lemmas.
-    retLemma = NodeManager::currentNM()->mkNode(kind::AND, lemmas);
-  }
-  return retLemma;
 }
 
 void PropEngine::assertLemmaInternal(theory::TrustNode trn, bool removable)
@@ -441,6 +428,7 @@ Node PropEngine::ensureLiteral(TNode n)
 
 Node PropEngine::getPreprocessedTerm(TNode n)
 {
+  Node rewritten = theory::Rewriter::rewrite(n);
   // must preprocess
   std::vector<theory::TrustNode> newLemmas;
   std::vector<Node> newSkolems;
@@ -453,6 +441,39 @@ Node PropEngine::getPreprocessedTerm(TNode n)
   return tpn.isNull() ? Node(n) : tpn.getNode();
 }
 
+Node PropEngine::getPreprocessedTerm(TNode n,
+                                     std::vector<Node>& skAsserts,
+                                     std::vector<Node>& sks)
+{
+  // get the preprocessed form of the term
+  Node pn = getPreprocessedTerm(n);
+  // initialize the set of skolems and assertions to process
+  std::vector<theory::TrustNode> toProcessAsserts;
+  std::vector<Node> toProcess;
+  d_theoryProxy->getSkolems(pn, toProcessAsserts, toProcess);
+  size_t index = 0;
+  // until fixed point is reached
+  while (index < toProcess.size())
+  {
+    theory::TrustNode ka = toProcessAsserts[index];
+    Node k = toProcess[index];
+    index++;
+    if (std::find(sks.begin(), sks.end(), k) != sks.end())
+    {
+      // already added the skolem to the list
+      continue;
+    }
+    // must preprocess lemmas as well
+    Node kap = getPreprocessedTerm(ka.getProven());
+    skAsserts.push_back(kap);
+    sks.push_back(k);
+    // get the skolems in the preprocessed form of the lemma ka
+    d_theoryProxy->getSkolems(kap, toProcessAsserts, toProcess);
+  }
+  // return the preprocessed term
+  return pn;
+}
+
 void PropEngine::push()
 {
   Assert(!d_inCheckSat) << "Sat solver in solve()!";
index 493dbfe01718eaa3ff76be3c49fdbfac7da61bcf..f7561d9453ec5a38f9d135642612063a2cb3bbe0 100644 (file)
@@ -145,9 +145,8 @@ class PropEngine
    *
    * @param trn the trust node storing the formula to assert
    * @param p the properties of the lemma
-   * @return the (preprocessed) lemma
    */
-  Node assertLemma(theory::TrustNode tlemma, theory::LemmaProperty p);
+  void assertLemma(theory::TrustNode tlemma, theory::LemmaProperty p);
 
   /**
    * If ever n is decided upon, it must be in the given phase.  This
@@ -209,6 +208,20 @@ class PropEngine
    * if preprocessing n involves introducing new skolems.
    */
   Node getPreprocessedTerm(TNode n);
+  /**
+   * Same as above, but also compute the skolems in n and in the lemmas
+   * corresponding to their definition.
+   *
+   * Note this will include skolems that occur in the definition lemma
+   * for all skolems in sks. This is run until a fixed point is reached.
+   * For example, if k1 has definition (ite A (= k1 k2) (= k1 x)) where k2 is
+   * another skolem introduced by term formula removal, then calling this
+   * method on (P k1) will include both k1 and k2 in sks, and their definitions
+   * in skAsserts.
+   */
+  Node getPreprocessedTerm(TNode n,
+                           std::vector<Node>& skAsserts,
+                           std::vector<Node>& sks);
 
   /**
    * Push the context level.
index c604c47f7d58a70a6976a3515ef2e3e8b1822a84..a6d570bc228516fb5bad20beebda46e43d4eb9d1 100644 (file)
@@ -194,6 +194,20 @@ theory::TrustNode TheoryProxy::removeItes(
   return rtf.run(node, newLemmas, newSkolems, true);
 }
 
+void TheoryProxy::getSkolems(TNode node,
+                             std::vector<theory::TrustNode>& skAsserts,
+                             std::vector<Node>& sks)
+{
+  RemoveTermFormulas& rtf = d_tpp.getRemoveTermFormulas();
+  std::unordered_set<Node, NodeHashFunction> skolems;
+  rtf.getSkolems(node, skolems);
+  for (const Node& k : skolems)
+  {
+    sks.push_back(k);
+    skAsserts.push_back(rtf.getLemmaForSkolem(k));
+  }
+}
+
 void TheoryProxy::preRegister(Node n) { d_theoryEngine->preRegister(n); }
 
 }/* CVC4::prop namespace */
index 57115d660013ac772bd8da3e233714c167358804..ac79cf967ca1528e3e917d86a6b7308b8d21b3f1 100644 (file)
@@ -118,6 +118,17 @@ class TheoryProxy : public Registrar
   theory::TrustNode removeItes(TNode node,
                                std::vector<theory::TrustNode>& newLemmas,
                                std::vector<Node>& newSkolems);
+  /**
+   * Get the skolems within node and their corresponding definitions, store
+   * them in sks and skAsserts respectively. Note that this method does not
+   * necessary include all of the skolems in skAsserts. In other words, it
+   * collects from node only. To compute all skolems that node depends on
+   * requires calling this method again on each lemma in skAsserts until a
+   * fixed point is reached.
+   */
+  void getSkolems(TNode node,
+                  std::vector<theory::TrustNode>& skAsserts,
+                  std::vector<Node>& sks);
   /** Preregister term */
   void preRegister(Node n) override;
 
index f77ae7b49d4077d11fc721cdbde96872e4a13aff..9a856fc149c908443c65f2985616f2359b05eb3b 100644 (file)
@@ -517,21 +517,9 @@ Node RemoveTermFormulas::getSkolemForNode(Node k) const
   return Node::null();
 }
 
-bool RemoveTermFormulas::getSkolems(
+void RemoveTermFormulas::getSkolems(
     TNode n, std::unordered_set<Node, NodeHashFunction>& skolems) const
 {
-  // if n was unchanged by term formula removal, just return immediately
-  std::pair<Node, uint32_t> initial(n, d_rtfc.initialValue());
-  TermFormulaCache::const_iterator itc = d_tfCache.find(initial);
-  if (itc != d_tfCache.end())
-  {
-    if (itc->second == n)
-    {
-      return false;
-    }
-  }
-  // otherwise, traverse it
-  bool ret = false;
   std::unordered_set<TNode, TNodeHashFunction> visited;
   std::unordered_set<TNode, TNodeHashFunction>::iterator it;
   std::vector<TNode> visit;
@@ -549,16 +537,15 @@ bool RemoveTermFormulas::getSkolems(
       {
         if (d_lemmaCache.find(cur) != d_lemmaCache.end())
         {
-          // technically could already be in skolems if skolems was non-empty,
-          // regardless set return value to true.
           skolems.insert(cur);
-          ret = true;
         }
       }
-      visit.insert(visit.end(), cur.begin(), cur.end());
+      else
+      {
+        visit.insert(visit.end(), cur.begin(), cur.end());
+      }
     }
   } while (!visit.empty());
-  return ret;
 }
 
 Node RemoveTermFormulas::getAxiomFor(Node n)
index ac264418266e1a4c1e35601b9dd0ef78a7ef6f7c..0c026a5fe5120708cda4932ff0c57b6ff2d1b439 100644 (file)
@@ -130,12 +130,10 @@ class RemoveTermFormulas {
    * Get the set of skolems introduced by this class that occur in node n,
    * add them to skolems.
    *
-   * This method uses an optimization that returns false immediately if n
-   * was unchanged by term formula removal, based on the initial context.
-   *
-   * Return true if any nodes were added to skolems.
+   * @param n The node to traverse
+   * @param skolems The set where the skolems are added
    */
-  bool getSkolems(TNode n,
+  void getSkolems(TNode n,
                   std::unordered_set<Node, NodeHashFunction>& skolems) const;
 
   /**
index 45a709d19019b5ae82353e2eafb2774123f0c0ce..402eeeb26306afb09c2dcb0a8c0e6801c7d2d6f0 100644 (file)
@@ -85,7 +85,7 @@ void CombinationCareGraph::combineTheories()
     // This is supposed to force preference to follow what the theory models
     // already have but it doesn't seem to make a big difference - need to
     // explore more -Clark
-    Node e = d_te.ensureLiteral(equality);
+    Node e = d_valuation.ensureLiteral(equality);
     propEngine->requirePhase(e, true);
   }
 }
index 71eac49a04be2af794a10500203f4f096448c6d3..21450df046da213e9990ee01a2298b0618cbc898 100644 (file)
@@ -28,6 +28,7 @@ CombinationEngine::CombinationEngine(TheoryEngine& te,
                                      const std::vector<Theory*>& paraTheories,
                                      ProofNodeManager* pnm)
     : d_te(te),
+      d_valuation(&te),
       d_pnm(pnm),
       d_logicInfo(te.getLogicInfo()),
       d_paraTheories(paraTheories),
index 765a49d689aae52ab72c5742777c43a15e9704dd..5bc9d7bdda69b0fab4076f8e7fd34c494c814bb5 100644 (file)
@@ -24,6 +24,7 @@
 #include "theory/ee_manager.h"
 #include "theory/model_manager.h"
 #include "theory/shared_solver.h"
+#include "theory/valuation.h"
 
 namespace CVC4 {
 
@@ -104,6 +105,8 @@ class CombinationEngine
   void sendLemma(TrustNode trn, TheoryId atomsTo);
   /** Reference to the theory engine */
   TheoryEngine& d_te;
+  /** Valuation for the engine */
+  Valuation d_valuation;
   /** The proof node manager */
   ProofNodeManager* d_pnm;
   /** Logic info of theory engine (cached) */
index 0aa56a381db75dc09a5f651af6f2fd7a3b3535b5..1105b918b17ac573f2d9b62ce30cebd87fe9aeab 100644 (file)
@@ -67,7 +67,7 @@ void EngineOutputChannel::safePoint(ResourceManager::Resource r)
   }
 }
 
-theory::LemmaStatus EngineOutputChannel::lemma(TNode lemma, LemmaProperty p)
+void EngineOutputChannel::lemma(TNode lemma, LemmaProperty p)
 {
   Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma("
                          << lemma << ")"
@@ -76,15 +76,13 @@ theory::LemmaStatus EngineOutputChannel::lemma(TNode lemma, LemmaProperty p)
   d_engine->d_outputChannelUsed = true;
 
   TrustNode tlem = TrustNode::mkTrustLemma(lemma);
-  theory::LemmaStatus result = d_engine->lemma(
-      tlem,
-      p,
-      isLemmaPropertySendAtoms(p) ? d_theory : theory::THEORY_LAST,
-      d_theory);
-  return result;
+  d_engine->lemma(tlem,
+                  p,
+                  isLemmaPropertySendAtoms(p) ? d_theory : theory::THEORY_LAST,
+                  d_theory);
 }
 
-theory::LemmaStatus EngineOutputChannel::splitLemma(TNode lemma, bool removable)
+void EngineOutputChannel::splitLemma(TNode lemma, bool removable)
 {
   Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma("
                          << lemma << ")" << std::endl;
@@ -95,8 +93,7 @@ theory::LemmaStatus EngineOutputChannel::splitLemma(TNode lemma, bool removable)
                        << std::endl;
   TrustNode tlem = TrustNode::mkTrustLemma(lemma);
   LemmaProperty p = removable ? LemmaProperty::REMOVABLE : LemmaProperty::NONE;
-  theory::LemmaStatus result = d_engine->lemma(tlem, p, d_theory);
-  return result;
+  d_engine->lemma(tlem, p, d_theory);
 }
 
 bool EngineOutputChannel::propagate(TNode literal)
@@ -172,7 +169,7 @@ void EngineOutputChannel::trustedConflict(TrustNode pconf)
   d_engine->conflict(pconf, d_theory);
 }
 
-LemmaStatus EngineOutputChannel::trustedLemma(TrustNode plem, LemmaProperty p)
+void EngineOutputChannel::trustedLemma(TrustNode plem, LemmaProperty p)
 {
   Trace("theory::lemma") << "EngineOutputChannel<" << d_theory
                          << ">::trustedLemma(" << plem << ")" << std::endl;
@@ -184,11 +181,10 @@ LemmaStatus EngineOutputChannel::trustedLemma(TrustNode plem, LemmaProperty p)
   ++d_statistics.lemmas;
   d_engine->d_outputChannelUsed = true;
   // now, call the normal interface for lemma
-  return d_engine->lemma(
-      plem,
-      p,
-      isLemmaPropertySendAtoms(p) ? d_theory : theory::THEORY_LAST,
-      d_theory);
+  d_engine->lemma(plem,
+                  p,
+                  isLemmaPropertySendAtoms(p) ? d_theory : theory::THEORY_LAST,
+                  d_theory);
 }
 
 }  // namespace theory
index 7a59dbf2a58bf372d39d302f5aea44bc9451106e..c53feabc5704702ef16802bddfd58f5e393bcf11 100644 (file)
@@ -48,10 +48,9 @@ class EngineOutputChannel : public theory::OutputChannel
   void conflict(TNode conflictNode) override;
   bool propagate(TNode literal) override;
 
-  theory::LemmaStatus lemma(TNode lemma,
-                            LemmaProperty p = LemmaProperty::NONE) override;
+  void lemma(TNode lemma, LemmaProperty p = LemmaProperty::NONE) override;
 
-  theory::LemmaStatus splitLemma(TNode lemma, bool removable = false) override;
+  void splitLemma(TNode lemma, bool removable = false) override;
 
   void demandRestart() override;
 
@@ -76,8 +75,8 @@ class EngineOutputChannel : public theory::OutputChannel
    * by the generator pfg. Apart from pfg, the interface for this method is
    * the same as calling OutputChannel::lemma on lem.
    */
-  LemmaStatus trustedLemma(TrustNode plem,
-                           LemmaProperty p = LemmaProperty::NONE) override;
+  void trustedLemma(TrustNode plem,
+                    LemmaProperty p = LemmaProperty::NONE) override;
 
  protected:
   /**
index 0a8c4ee0eedcafa6f66f3ac2992e5878a99e8263..a71a2d0eb54f58605afdbb5fd8b3598972fe0f76 100644 (file)
@@ -918,9 +918,6 @@ void TheoryFp::handleLemma(Node node) {
   Trace("fp") << "TheoryFp::handleLemma(): asserting " << node << std::endl;
   // Preprocess has to be true because it contains embedded ITEs
   d_out->lemma(node, LemmaProperty::PREPROCESS);
-  // Ignore the LemmaStatus structure for now...
-
-  return;
 }
 
 bool TheoryFp::propagateLit(TNode node)
index 91f30514cd41c6dab7788695c82d5e53748f10b9..e63b784863a32410278b7690593490bb04057a16 100644 (file)
@@ -84,19 +84,7 @@ std::ostream& operator<<(std::ostream& out, LemmaProperty p)
   return out;
 }
 
-LemmaStatus::LemmaStatus(TNode rewrittenLemma, unsigned level)
-    : d_rewrittenLemma(rewrittenLemma), d_level(level)
-{
-}
-
-TNode LemmaStatus::getRewrittenLemma() const { return d_rewrittenLemma; }
-
-unsigned LemmaStatus::getLevel() const { return d_level; }
-
-LemmaStatus OutputChannel::split(TNode n)
-{
-  return splitLemma(n.orNode(n.notNode()));
-}
+void OutputChannel::split(TNode n) { splitLemma(n.orNode(n.notNode())); }
 
 void OutputChannel::trustedConflict(TrustNode pconf)
 {
@@ -104,7 +92,7 @@ void OutputChannel::trustedConflict(TrustNode pconf)
                 << std::endl;
 }
 
-LemmaStatus OutputChannel::trustedLemma(TrustNode lem, LemmaProperty p)
+void OutputChannel::trustedLemma(TrustNode lem, LemmaProperty p)
 {
   Unreachable() << "OutputChannel::trustedLemma: no implementation"
                 << std::endl;
index 197e42a99eee57705f73cf9643bd5789a1790195..c3d4b6a4261e5cd3716cf056ffea05338fa42aef 100644 (file)
@@ -72,29 +72,6 @@ std::ostream& operator<<(std::ostream& out, LemmaProperty p);
 
 class Theory;
 
-/**
- * A LemmaStatus, returned from OutputChannel::lemma(), provides information
- * about the lemma added.  In particular, it contains the T-rewritten lemma
- * for inspection and the user-level at which the lemma will reside.
- */
-class LemmaStatus {
- public:
-  LemmaStatus(TNode rewrittenLemma, unsigned level);
-
-  /** Get the T-rewritten form of the lemma. */
-  TNode getRewrittenLemma() const;
-  /**
-   * Get the user-level at which the lemma resides.  After this user level
-   * is popped, the lemma is un-asserted from the SAT layer.  This level
-   * will be 0 if the lemma didn't reach the SAT layer at all.
-   */
-  unsigned getLevel() const;
-
- private:
-  Node d_rewrittenLemma;
-  unsigned d_level;
-}; /* class LemmaStatus */
-
 /**
  * Generic "theory output channel" interface.
  *
@@ -150,10 +127,8 @@ class OutputChannel {
    *
    * @param n - a theory lemma valid at decision level 0
    * @param p The properties of the lemma
-   * @return the "status" of the lemma, including user level at which
-   * the lemma resides; the lemma will be removed when this user level pops
    */
-  virtual LemmaStatus lemma(TNode n, LemmaProperty p = LemmaProperty::NONE) = 0;
+  virtual void lemma(TNode n, LemmaProperty p = LemmaProperty::NONE) = 0;
 
   /**
    * Request a split on a new theory atom.  This is equivalent to
@@ -161,9 +136,9 @@ class OutputChannel {
    *
    * @param n - a theory atom; must be of Boolean type
    */
-  LemmaStatus split(TNode n);
+  void split(TNode n);
 
-  virtual LemmaStatus splitLemma(TNode n, bool removable = false) = 0;
+  virtual void splitLemma(TNode n, bool removable = false) = 0;
 
   /**
    * If a decision is made on n, it must be in the phase specified.
@@ -227,8 +202,8 @@ class OutputChannel {
    * by the generator pfg. Apart from pfg, the interface for this method is
    * the same as OutputChannel.
    */
-  virtual LemmaStatus trustedLemma(TrustNode lem,
-                                   LemmaProperty p = LemmaProperty::NONE);
+  virtual void trustedLemma(TrustNode lem,
+                            LemmaProperty p = LemmaProperty::NONE);
   //---------------------------- end new proof
 }; /* class OutputChannel */
 
index 118e7023c12afb377ba81239a96c2adbdf820b8d..8a8678749228bafea5bc3457e1330775973ec43a 100644 (file)
@@ -373,13 +373,20 @@ void InstStrategyCegqi::registerCounterexampleLemma(Node q, Node lem)
   {
     ce_vars.push_back(tutil->getInstantiationConstant(q, i));
   }
-  CegInstantiator* cinst = getInstantiator(q);
-  LemmaStatus status =
-      d_quantEngine->getOutputChannel().lemma(lem, LemmaProperty::PREPROCESS);
-  Node ppLem = status.getRewrittenLemma();
+  // send the lemma
+  d_quantEngine->getOutputChannel().lemma(lem, LemmaProperty::PREPROCESS);
+  // get the preprocessed form of the lemma we just sent
+  std::vector<Node> skolems;
+  std::vector<Node> skAsserts;
+  Node ppLem = d_quantEngine->getValuation().getPreprocessedTerm(
+      lem, skAsserts, skolems);
+  std::vector<Node> lemp{ppLem};
+  lemp.insert(lemp.end(), skAsserts.begin(), skAsserts.end());
+  ppLem = NodeManager::currentNM()->mkAnd(lemp);
   Trace("cegqi-debug") << "Counterexample lemma (post-preprocess): " << ppLem
                        << std::endl;
   std::vector<Node> auxLems;
+  CegInstantiator* cinst = getInstantiator(q);
   cinst->registerCounterexampleLemma(ppLem, ce_vars, auxLems);
   for (unsigned i = 0, size = auxLems.size(); i < size; i++)
   {
index 18d9bb572ce36890281610c3a1769f5b7bc022ba..3492f97a9253592a05e6b979e4e7b86e2396f3f7 100644 (file)
@@ -1161,19 +1161,6 @@ Node TheoryEngine::getModelValue(TNode var) {
   return theoryOf(Theory::theoryOf(var.getType()))->getModelValue(var);
 }
 
-
-Node TheoryEngine::ensureLiteral(TNode n) {
-  Trace("ensureLiteral") << "ensureLiteral rewriting: " << n << std::endl;
-  Node rewritten = Rewriter::rewrite(n);
-  return d_propEngine->ensureLiteral(rewritten);
-}
-
-Node TheoryEngine::getPreprocessedTerm(TNode n)
-{
-  Node rewritten = Rewriter::rewrite(n);
-  return d_propEngine->getPreprocessedTerm(rewritten);
-}
-
 void TheoryEngine::printSynthSolution( std::ostream& out ) {
   if( d_quantEngine ){
     d_quantEngine->printSynthSolution( out );
@@ -1340,10 +1327,10 @@ void TheoryEngine::ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::The
   }
 }
 
-theory::LemmaStatus TheoryEngine::lemma(theory::TrustNode tlemma,
-                                        theory::LemmaProperty p,
-                                        theory::TheoryId atomsTo,
-                                        theory::TheoryId from)
+void TheoryEngine::lemma(theory::TrustNode tlemma,
+                         theory::LemmaProperty p,
+                         theory::TheoryId atomsTo,
+                         theory::TheoryId from)
 {
   // For resource-limiting (also does a time check).
   // spendResource();
@@ -1393,20 +1380,24 @@ theory::LemmaStatus TheoryEngine::lemma(theory::TrustNode tlemma,
     printer.toStreamCmdCheckSat(out, n);
   }
 
-  Node retLemma = d_propEngine->assertLemma(tlemma, p);
+  // assert the lemma
+  d_propEngine->assertLemma(tlemma, p);
 
   // If specified, we must add this lemma to the set of those that need to be
-  // justified, where note we pass all auxiliary lemmas in lemmas, since these
-  // by extension must be justified as well.
+  // justified, where note we pass all auxiliary lemmas in skAsserts as well,
+  // since these by extension must be justified as well.
   if (d_relManager != nullptr && isLemmaPropertyNeedsJustify(p))
   {
+    std::vector<Node> skAsserts;
+    std::vector<Node> sks;
+    Node retLemma =
+        d_propEngine->getPreprocessedTerm(tlemma.getProven(), skAsserts, sks);
     d_relManager->notifyPreprocessedAssertion(retLemma);
+    d_relManager->notifyPreprocessedAssertions(skAsserts);
   }
 
   // Mark that we added some lemmas
   d_lemmasAdded = true;
-
-  return theory::LemmaStatus(retLemma, d_userContext->getLevel());
 }
 
 void TheoryEngine::conflict(theory::TrustNode tconflict, TheoryId theoryId)
index 747c1ccc900b8ad4e72a7f86ba7814ae0caec29e..46498e71a68a3073dcc85116772ff168c0efaf49 100644 (file)
@@ -274,13 +274,11 @@ class TheoryEngine {
    * @param p the properties of the lemma.
    * @param atomsTo the theory that atoms of the lemma should be sent to
    * @param from the theory that sent the lemma
-   * @return a lemma status, containing the lemma and context information
-   * about when it was sent.
    */
-  theory::LemmaStatus lemma(theory::TrustNode node,
-                            theory::LemmaProperty p,
-                            theory::TheoryId atomsTo = theory::THEORY_LAST,
-                            theory::TheoryId from = theory::THEORY_LAST);
+  void lemma(theory::TrustNode node,
+             theory::LemmaProperty p,
+             theory::TheoryId atomsTo = theory::THEORY_LAST,
+             theory::TheoryId from = theory::THEORY_LAST);
 
   /** Enusre that the given atoms are send to the given theory */
   void ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::TheoryId theory);
@@ -648,20 +646,6 @@ class TheoryEngine {
    * has (or null if none);
    */
   Node getModelValue(TNode var);
-
-  /**
-   * Takes a literal and returns an equivalent literal that is guaranteed to be
-   * a SAT literal. This rewrites and preprocesses n, which notice may involve
-   * adding clauses to the SAT solver if preprocessing n involves introducing
-   * new skolems.
-   */
-  Node ensureLiteral(TNode n);
-  /**
-   * This returns the theory-preprocessed form of term n. This rewrites and
-   * preprocesses n, which notice may involve adding clauses to the SAT solver
-   * if preprocessing n involves introducing new skolems.
-   */
-  Node getPreprocessedTerm(TNode n);
   /**
    * Print solution for synthesis conjectures found by ce_guided_instantiation module
    */
index 003e439ae85f2677712a4ef4d3079bd10aa9c396..f37e4c942f0674cf8697988e8a16ea13c12a5cc5 100644 (file)
@@ -77,26 +77,18 @@ public:
     return true;
   }
 
-  LemmaStatus lemma(TNode n, LemmaProperty p) override
-  {
-    push(LEMMA, n);
-    return LemmaStatus(Node::null(), 0);
-  }
+  void lemma(TNode n, LemmaProperty p) override { push(LEMMA, n); }
 
-  LemmaStatus trustedLemma(TrustNode n, LemmaProperty p) override
+  void trustedLemma(TrustNode n, LemmaProperty p) override
   {
     push(LEMMA, n.getNode());
-    return LemmaStatus(Node::null(), 0);
   }
 
   void requirePhase(TNode, bool) override {}
   void setIncomplete() override {}
   void handleUserAttribute(const char* attr, theory::Theory* t) override {}
 
-  LemmaStatus splitLemma(TNode n, bool removable = false) override {
-    push(LEMMA, n);
-    return LemmaStatus(Node::null(), 0);
-  }
+  void splitLemma(TNode n, bool removable = false) override { push(LEMMA, n); }
 
   void clear() { d_callHistory.clear(); }
 
index b8ee5d41c1830c9427d0e9c5f371f276146b3a8b..6fae8421dac37585263ad4937bcc5ae86719f504 100644 (file)
@@ -156,13 +156,21 @@ void Valuation::setIrrelevantKind(Kind k)
 
 Node Valuation::ensureLiteral(TNode n) {
   Assert(d_engine != nullptr);
-  return d_engine->ensureLiteral(n);
+  return d_engine->getPropEngine()->ensureLiteral(n);
 }
 
 Node Valuation::getPreprocessedTerm(TNode n)
 {
   Assert(d_engine != nullptr);
-  return d_engine->getPreprocessedTerm(n);
+  return d_engine->getPropEngine()->getPreprocessedTerm(n);
+}
+
+Node Valuation::getPreprocessedTerm(TNode n,
+                                    std::vector<Node>& skAsserts,
+                                    std::vector<Node>& sks)
+{
+  Assert(d_engine != nullptr);
+  return d_engine->getPropEngine()->getPreprocessedTerm(n, skAsserts, sks);
 }
 
 bool Valuation::isDecision(Node lit) const {
index 06555687222dffb0af0475c1f4e69d1134037fca..9759309fa96d0f53723b1e923837db430db9657f 100644 (file)
@@ -159,6 +159,13 @@ public:
    * @return The preprocessed form of n
    */
   Node getPreprocessedTerm(TNode n);
+  /**
+   * Same as above, but also tracks the skolems and their corresponding
+   * definitions in sks and skAsserts respectively.
+   */
+  Node getPreprocessedTerm(TNode n,
+                           std::vector<Node>& skAsserts,
+                           std::vector<Node>& sks);
 
   /**
    * Returns whether the given lit (which must be a SAT literal) is a decision
index 97da7eb8bb3a7d475c157cc367902769f4a837a6..04bc79b3a68c068902061aa046dc400743d52926 100644 (file)
@@ -56,8 +56,7 @@ using namespace std;
 class FakeOutputChannel : public OutputChannel {
   void conflict(TNode n) override { Unimplemented(); }
   bool propagate(TNode n) override { Unimplemented(); }
-  LemmaStatus lemma(TNode n,
-                    LemmaProperty p = LemmaProperty::NONE) override
+  void lemma(TNode n, LemmaProperty p = LemmaProperty::NONE) override
   {
     Unimplemented();
   }
@@ -66,7 +65,7 @@ class FakeOutputChannel : public OutputChannel {
   void handleUserAttribute(const char* attr, Theory* t) override {
     Unimplemented();
   }
-  LemmaStatus splitLemma(TNode n, bool removable) override { Unimplemented(); }
+  void splitLemma(TNode n, bool removable) override { Unimplemented(); }
 }; /* class FakeOutputChannel */
 
 template<TheoryId theory>
index 9f23dbad6a6720c91b3106b0b0a688e4470c85b2..4b6c1a0643ae5924a793bf10ee9d7f0b26508e92 100644 (file)
@@ -54,17 +54,12 @@ class TestOutputChannel : public OutputChannel {
     return true;
   }
 
-  LemmaStatus lemma(TNode n,
-                    LemmaProperty p = LemmaProperty::NONE) override
+  void lemma(TNode n, LemmaProperty p = LemmaProperty::NONE) override
   {
     push(LEMMA, n);
-    return LemmaStatus(Node::null(), 0);
   }
 
-  LemmaStatus splitLemma(TNode n, bool removable) override {
-    push(LEMMA, n);
-    return LemmaStatus(Node::null(), 0);
-  }
+  void splitLemma(TNode n, bool removable) override { push(LEMMA, n); }
 
   void requirePhase(TNode, bool) override { Unreachable(); }
   void setIncomplete() override { Unreachable(); }