Adding support for a master equality engine. Each theory gets the master equality...
authorDejan Jovanović <dejan.jovanovic@gmail.com>
Mon, 26 Nov 2012 17:07:46 +0000 (17:07 +0000)
committerDejan Jovanović <dejan.jovanovic@gmail.com>
Mon, 26 Nov 2012 17:07:46 +0000 (17:07 +0000)
22 files changed:
src/smt/smt_engine.cpp
src/theory/arith/congruence_manager.cpp
src/theory/arith/congruence_manager.h
src/theory/arith/theory_arith.cpp
src/theory/arith/theory_arith.h
src/theory/arrays/theory_arrays.cpp
src/theory/arrays/theory_arrays.h
src/theory/bv/bv_subtheory_eq.cpp
src/theory/bv/bv_subtheory_eq.h
src/theory/bv/theory_bv.cpp
src/theory/bv/theory_bv.h
src/theory/datatypes/theory_datatypes.cpp
src/theory/datatypes/theory_datatypes.h
src/theory/quantifiers/theory_quantifiers.cpp
src/theory/quantifiers/theory_quantifiers.h
src/theory/theory.h
src/theory/theory_engine.cpp
src/theory/theory_engine.h
src/theory/uf/equality_engine.cpp
src/theory/uf/equality_engine.h
src/theory/uf/theory_uf.cpp
src/theory/uf/theory_uf.h

index 7c913578bd1523dcc57604bdd092d092f026b1fd..03834825de9406e29c300e227f25039c53a60421 100644 (file)
@@ -554,6 +554,7 @@ void SmtEngine::finishInit() {
 
   d_theoryEngine->setPropEngine(d_propEngine);
   d_theoryEngine->setDecisionEngine(d_decisionEngine);
+  d_theoryEngine->finishInit();
 
   // [MGD 10/20/2011] keep around in incremental mode, due to a
   // cleanup ordering issue and Nodes/TNodes.  If SAT is popped
index 09410f15bd658a0a1fe27089cc4740009806959d..5ee250c09204bfc294a923f767bb924a245f3666 100644 (file)
@@ -65,6 +65,10 @@ ArithCongruenceManager::Statistics::~Statistics(){
   StatisticsRegistry::unregisterStat(&d_conflicts);
 }
 
+void ArithCongruenceManager::setMasterEqualityEngine(eq::EqualityEngine* eq) {
+  d_ee.setMasterEqualityEngine(eq);
+}
+
 void ArithCongruenceManager::watchedVariableIsZero(Constraint lb, Constraint ub){
   Assert(lb->isLowerBound());
   Assert(ub->isUpperBound());
index 502ea5cf038fc71059309e39aa2d3463b2fd4230..5e2c80a63417c90e623c02c02a991cd1b0e0bda7 100644 (file)
@@ -144,6 +144,8 @@ public:
     return d_explanationMap.find(n) != d_explanationMap.end();
   }
 
+  void setMasterEqualityEngine(eq::EqualityEngine* eq);
+
 private:
   Node externalToInternal(TNode n) const{
     Assert(canExplain(n));
index 141b22dc6eaf44883a5cf305b13989ea685ae460..6ec6c709091fb4bd176cfde45818fc1b6f0e76e7 100644 (file)
@@ -91,6 +91,10 @@ TheoryArith::TheoryArith(context::Context* c, context::UserContext* u, OutputCha
 
 TheoryArith::~TheoryArith(){}
 
+void TheoryArith::setMasterEqualityEngine(eq::EqualityEngine* eq) {
+  d_congruenceManager.setMasterEqualityEngine(eq);
+}
+
 Node skolemFunction(const std::string& name, TypeNode dom, TypeNode range){
   NodeManager* currNM = NodeManager::currentNM();
   TypeNode functionType = currNM->mkFunctionType(dom, range);
index 0773ab7ba01fd60c771ba7ad1f5f1eba871c45ca..ad041208d8eb23c39799321d5ede4d2afe89c478 100644 (file)
@@ -341,6 +341,8 @@ public:
    */
   void preRegisterTerm(TNode n);
 
+  void setMasterEqualityEngine(eq::EqualityEngine* eq);
+
   void check(Effort e);
   void propagate(Effort e);
   Node explain(TNode n);
index f40fea0ba208d0362d03ddebf1ef110a91a159e1..b8c1ace4b6ae4b648cab0d7a5aec2d42bee1cfa9 100644 (file)
@@ -111,7 +111,6 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u, OutputC
   }
 }
 
-
 TheoryArrays::~TheoryArrays() {
 
   StatisticsRegistry::unregisterStat(&d_numRow);
@@ -124,6 +123,10 @@ TheoryArrays::~TheoryArrays() {
 
 }
 
+void TheoryArrays::setMasterEqualityEngine(eq::EqualityEngine* eq) {
+  d_equalityEngine.setMasterEqualityEngine(eq);
+}
+
 
 /////////////////////////////////////////////////////////////////////////////
 // PREPROCESSING
index eaa3ca4311b6be6757d221e1981949218b33ef91..240cfad9a8c9c351e4fe1a1c8fe2fab2c785754a 100644 (file)
@@ -123,6 +123,8 @@ class TheoryArrays : public Theory {
   TheoryArrays(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe);
   ~TheoryArrays();
 
+  void setMasterEqualityEngine(eq::EqualityEngine* eq);
+
   std::string identify() const { return std::string("TheoryArrays"); }
 
   /////////////////////////////////////////////////////////////////////////////
index 17ea7034bfc31ed695bbb6da28adf20dc1b0b70d..ca3e3e35c113f1b0ba28d5cfb1344a7e131eeb22 100644 (file)
@@ -67,6 +67,10 @@ EqualitySolver::EqualitySolver(context::Context* c, TheoryBV* bv)
   }
 }
 
+void EqualitySolver::setMasterEqualityEngine(eq::EqualityEngine* eq) {
+  d_equalityEngine.setMasterEqualityEngine(eq);
+}
+
 void EqualitySolver::preRegister(TNode node) {
   if (!d_useEqualityEngine)
     return;
index 64fe12706825eba26d04f844f1a20be12d6d7eef..2b024cfd496f3a2b00587ede1ed054b5f18579b8 100644 (file)
@@ -63,7 +63,7 @@ class EqualitySolver : public SubtheorySolver {
 public:
 
   EqualitySolver(context::Context* c, TheoryBV* bv);
-
+  void setMasterEqualityEngine(eq::EqualityEngine* eq);
   void  preRegister(TNode node);
   bool  addAssertions(const std::vector<TNode>& assertions, Theory::Effort e);
   void  explain(TNode literal, std::vector<TNode>& assumptions);
index a37ed59c87593a05800a1d67518b1b1e55412401..7acb93cc2c4b01fb2749fed0ffa84e639a06a4ed 100644 (file)
@@ -50,6 +50,11 @@ TheoryBV::TheoryBV(context::Context* c, context::UserContext* u, OutputChannel&
 
 TheoryBV::~TheoryBV() {}
 
+
+void TheoryBV::setMasterEqualityEngine(eq::EqualityEngine* eq) {
+  d_equalitySolver.setMasterEqualityEngine(eq);
+}
+
 TheoryBV::Statistics::Statistics():
   d_avgConflictSize("theory::bv::AvgBVConflictSize"),
   d_solveSubstitutions("theory::bv::NumberOfSolveSubstitutions", 0),
index 933fd87007f2da1e619f38cccd07f223c77953b2..0c8df3fcaf3f7f0928e7f3518409822629204a69 100644 (file)
@@ -50,6 +50,8 @@ public:
   TheoryBV(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe);
   ~TheoryBV();
 
+  void setMasterEqualityEngine(eq::EqualityEngine* eq);
+
   void preRegisterTerm(TNode n);
 
   void check(Effort e);
index 6b576cba8fae1a3ed4dd6963ef77b9c1cd016540..8ec45efb913cefd0dbbc4e5194e10040b3f7dd59 100644 (file)
@@ -56,6 +56,10 @@ TheoryDatatypes::TheoryDatatypes(Context* c, UserContext* u, OutputChannel& out,
 TheoryDatatypes::~TheoryDatatypes() {
 }
 
+void TheoryDatatypes::setMasterEqualityEngine(eq::EqualityEngine* eq) {
+  d_equalityEngine.setMasterEqualityEngine(eq);
+}
+
 TheoryDatatypes::EqcInfo* TheoryDatatypes::getOrMakeEqcInfo( Node n, bool doMake ){
   std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );
   if( !hasEqcInfo( n ) ){
index 16e403e95e99c4bf1eb77a7a5fbfdccb813281bb..5cda9eeaeed49867ab2253030be238fbf81973ed 100644 (file)
@@ -179,6 +179,9 @@ public:
   TheoryDatatypes(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation,
                   const LogicInfo& logicInfo, QuantifiersEngine* qe);
   ~TheoryDatatypes();
+
+  void setMasterEqualityEngine(eq::EqualityEngine* eq);
+
   /** propagate */
   void propagate(Effort effort);
   /** propagate */
index 6e704ba1cca2aa631c6e3a2c06a051fc349a1022..446c9285ec4d5cc11daada2b6985d0af061c539f 100644 (file)
@@ -36,17 +36,22 @@ using namespace CVC4::theory::quantifiers;
 
 TheoryQuantifiers::TheoryQuantifiers(Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe) :
   Theory(THEORY_QUANTIFIERS, c, u, out, valuation, logicInfo, qe),
-  d_numRestarts(0){
+  d_numRestarts(0),
+  d_masterEqualityEngine(0)
+{
   d_numInstantiations = 0;
   d_baseDecLevel = -1;
   out.handleUserAttribute( "axiom", this );
   out.handleUserAttribute( "conjecture", this );
 }
 
-
 TheoryQuantifiers::~TheoryQuantifiers() {
 }
 
+void TheoryQuantifiers::setMasterEqualityEngine(eq::EqualityEngine* eq) {
+  d_masterEqualityEngine = eq;
+}
+
 void TheoryQuantifiers::addSharedTerm(TNode t) {
   Debug("quantifiers-other") << "TheoryQuantifiers::addSharedTerm(): "
                      << t << endl;
index 7b050bb1ca7cf5b26b3b4b00b3c5287f55d1d0a9..12b735497b3069e36ebc177d8c05e733507fddda 100644 (file)
@@ -31,6 +31,7 @@ namespace CVC4 {
 class TheoryEngine;
 
 namespace theory {
+
 namespace quantifiers {
 
 class ModelEngine;
@@ -49,10 +50,14 @@ private:
 
   KEEP_STATISTIC(TimerStat, d_theoryTime, "theory::quantifiers::theoryTime");
 
+  eq::EqualityEngine* d_masterEqualityEngine;
+
 public:
   TheoryQuantifiers(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe);
   ~TheoryQuantifiers();
 
+  void setMasterEqualityEngine(eq::EqualityEngine* eq);
+
   void addSharedTerm(TNode t);
   void notifyEq(TNode lhs, TNode rhs);
   void preRegisterTerm(TNode n);
index 95fe03c829a9f6430acbc25ced15d6a5e0becdcf..4d535a8afe728588f2d97fe4bfda4542f15e47a5 100644 (file)
@@ -54,6 +54,10 @@ namespace rrinst{
 class CandidateGenerator;
 }
 
+namespace eq {
+class EqualityEngine;
+}
+
 /**
  * Information about an assertion for the theories.
  */
@@ -246,7 +250,8 @@ protected:
    * Construct a Theory.
    */
   Theory(TheoryId id, context::Context* satContext, context::UserContext* userContext,
-         OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe) throw()
+         OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo,
+         QuantifiersEngine* qe, eq::EqualityEngine* master = 0) throw()
   : d_id(id)
   , d_satContext(satContext)
   , d_userContext(userContext)
@@ -514,6 +519,11 @@ public:
    */
   virtual void addSharedTerm(TNode n) { }
 
+  /**
+   * Called to set the master equality engine.
+   */
+  virtual void setMasterEqualityEngine(eq::EqualityEngine* eq) { }
+
   /**
    * Return the current theory care graph. Theories should overload computeCareGraph to do
    * the actual computation, and use addCarePair to add pairs to the care graph.
index 4b4316db131d29c13fcfe70ba2592d47f572b55c..cd3b34879a7f15329f05d8678e9810516d516763 100644 (file)
 #include "theory/quantifiers/model_engine.h"
 #include "theory/quantifiers/first_order_model.h"
 
+#include "theory/uf/equality_engine.h"
 
 using namespace std;
 
 using namespace CVC4;
 using namespace CVC4::theory;
 
+void TheoryEngine::finishInit() {
+  if (d_logicInfo.isQuantified()) {
+    Assert(d_masterEqualityEngine == 0);
+    d_masterEqualityEngine = new eq::EqualityEngine(getSatContext(), "theory::master");
+
+    for(TheoryId theoryId = theory::THEORY_FIRST; theoryId != theory::THEORY_LAST; ++ theoryId) {
+      if (d_theoryTable[theoryId]) {
+        d_theoryTable[theoryId]->setMasterEqualityEngine(d_masterEqualityEngine);
+      }
+    }
+  }
+}
+
 TheoryEngine::TheoryEngine(context::Context* context,
                            context::UserContext* userContext,
                            RemoveITE& iteRemover,
@@ -58,6 +72,7 @@ TheoryEngine::TheoryEngine(context::Context* context,
   d_userContext(userContext),
   d_logicInfo(logicInfo),
   d_sharedTerms(this, context),
+  d_masterEqualityEngine(NULL),
   d_quantEngine(NULL),
   d_curr_model(NULL),
   d_curr_model_builder(NULL),
@@ -114,6 +129,8 @@ TheoryEngine::~TheoryEngine() {
 
   delete d_quantEngine;
 
+  delete d_masterEqualityEngine;
+
   StatisticsRegistry::unregisterStat(&d_combineTheoriesTime);
 }
 
@@ -229,21 +246,6 @@ void TheoryEngine::dumpAssertions(const char* tag) {
   }
 }
 
-
-template<typename T, bool doAssert>
-class scoped_vector_clear {
-  vector<T>& d_v;
-public:
-  scoped_vector_clear(vector<T>& v)
-  : d_v(v) {
-    Assert(!doAssert || d_v.empty());
-  }
-  ~scoped_vector_clear() {
-    d_v.clear();
-  }
-
-};
-
 /**
  * Check all (currently-active) theories for conflicts.
  * @param effort the effort level to use
index d6e984f8f672286814c04a2387e1f13ea90b62c4..de872db42fce632882fcc1d08d19a96b422d9fd0 100644 (file)
@@ -76,8 +76,13 @@ namespace theory {
   class Instantiator;
   class TheoryModel;
   class TheoryEngineModelBuilder;
+
+  namespace eq {
+    class EqualityEngine;
+  }
 }/* CVC4::theory namespace */
 
+
 class DecisionEngine;
 
 /**
@@ -123,6 +128,11 @@ class TheoryEngine {
    */
   SharedTermsDatabase d_sharedTerms;
 
+  /**
+   * Master equality engine, to share with theories.
+   */
+  theory::eq::EqualityEngine* d_masterEqualityEngine;
+
   /**
    * The quantifiers engine
    */
@@ -428,6 +438,9 @@ public:
     d_decisionEngine = decisionEngine;
   }
 
+  /** Called when all initialization of options/logic is done */
+  void finishInit();
+
   /**
    * Get a pointer to the underlying propositional engine.
    */
index 90de8d0d28c21c356dd18bd83c54b168706c8b03..636427ed13e340a01bd2ad3e80ca04d98297ded8 100644 (file)
@@ -79,8 +79,9 @@ EqualityEngine::~EqualityEngine() throw(AssertionException) {
 }
 
 
-EqualityEngine::EqualityEngine(context::Context* context, std::string name) 
+EqualityEngine::EqualityEngine(context::Context* context, std::string name)
 : ContextNotifyObj(context)
+, d_masterEqualityEngine(0)
 , d_context(context)
 , d_done(context, false)
 , d_performNotify(true)
@@ -102,6 +103,7 @@ EqualityEngine::EqualityEngine(context::Context* context, std::string name)
 
 EqualityEngine::EqualityEngine(EqualityEngineNotify& notify, context::Context* context, std::string name)
 : ContextNotifyObj(context)
+, d_masterEqualityEngine(0)
 , d_context(context)
 , d_done(context, false)
 , d_performNotify(true)
@@ -121,6 +123,11 @@ EqualityEngine::EqualityEngine(EqualityEngineNotify& notify, context::Context* c
   init();
 }
 
+void EqualityEngine::setMasterEqualityEngine(EqualityEngine* master) {
+  Assert(d_masterEqualityEngine == 0);
+  d_masterEqualityEngine = master;
+}
+
 void EqualityEngine::enqueue(const MergeCandidate& candidate, bool back) {
   Debug("equality") << d_name << "::eq::enqueue(" << d_nodes[candidate.t1Id] << ", " << d_nodes[candidate.t2Id] << ", " << candidate.type << ")" << std::endl;
   if (back) {
@@ -294,6 +301,11 @@ void EqualityEngine::addTerm(TNode t) {
     d_nodeIndividualTrigger[tId] = newTriggerTermSet();
   }
 
+  // If this is not an internal node, add it to the master
+  if (d_masterEqualityEngine && !d_isInternal[result]) {
+    d_masterEqualityEngine->addTerm(t);
+  }
+
   propagate();
 
   Debug("equality") << d_name << "::eq::addTerm(" << t << ") => " << result << std::endl;
@@ -1213,9 +1225,34 @@ void EqualityEngine::propagate() {
       continue;
     }
 
-    // Depending on the merge preference (such as size, or being a constant), merge them
+    // Vector to collect the triggered events
     std::vector<TriggerId> triggers;
-    if ((node2.getSize() > node1.getSize() && !d_isConstant[t1classId]) || d_isConstant[t2classId]) {
+
+    // Figure out the merge preference
+    EqualityNodeId mergeInto = t1classId;
+    if (d_isInternal[t2classId] != d_isInternal[t1classId]) {
+      // We always keep non-internal nodes as representatives: if any node in
+      // the class is non-internal, then the representative will be non-internal
+      if (d_isInternal[t1classId]) {
+        mergeInto = t2classId;
+      } else {
+        mergeInto = t1classId;
+      }
+    } else if (d_isConstant[t2classId] != d_isConstant[t1classId]) {
+      // We always keep constants as representatives: if any (at most one) node
+      // in the class in a constant, then the representative will be a constant
+      if (d_isConstant[t2classId]) {
+        mergeInto = t2classId;
+      } else {
+        mergeInto = t1classId;
+      }
+    } else if (node2.getSize() > node1.getSize()) {
+      // We always merge into the bigger class to reduce the amount of traversing
+      // we need to do
+      mergeInto = t2classId;
+    }
+
+    if (mergeInto == t2classId) {
       Debug("equality") << d_name << "::eq::propagate(): merging " << d_nodes[current.t1Id]<< " into " << d_nodes[current.t2Id] << std::endl;
       d_assertedEqualities.push_back(Equality(t2classId, t1classId));
       d_assertedEqualitiesCount = d_assertedEqualitiesCount + 1;
@@ -1231,6 +1268,12 @@ void EqualityEngine::propagate() {
       }
     }
 
+    // If not merging internal nodes, notify the master
+    if (d_masterEqualityEngine && !d_isInternal[mergeInto]) {
+      d_masterEqualityEngine->assertEqualityInternal(d_nodes[t1classId], d_nodes[t2classId], TNode::null());
+      d_masterEqualityEngine->propagate();
+    }
+
     // Notify the triggers
     if (d_performNotify && !d_done) {
       for (size_t trigger_i = 0, trigger_end = triggers.size(); trigger_i < trigger_end && !d_done; ++ trigger_i) {
index 166362951cfdb19e82a63fe400058d4b6761bd1a..9bc2cb61c458235b1a5869b2ea6198ed6fab9a43 100644 (file)
@@ -151,8 +151,35 @@ class EqualityEngine : public context::ContextNotifyObj {
   /** Default implementation of the notification object */
   static EqualityEngineNotifyNone s_notifyNone;
 
+  /**
+   * Master equality engine that gets all the equality information from
+   * this one, or null if none.
+   */
+  EqualityEngine* d_masterEqualityEngine;
+
 public:
 
+  /**
+   * Initialize the equality engine, given the notification class.
+   */
+  EqualityEngine(EqualityEngineNotify& notify, context::Context* context, std::string name);
+
+  /**
+   * Initialize the equality engine with no notification class.
+   */
+  EqualityEngine(context::Context* context, std::string name);
+
+  /**
+   * Just a destructor.
+   */
+  virtual ~EqualityEngine() throw(AssertionException);
+
+  /**
+   * Set the master equality engine for this one. Master engine will get copies of all
+   * the terms and equalities from this engine.
+   */
+  void setMasterEqualityEngine(EqualityEngine* master);
+
   /** Statistics about the equality engine instance */
   struct Statistics {
     /** Total number of merges */
@@ -639,21 +666,6 @@ private:
 
 public:
 
-  /**
-   * Initialize the equality engine, given the notification class.
-   */
-  EqualityEngine(EqualityEngineNotify& notify, context::Context* context, std::string name);
-
-  /**
-   * Initialize the equality engine with no notification class.
-   */
-  EqualityEngine(context::Context* context, std::string name);
-
-  /**
-   * Just a destructor.
-   */
-  virtual ~EqualityEngine() throw(AssertionException);
-
   /**
    * Adds a term to the term database.
    */
index d76d95adb6ef8cb537acee2faf7c8ac8d1d4887a..e6ae3747c1ed89c06b22cb46d3ad88e0d070e80a 100644 (file)
@@ -45,6 +45,10 @@ TheoryUF::TheoryUF(context::Context* c, context::UserContext* u, OutputChannel&
   d_equalityEngine.addFunctionKind(kind::APPLY_UF);
 }
 
+void TheoryUF::setMasterEqualityEngine(eq::EqualityEngine* eq) {
+  d_equalityEngine.setMasterEqualityEngine(eq);
+}
+
 static Node mkAnd(const std::vector<TNode>& conjunctions) {
   Assert(conjunctions.size() > 0);
 
index f30619e2e77a12dd1a2bbbfd1f46c99370551250..46a17a5e01414b0b4755202461d68ec19398e21a 100644 (file)
@@ -187,6 +187,8 @@ public:
     }
   }
 
+  void setMasterEqualityEngine(eq::EqualityEngine* eq);
+
   void check(Effort);
   void preRegisterTerm(TNode term);
   Node explain(TNode n);