More flexible design for model manager distributed (#4976)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Sun, 20 Sep 2020 15:59:36 +0000 (10:59 -0500)
committerGitHub <noreply@github.com>
Sun, 20 Sep 2020 15:59:36 +0000 (10:59 -0500)
This PR makes it so that the distributed model manager can be used independently of the architecture for equality engine management for theories, meaning the choice of using a separate equality engine for the model can be done in both the current distributed architecture, or the proposed central architecture (where there would be 2 equality engines, the central one and the model one). The "central model manager" on the other hand will only be combined with the central architecture. This will make it easier to test the centralized equality engine manager, since all things related to model construction can be preserved when using a central architecture.

This PR moves some of the responsibilities from the (distributed) equality engine manager to the distributed model manager, including the management of the context of the model equality engine and the allocation of its equality engine.

This PR is not intended to make any behavior changes to the current architecture.

src/theory/combination_engine.cpp
src/theory/ee_manager.cpp
src/theory/ee_manager.h
src/theory/ee_manager_distributed.cpp
src/theory/ee_manager_distributed.h
src/theory/model_manager.cpp
src/theory/model_manager.h
src/theory/model_manager_distributed.cpp
src/theory/model_manager_distributed.h
src/theory/theory_model.cpp
src/theory/theory_model.h

index 5c9e6713ba8668f1499b1c07c54c44983eb5561d..7ff2848dfb275d9a0b2ce7a06cf98566010efef7 100644 (file)
@@ -18,8 +18,6 @@
 #include "theory/care_graph.h"
 #include "theory/ee_manager_distributed.h"
 #include "theory/model_manager_distributed.h"
-#include "theory/shared_terms_database.h"
-#include "theory/term_registration_visitor.h"
 #include "theory/theory_engine.h"
 
 namespace CVC4 {
@@ -46,11 +44,9 @@ void CombinationEngine::finishInit()
   if (options::eeMode() == options::EqEngineMode::DISTRIBUTED)
   {
     // make the distributed equality engine manager
-    std::unique_ptr<EqEngineManagerDistributed> eeDistributed(
-        new EqEngineManagerDistributed(d_te));
+    d_eemanager.reset(new EqEngineManagerDistributed(d_te));
     // make the distributed model manager
-    d_mmanager.reset(new ModelManagerDistributed(d_te, *eeDistributed.get()));
-    d_eemanager = std::move(eeDistributed);
+    d_mmanager.reset(new ModelManagerDistributed(d_te, *d_eemanager.get()));
   }
   else
   {
@@ -65,13 +61,9 @@ void CombinationEngine::finishInit()
   d_eemanager->initializeTheories();
 
   Assert(d_mmanager != nullptr);
-  // initialize the model manager
-  d_mmanager->finishInit();
-
-  // initialize equality engine of the model using the equality engine manager
-  TheoryModel* m = d_mmanager->getModel();
+  // initialize the model manager, based on the notify object of this class
   eq::EqualityEngineNotify* meen = getModelEqualityEngineNotify();
-  d_eemanager->initializeModel(m, meen);
+  d_mmanager->finishInit(meen);
 }
 
 const EeTheoryInfo* CombinationEngine::getEeTheoryInfo(TheoryId tid) const
@@ -118,7 +110,7 @@ void CombinationEngine::sendLemma(TrustNode trn, TheoryId atomsTo)
 
 void CombinationEngine::resetRound()
 {
-  // do nothing
+  // compute the relevant terms?
 }
 
 }  // namespace theory
index bec355e7dda59f6718b01f8d7a5b6149418a3d8f..ad6892e31ec5ffdf77a39bdda117078a1b99d21b 100644 (file)
 
 #include "theory/ee_manager.h"
 
+#include "theory/theory_model.h"
+
 namespace CVC4 {
 namespace theory {
 
+EqEngineManager::EqEngineManager(TheoryEngine& te) : d_te(te) {}
+
 const EeTheoryInfo* EqEngineManager::getEeTheoryInfo(TheoryId tid) const
 {
   std::map<TheoryId, EeTheoryInfo>::const_iterator it = d_einfo.find(tid);
@@ -27,5 +31,17 @@ const EeTheoryInfo* EqEngineManager::getEeTheoryInfo(TheoryId tid) const
   return nullptr;
 }
 
+eq::EqualityEngine* EqEngineManager::allocateEqualityEngine(EeSetupInfo& esi,
+                                                            context::Context* c)
+{
+  if (esi.d_notify != nullptr)
+  {
+    return new eq::EqualityEngine(
+        *esi.d_notify, c, esi.d_name, esi.d_constantsAreTriggers);
+  }
+  // the theory doesn't care about explicit notifications
+  return new eq::EqualityEngine(c, esi.d_name, esi.d_constantsAreTriggers);
+}
+
 }  // namespace theory
 }  // namespace CVC4
index aa4bcc66c9c2e1fe1edb333998ea6a92aae80b3e..14175037e20767c48e10755444a69e5e6b939fd1 100644 (file)
@@ -25,6 +25,9 @@
 #include "theory/uf/equality_engine.h"
 
 namespace CVC4 {
+
+class TheoryEngine;
+
 namespace theory {
 
 /**
@@ -48,9 +51,10 @@ struct EeTheoryInfo
 class EqEngineManager
 {
  public:
+  EqEngineManager(TheoryEngine& te);
   virtual ~EqEngineManager() {}
   /**
-   * Finish initialize, called by TheoryEngine::finishInit after theory
+   * Initialize theories, called during TheoryEngine::finishInit after theory
    * objects have been created but prior to their final initialization. This
    * sets up equality engines for all theories.
    *
@@ -58,16 +62,6 @@ class EqEngineManager
    * the lifetime of TheoryEngine (during finishInit).
    */
   virtual void initializeTheories() = 0;
-  /**
-   * Finish initialize, called by TheoryEngine::finishInit after theory
-   * objects have been created but prior to their final initialization. This
-   * sets up equality engines for all theories.
-   *
-   * This method is context-independent, and is applied once during
-   * the lifetime of TheoryEngine (during finishInit).
-   */
-  virtual void initializeModel(TheoryModel* m,
-                               eq::EqualityEngineNotify* notify) = 0;
   /**
    * Get the equality engine theory information for theory with the given id.
    */
@@ -80,7 +74,13 @@ class EqEngineManager
    */
   virtual eq::EqualityEngine* getCoreEqualityEngine() = 0;
 
+  /** Allocate equality engine that is context-dependent on c with info esi */
+  eq::EqualityEngine* allocateEqualityEngine(EeSetupInfo& esi,
+                                             context::Context* c);
+
  protected:
+  /** Reference to the theory engine */
+  TheoryEngine& d_te;
   /** Information related to the equality engine, per theory. */
   std::map<TheoryId, EeTheoryInfo> d_einfo;
 };
index ea618fcaea395fb8e3b1d24f2c7700ab590bd463..7abd602197e261cc3fe30ec35617019c39af490a 100644 (file)
@@ -21,14 +21,12 @@ namespace CVC4 {
 namespace theory {
 
 EqEngineManagerDistributed::EqEngineManagerDistributed(TheoryEngine& te)
-    : d_te(te), d_masterEENotify(nullptr)
+    : EqEngineManager(te), d_masterEENotify(nullptr)
 {
 }
 
 EqEngineManagerDistributed::~EqEngineManagerDistributed()
 {
-  // pop the model context which we pushed on initialization
-  d_modelEeContext.pop();
 }
 
 void EqEngineManagerDistributed::initializeTheories()
@@ -96,62 +94,16 @@ void EqEngineManagerDistributed::initializeTheories()
   }
 }
 
-void EqEngineManagerDistributed::initializeModel(
-    TheoryModel* m, eq::EqualityEngineNotify* notify)
-{
-  Assert(m != nullptr);
-  // initialize the model equality engine
-  EeSetupInfo esim;
-  if (m->needsEqualityEngine(esim))
-  {
-    // use the provided notification object
-    esim.d_notify = notify;
-    d_modelEqualityEngine.reset(
-        allocateEqualityEngine(esim, &d_modelEeContext));
-    m->setEqualityEngine(d_modelEqualityEngine.get());
-  }
-  else
-  {
-    AlwaysAssert(false) << "Expected model to use equality engine";
-  }
-  m->finishInit();
-  // We push a context during initialization since the model is cleared during
-  // collectModelInfo using pop/push.
-  d_modelEeContext.push();
-}
-
 void EqEngineManagerDistributed::MasterNotifyClass::eqNotifyNewClass(TNode t)
 {
   // adds t to the quantifiers term database
   d_quantEngine->eqNotifyNewClass(t);
 }
 
-context::Context* EqEngineManagerDistributed::getModelEqualityEngineContext()
-{
-  return &d_modelEeContext;
-}
-
-eq::EqualityEngine* EqEngineManagerDistributed::getModelEqualityEngine()
-{
-  return d_modelEqualityEngine.get();
-}
-
 eq::EqualityEngine* EqEngineManagerDistributed::getCoreEqualityEngine()
 {
   return d_masterEqualityEngine.get();
 }
 
-eq::EqualityEngine* EqEngineManagerDistributed::allocateEqualityEngine(
-    EeSetupInfo& esi, context::Context* c)
-{
-  if (esi.d_notify != nullptr)
-  {
-    return new eq::EqualityEngine(
-        *esi.d_notify, c, esi.d_name, esi.d_constantsAreTriggers);
-  }
-  // the theory doesn't care about explicit notifications
-  return new eq::EqualityEngine(c, esi.d_name, esi.d_constantsAreTriggers);
-}
-
 }  // namespace theory
 }  // namespace CVC4
index dd4608c9ac5ebb085af7da6525592d6a70612ff0..bbdd9988137ced550ea6183a06b40dd64ceb270e 100644 (file)
@@ -25,9 +25,6 @@
 #include "theory/uf/equality_engine.h"
 
 namespace CVC4 {
-
-class TheoryEngine;
-
 namespace theory {
 
 /**
@@ -55,27 +52,9 @@ class EqEngineManagerDistributed : public EqEngineManager
    * per theories and connects them to a master equality engine.
    */
   void initializeTheories() override;
-  /**
-   * Initialize model. This method allocates a new equality engine for the
-   * model.
-   */
-  void initializeModel(TheoryModel* m,
-                       eq::EqualityEngineNotify* notify) override;
-  /**
-   * Get the model equality engine context. This is a dummy context that is
-   * used for clearing the contents of the model's equality engine via
-   * pop/push.
-   */
-  context::Context* getModelEqualityEngineContext();
-  /** get the model equality engine */
-  eq::EqualityEngine* getModelEqualityEngine();
   /** get the core equality engine */
   eq::EqualityEngine* getCoreEqualityEngine() override;
-
  private:
-  /** Allocate equality engine that is context-dependent on c with info esi */
-  eq::EqualityEngine* allocateEqualityEngine(EeSetupInfo& esi,
-                                             context::Context* c);
   /** notify class for master equality engine */
   class MasterNotifyClass : public theory::eq::EqualityEngineNotify
   {
@@ -106,21 +85,10 @@ class EqEngineManagerDistributed : public EqEngineManager
     /** Pointer to quantifiers engine */
     QuantifiersEngine* d_quantEngine;
   };
-  /** Reference to the theory engine */
-  TheoryEngine& d_te;
   /** The master equality engine notify class */
   std::unique_ptr<MasterNotifyClass> d_masterEENotify;
   /** The master equality engine. */
   std::unique_ptr<eq::EqualityEngine> d_masterEqualityEngine;
-  /**
-   * A dummy context for the model equality engine, so we can clear it
-   * independently of search context.
-   */
-  context::Context d_modelEeContext;
-  /**
-   * The equality engine of the model.
-   */
-  std::unique_ptr<eq::EqualityEngine> d_modelEqualityEngine;
 };
 
 }  // namespace theory
index 89daa922c0966e93001c0af70ce54e442845d3e2..530aec19096112b1b28adcf4bfaac67fb214aca9 100644 (file)
 namespace CVC4 {
 namespace theory {
 
-ModelManager::ModelManager(TheoryEngine& te)
+ModelManager::ModelManager(TheoryEngine& te, EqEngineManager& eem)
     : d_te(te),
       d_logicInfo(te.getLogicInfo()),
+      d_eem(eem),
+      d_modelEqualityEngine(nullptr),
+      d_modelEqualityEngineAlloc(nullptr),
       d_model(nullptr),
       d_modelBuilder(nullptr),
       d_modelBuilt(false),
@@ -33,7 +36,7 @@ ModelManager::ModelManager(TheoryEngine& te)
 
 ModelManager::~ModelManager() {}
 
-void ModelManager::finishInit()
+void ModelManager::finishInit(eq::EqualityEngineNotify* notify)
 {
   // construct the model
   const LogicInfo& logicInfo = d_te.getLogicInfo();
@@ -61,6 +64,7 @@ void ModelManager::finishInit()
     d_modelBuilder = d_alocModelBuilder.get();
   }
   // notice that the equality engine of the model has yet to be assigned.
+  initializeModelEqEngine(notify);
 }
 
 void ModelManager::resetModel()
@@ -209,7 +213,6 @@ void ModelManager::collectTerms(TheoryId tid,
     // only add to term set if a relevant kind
     if (irrKinds.find(k) == irrKinds.end())
     {
-      Assert(Theory::theoryOf(cur) == tid);
       termSet.insert(cur);
     }
     // traverse owned terms, don't go under quantifiers
index 9511f2779e4dd04918952df985f557cd8bce471d..b84cd29d7f70aed44263262c555ff87b4cf2179c 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <memory>
 
+#include "theory/ee_manager.h"
 #include "theory/logic_info.h"
 #include "theory/theory_model.h"
 #include "theory/theory_model_builder.h"
@@ -39,10 +40,16 @@ namespace theory {
 class ModelManager
 {
  public:
-  ModelManager(TheoryEngine& te);
+  ModelManager(TheoryEngine& te, EqEngineManager& eem);
   virtual ~ModelManager();
-  /** Finish initializing this class. */
-  void finishInit();
+  /**
+   * Finish initializing this class, which allocates the model, the model
+   * builder as well as the equality engine of the model. The equality engine
+   * to use is determined by the virtual method initializeModelEqEngine.
+   *
+   * @param notify The object that wants to be notified for callbacks occurring
+   */
+  void finishInit(eq::EqualityEngineNotify* notify);
   /** Reset model, called during full effort check before the model is built */
   void resetModel();
   /**
@@ -84,6 +91,12 @@ class ModelManager
   virtual bool finishBuildModel() const = 0;
   //------------------------ end finer grained control over model building
  protected:
+  /**
+   * Initialize model equality engine. This is called at the end of finish
+   * init, after we have created a model object but before we have assigned it
+   * an equality engine.
+   */
+  virtual void initializeModelEqEngine(eq::EqualityEngineNotify* notify) = 0;
   /**
    * Collect model Boolean variables.
    * This asserts the values of all boolean variables to the equality engine of
@@ -112,6 +125,17 @@ class ModelManager
   TheoryEngine& d_te;
   /** Logic info of theory engine (cached) */
   const LogicInfo& d_logicInfo;
+  /** The equality engine manager */
+  EqEngineManager& d_eem;
+  /**
+   * A dummy context for the model equality engine, so we can clear it
+   * independently of search context.
+   */
+  context::Context d_modelEeContext;
+  /** Pointer to the equality engine of the model */
+  eq::EqualityEngine* d_modelEqualityEngine;
+  /** The equality engine of the model, if we allocated it */
+  std::unique_ptr<eq::EqualityEngine> d_modelEqualityEngineAlloc;
   /** The model object we are using */
   theory::TheoryModel* d_model;
   /** The model object we have allocated (if one exists) */
index c2e1d65218b2a98a3be731c2a1cbe5defc5c6df8..4d47329b5dfeb07be71ae633b10783bef6a1b9e9 100644 (file)
 namespace CVC4 {
 namespace theory {
 
-ModelManagerDistributed::ModelManagerDistributed(
-    TheoryEngine& te, EqEngineManagerDistributed& eem)
-    : ModelManager(te), d_eem(eem)
+ModelManagerDistributed::ModelManagerDistributed(TheoryEngine& te,
+                                                 EqEngineManager& eem)
+    : ModelManager(teeem)
 {
 }
 
-ModelManagerDistributed::~ModelManagerDistributed() {}
+ModelManagerDistributed::~ModelManagerDistributed()
+{
+  // pop the model context which we pushed on initialization
+  d_modelEeContext.pop();
+}
+
+void ModelManagerDistributed::initializeModelEqEngine(
+    eq::EqualityEngineNotify* notify)
+{
+  // initialize the model equality engine, use the provided notification object,
+  // which belongs e.g. to CombinationModelBased
+  EeSetupInfo esim;
+  esim.d_notify = notify;
+  esim.d_name = d_model->getName() + "::ee";
+  esim.d_constantsAreTriggers = false;
+  d_modelEqualityEngineAlloc.reset(
+      d_eem.allocateEqualityEngine(esim, &d_modelEeContext));
+  d_modelEqualityEngine = d_modelEqualityEngineAlloc.get();
+  // finish initializing the model
+  d_model->finishInit(d_modelEqualityEngine);
+  // We push a context during initialization since the model is cleared during
+  // collectModelInfo using pop/push.
+  d_modelEeContext.push();
+}
 
 bool ModelManagerDistributed::prepareModel()
 {
@@ -34,9 +57,8 @@ bool ModelManagerDistributed::prepareModel()
                          << std::endl;
 
   // push/pop to clear the equality engine of the model
-  context::Context* meec = d_eem.getModelEqualityEngineContext();
-  meec->pop();
-  meec->push();
+  d_modelEeContext.pop();
+  d_modelEeContext.push();
 
   // Collect model info from the theories
   Trace("model-builder") << "ModelManagerDistributed: Collect model info..."
@@ -76,6 +98,7 @@ bool ModelManagerDistributed::prepareModel()
 
 bool ModelManagerDistributed::finishBuildModel() const
 {
+  // do not use relevant terms
   if (!d_modelBuilder->buildModel(d_model))
   {
     Trace("model-builder") << "ModelManager: fail build model" << std::endl;
index 2f86c0b00d47978fc54c32a9310a2af5629c13fb..2cf35d039f31dfe521d8050b69d56587eefc9cc3 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <memory>
 
-#include "theory/ee_manager_distributed.h"
+#include "theory/ee_manager.h"
 #include "theory/model_manager.h"
 
 namespace CVC4 {
@@ -29,17 +29,20 @@ class TheoryEngine;
 namespace theory {
 
 /**
- * Manager for building models in a distributed architecture. Its prepare
- * model method uses collectModelInfo to assert all equalities from the equality
- * engine of each theory into the equality engine of the model. It additionally
- * uses the model equality engine context to clear the information from
- * the model's equality engine, as maintained by the distributed equality
- * engine manager.
+ * Manager for building models where the equality engine of the model is
+ * a separate instance. Notice that this manager can be used regardless of the
+ * method for managing the equality engines of the theories (which is the
+ * responsibility of the equality engine manager eem referenced by this class).
+ *
+ * Its prepare model method uses collectModelInfo to assert all equalities from
+ * the equality engine of each theory into the equality engine of the model. It
+ * additionally uses the model equality engine context to clear the information
+ * from the model's equality engine, which is maintained by this class.
  */
 class ModelManagerDistributed : public ModelManager
 {
  public:
-  ModelManagerDistributed(TheoryEngine& te, EqEngineManagerDistributed& eem);
+  ModelManagerDistributed(TheoryEngine& te, EqEngineManager& eem);
   ~ModelManagerDistributed();
 
   /** Prepare the model, as described above. */
@@ -49,13 +52,9 @@ class ModelManagerDistributed : public ModelManager
    * model, return true if successful.
    */
   bool finishBuildModel() const override;
-
  protected:
-  /**
-   * Distributed equality engine manager, which maintains the context of the
-   * model's equality engine.
-   */
-  EqEngineManagerDistributed& d_eem;
+  /** Initialize model equality engine */
+  void initializeModelEqEngine(eq::EqualityEngineNotify* notify) override;
 };
 
 }  // namespace theory
index da9f28d013e8eab50445d25329e37f7c7f774272..53267727bf0e5302423b8d6fa10e2d769a9b1c28 100644 (file)
@@ -44,22 +44,10 @@ TheoryModel::TheoryModel(context::Context* c,
 
 TheoryModel::~TheoryModel() {}
 
-void TheoryModel::setEqualityEngine(eq::EqualityEngine* ee)
+void TheoryModel::finishInit(eq::EqualityEngine* ee)
 {
+  Assert(ee != nullptr);
   d_equalityEngine = ee;
-}
-
-bool TheoryModel::needsEqualityEngine(EeSetupInfo& esi)
-{
-  // no notifications
-  esi.d_name = d_name;
-  esi.d_constantsAreTriggers = false;
-  return true;
-}
-
-void TheoryModel::finishInit()
-{
-  Assert(d_equalityEngine != nullptr);
   // The kinds we are treating as function application in congruence
   d_equalityEngine->addFunctionKind(kind::APPLY_UF, false, options::ufHo());
   d_equalityEngine->addFunctionKind(kind::HO_APPLY);
@@ -772,5 +760,7 @@ std::vector< Node > TheoryModel::getFunctionsToAssign() {
   return funcs_to_assign;
 }
 
+const std::string& TheoryModel::getName() const { return d_name; }
+
 } /* namespace CVC4::theory */
 } /* namespace CVC4 */
index aea3463c80ec055b1d7405b8558cfcf43c1d271c..0de52b5ff91b8a2e3b7f01fe09dfab14f43f1fc8 100644 (file)
@@ -82,17 +82,10 @@ class TheoryModel : public Model
 public:
   TheoryModel(context::Context* c, std::string name, bool enableFuncModels);
   ~TheoryModel() override;
-  //---------------------------- initialization
-  /** Called to set the equality engine. */
-  void setEqualityEngine(eq::EqualityEngine* ee);
   /**
-   * Returns true if we need an equality engine, this has the same contract
-   * as Theory::needsEqualityEngine.
+   * Finish init, where ee is the equality engine the model should use.
    */
-  bool needsEqualityEngine(EeSetupInfo& esi);
-  /** Finish init */
-  void finishInit();
-  //---------------------------- end initialization
+  void finishInit(eq::EqualityEngine* ee);
 
   /** reset the model */
   virtual void reset();
@@ -355,6 +348,9 @@ public:
   */
   std::vector< Node > getFunctionsToAssign();
   //---------------------------- end function values
+  /** Get the name of this model */
+  const std::string& getName() const;
+
  protected:
   /** Unique name of this model */
   std::string d_name;