Move equality query utility into quantifiers model (#6186)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Mon, 22 Mar 2021 18:42:46 +0000 (13:42 -0500)
committerGitHub <noreply@github.com>
Mon, 22 Mar 2021 18:42:46 +0000 (18:42 +0000)
This simplifies the initialization of quantifiers engine.

This PR also makes general improvements to EqualityQuery.

src/theory/quantifiers/ematching/candidate_generator.cpp
src/theory/quantifiers/equality_query.cpp
src/theory/quantifiers/equality_query.h
src/theory/quantifiers/first_order_model.cpp
src/theory/quantifiers/first_order_model.h
src/theory/quantifiers/fmf/first_order_model_fmc.cpp
src/theory/quantifiers/fmf/model_engine.cpp
src/theory/quantifiers/instantiate.cpp
src/theory/quantifiers_engine.cpp
src/theory/quantifiers_engine.h

index 4a1a2179864ec5df7a01c97caa80239ad6725e28..4cc912e457603592875cfe8337c5025a6012e9a2 100644 (file)
@@ -18,6 +18,7 @@
 #include "options/quantifiers_options.h"
 #include "smt/smt_engine.h"
 #include "smt/smt_engine_scope.h"
+#include "theory/quantifiers/first_order_model.h"
 #include "theory/quantifiers/inst_match.h"
 #include "theory/quantifiers/instantiate.h"
 #include "theory/quantifiers/quantifiers_state.h"
@@ -193,7 +194,7 @@ Node CandidateGeneratorQEAll::getNextCandidate() {
       if( !nh.isNull() ){
         if (options::instMaxLevel() != -1)
         {
-          nh = d_qe->getInternalRepresentative( nh, d_f, d_index );
+          nh = d_qe->getModel()->getInternalRepresentative(nh, d_f, d_index);
           //don't consider this if already the instantiation is ineligible
           if (!nh.isNull() && !tdb->isTermEligibleForInstantiation(nh, d_f))
           {
index b94076c9f6f1fd077472c1eb61b72b5b85eb95f1..48e5682f20e685b86d0c00f3577a4ab24a16d43e 100644 (file)
@@ -17,6 +17,7 @@
 #include "options/quantifiers_options.h"
 #include "theory/quantifiers/first_order_model.h"
 #include "theory/quantifiers/quantifiers_attributes.h"
+#include "theory/quantifiers/quantifiers_state.h"
 #include "theory/quantifiers/term_util.h"
 
 using namespace std;
@@ -27,8 +28,7 @@ namespace CVC4 {
 namespace theory {
 namespace quantifiers {
 
-EqualityQueryQuantifiersEngine::EqualityQueryQuantifiersEngine(
-    QuantifiersState& qs, FirstOrderModel* m)
+EqualityQuery::EqualityQuery(QuantifiersState& qs, FirstOrderModel* m)
     : d_qstate(qs),
       d_model(m),
       d_eqi_counter(qs.getSatContext()),
@@ -36,18 +36,16 @@ EqualityQueryQuantifiersEngine::EqualityQueryQuantifiersEngine(
 {
 }
 
-EqualityQueryQuantifiersEngine::~EqualityQueryQuantifiersEngine(){
-}
+EqualityQuery::~EqualityQuery() {}
 
-bool EqualityQueryQuantifiersEngine::reset( Theory::Effort e ){
+bool EqualityQuery::reset(Theory::Effort e)
+{
   d_int_rep.clear();
   d_reset_count++;
   return true;
 }
 
-Node EqualityQueryQuantifiersEngine::getInternalRepresentative(Node a,
-                                                               Node q,
-                                                               int index)
+Node EqualityQuery::getInternalRepresentative(Node a, Node q, size_t index)
 {
   Assert(q.isNull() || q.getKind() == FORALL);
   Node r = d_qstate.getRepresentative(a);
@@ -74,7 +72,7 @@ Node EqualityQueryQuantifiersEngine::getInternalRepresentative(Node a,
   TypeNode v_tn = q.isNull() ? a.getType() : q[0][index].getType();
   if (options::quantRepMode() == options::QuantRepMode::EE)
   {
-    int score = getRepScore(r, q, index, v_tn);
+    int32_t score = getRepScore(r, q, index, v_tn);
     if (score >= 0)
     {
       return r;
@@ -94,10 +92,10 @@ Node EqualityQueryQuantifiersEngine::getInternalRepresentative(Node a,
   Trace("internal-rep-select")
       << "Choose representative for equivalence class : " << eqc
       << ", type = " << v_tn << std::endl;
-  int r_best_score = -1;
+  int32_t r_best_score = -1;
   for (const Node& n : eqc)
   {
-    int score = getRepScore(n, q, index, v_tn);
+    int32_t score = getRepScore(n, q, index, v_tn);
     if (score != -2)
     {
       if (r_best.isNull()
@@ -143,7 +141,11 @@ Node EqualityQueryQuantifiersEngine::getInternalRepresentative(Node a,
 
 //helper functions
 
-Node EqualityQueryQuantifiersEngine::getInstance( Node n, const std::vector< Node >& eqc, std::unordered_map<TNode, Node, TNodeHashFunction>& cache ){
+Node EqualityQuery::getInstance(
+    Node n,
+    const std::vector<Node>& eqc,
+    std::unordered_map<TNode, Node, TNodeHashFunction>& cache)
+{
   if(cache.find(n) != cache.end()) {
     return cache[n];
   }
@@ -161,10 +163,7 @@ Node EqualityQueryQuantifiersEngine::getInstance( Node n, const std::vector< Nod
 }
 
 //-2 : invalid, -1 : undesired, otherwise : smaller the score, the better
-int EqualityQueryQuantifiersEngine::getRepScore(Node n,
-                                                Node q,
-                                                int index,
-                                                TypeNode v_tn)
+int32_t EqualityQuery::getRepScore(Node n, Node q, size_t index, TypeNode v_tn)
 {
   if( options::cegqi() && quantifiers::TermUtil::hasInstConstAttr(n) ){  //reject
     return -2;
@@ -174,21 +173,16 @@ int EqualityQueryQuantifiersEngine::getRepScore(Node n,
     //score prefer lowest instantiation level
     if( n.hasAttribute(InstLevelAttribute()) ){
       return n.getAttribute(InstLevelAttribute());
-    }else{
-      return options::instLevelInputOnly() ? -1 : 0;
-    }
-  }else{
-    if (options::quantRepMode() == options::QuantRepMode::FIRST)
-    {
-      //score prefers earliest use of this term as a representative
-      return d_rep_score.find( n )==d_rep_score.end() ? -1 : d_rep_score[n];
-    }
-    else
-    {
-      Assert(options::quantRepMode() == options::QuantRepMode::DEPTH);
-      return quantifiers::TermUtil::getTermDepth( n );
     }
+    return options::instLevelInputOnly() ? -1 : 0;
+  }
+  else if (options::quantRepMode() == options::QuantRepMode::FIRST)
+  {
+    // score prefers earliest use of this term as a representative
+    return d_rep_score.find(n) == d_rep_score.end() ? -1 : d_rep_score[n];
   }
+  Assert(options::quantRepMode() == options::QuantRepMode::DEPTH);
+  return quantifiers::TermUtil::getTermDepth(n);
 }
 
 } /* CVC4::theory::quantifiers namespace */
index 6dec66b5ce7eb025d870286ce571a81c9c69113f..887c54f4296fd34e56f96681b1bb9a8ec7bc5180 100644 (file)
 #include "context/context.h"
 #include "expr/node.h"
 #include "theory/quantifiers/quant_util.h"
-#include "theory/quantifiers/quantifiers_state.h"
 
 namespace CVC4 {
 namespace theory {
 namespace quantifiers {
 
 class FirstOrderModel;
+class QuantifiersState;
 
-/** EqualityQueryQuantifiersEngine class
+/** EqualityQuery class
  *
  * The main method of this class is the function
  * getInternalRepresentative, which is used by instantiation-based methods
@@ -39,18 +39,18 @@ class FirstOrderModel;
  * representative based on the internal heuristic, which is currently based on
  * choosing the term that was previously chosen as a representative earliest.
  */
-class EqualityQueryQuantifiersEngine : public QuantifiersUtil
+class EqualityQuery : public QuantifiersUtil
 {
  public:
-  EqualityQueryQuantifiersEngine(QuantifiersState& qs,
-                                 FirstOrderModel* m);
-  virtual ~EqualityQueryQuantifiersEngine();
+  EqualityQuery(QuantifiersState& qs, FirstOrderModel* m);
+  virtual ~EqualityQuery();
+
   /** reset */
   bool reset(Theory::Effort e) override;
   /* Called for new quantifiers */
   void registerQuantifier(Node q) override {}
   /** identify */
-  std::string identify() const override { return "EqualityQueryQE"; }
+  std::string identify() const override { return "EqualityQuery"; }
   /** gets the current best representative in the equivalence
    * class of a, based on some heuristic. Currently, the default heuristic
    * chooses terms that were previously chosen as representatives
@@ -65,7 +65,7 @@ class EqualityQueryQuantifiersEngine : public QuantifiersUtil
    * Node::null() if all terms in the equivalence class of a
    * are ineligible.
    */
-  Node getInternalRepresentative(Node a, Node q, int index);
+  Node getInternalRepresentative(Node a, Node q, size_t index);
 
  private:
   /** the quantifiers state */
@@ -77,16 +77,16 @@ class EqualityQueryQuantifiersEngine : public QuantifiersUtil
   /** internal representatives */
   std::map< TypeNode, std::map< Node, Node > > d_int_rep;
   /** rep score */
-  std::map< Node, int > d_rep_score;
+  std::map<Node, int32_t> d_rep_score;
   /** the number of times reset( e ) has been called */
-  int d_reset_count;
+  size_t d_reset_count;
   /** processInferences : will merge equivalence classes in master equality engine, if possible */
   bool processInferences( Theory::Effort e );
   /** node contains */
   Node getInstance( Node n, const std::vector< Node >& eqc, std::unordered_map<TNode, Node, TNodeHashFunction>& cache );
   /** get score */
-  int getRepScore( Node n, Node f, int index, TypeNode v_tn );
-}; /* EqualityQueryQuantifiersEngine */
+  int32_t getRepScore(Node n, Node f, size_t index, TypeNode v_tn);
+}; /* EqualityQuery */
 
 }/* CVC4::theory::quantifiers namespace */
 }/* CVC4::theory namespace */
index 001c2f62a55af2422da1c91a808bcd467a184889..fd84dc500c4e00e49300ca378bee2cad38f0d2f0 100644 (file)
 #include "theory/quantifiers/term_registry.h"
 #include "theory/quantifiers/term_util.h"
 
-using namespace std;
 using namespace CVC4::kind;
 using namespace CVC4::context;
-using namespace CVC4::theory::quantifiers::fmcheck;
 
 namespace CVC4 {
 namespace theory {
@@ -51,6 +49,7 @@ FirstOrderModel::FirstOrderModel(QuantifiersState& qs,
       d_qe(nullptr),
       d_qreg(qr),
       d_treg(tr),
+      d_eq_query(qs, this),
       d_forall_asserts(qs.getSatContext()),
       d_forallRlvComputed(false)
 {
@@ -59,6 +58,11 @@ FirstOrderModel::FirstOrderModel(QuantifiersState& qs,
 //!!!!!!!!!!!!!!!!!!!!! temporary (project #15)
 void FirstOrderModel::finishInit(QuantifiersEngine* qe) { d_qe = qe; }
 
+Node FirstOrderModel::getInternalRepresentative(Node a, Node q, size_t index)
+{
+  return d_eq_query.getInternalRepresentative(a, q, index);
+}
+
 void FirstOrderModel::assertQuantifier( Node n ){
   if( n.getKind()==FORALL ){
     d_forall_asserts.push_back( n );
@@ -163,6 +167,8 @@ bool FirstOrderModel::isModelBasis(TNode n)
   return n.getAttribute(ModelBasisAttribute());
 }
 
+EqualityQuery* FirstOrderModel::getEqualityQuery() { return &d_eq_query; }
+
 /** needs check */
 bool FirstOrderModel::checkNeeded() {
   return d_forall_asserts.size()>0;
index c2660d9335d9dde4313bfc6ca16a23ebf0c021b2..b86abd96091d65d46b811793ef8c355f9dfaced1 100644 (file)
@@ -18,7 +18,7 @@
 #define CVC4__FIRST_ORDER_MODEL_H
 
 #include "context/cdlist.h"
-#include "expr/attribute.h"
+#include "theory/quantifiers/equality_query.h"
 #include "theory/theory_model.h"
 #include "theory/uf/theory_uf_model.h"
 
@@ -33,13 +33,6 @@ class QuantifiersState;
 class TermRegistry;
 class QuantifiersRegistry;
 
-namespace fmcheck {
-  class FirstOrderModelFmc;
-}/* CVC4::theory::quantifiers::fmcheck namespace */
-
-struct IsStarAttributeId {};
-typedef expr::Attribute<IsStarAttributeId, bool> IsStarAttribute;
-
 // TODO (#1301) : document and refactor this class
 class FirstOrderModel : public TheoryModel
 {
@@ -52,6 +45,17 @@ class FirstOrderModel : public TheoryModel
   //!!!!!!!!!!!!!!!!!!!!! temporary (project #15)
   /** finish initialize */
   void finishInit(QuantifiersEngine* qe);
+  /** get internal representative
+   *
+   * Choose a term that is equivalent to a in the current context that is the
+   * best term for instantiating the index^th variable of quantified formula q.
+   * If no legal term can be found, we return null. This can occur if:
+   * - a's type is not a subtype of the type of the index^th variable of q,
+   * - a is in an equivalent class with all terms that are restricted not to
+   * appear in instantiations of q, e.g. INST_CONSTANT terms for counterexample
+   * guided instantiation.
+   */
+  Node getInternalRepresentative(Node a, Node q, size_t index);
 
   /** assert quantifier */
   void assertQuantifier( Node n );
@@ -127,6 +131,8 @@ class FirstOrderModel : public TheoryModel
    * Has the term been marked as a model basis term?
    */
   static bool isModelBasis(TNode n);
+  /** Get the equality query */
+  EqualityQuery* getEqualityQuery();
 
  protected:
   //!!!!!!!!!!!!!!!!!!!!!!! TODO (project #15): temporarily available
@@ -135,6 +141,8 @@ class FirstOrderModel : public TheoryModel
   QuantifiersRegistry& d_qreg;
   /** Reference to the term registry */
   TermRegistry& d_treg;
+  /** equality query class */
+  EqualityQuery d_eq_query;
   /** list of quantifiers asserted in the current context */
   context::CDList<Node> d_forall_asserts;
   /** 
index 252261b9cc8b08bdee01a46e5a4d3071f790c43f..9577e296bc9af329699a31037dd02669f3640fa6 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "theory/quantifiers/fmf/first_order_model_fmc.h"
 
+#include "expr/attribute.h"
 #include "theory/quantifiers/fmf/full_model_check.h"
 #include "theory/rewriter.h"
 
@@ -24,6 +25,15 @@ namespace theory {
 namespace quantifiers {
 namespace fmcheck {
 
+/**
+ * Marks that a term represents the entire domain of quantified formula for
+ * the finite model finding fmc algorithm.
+ */
+struct IsStarAttributeId
+{
+};
+using IsStarAttribute = expr::Attribute<IsStarAttributeId, bool>;
+
 FirstOrderModelFmc::FirstOrderModelFmc(QuantifiersState& qs,
                                        QuantifiersRegistry& qr,
                                        TermRegistry& tr,
index 25792673719461fb19e0e1963485dd1c52b565d4..789a7bd7c89c1867aca4bdd525b59646655ceb89 100644 (file)
@@ -166,7 +166,7 @@ int ModelEngine::checkModel(){
       Trace("model-engine-debug") << std::endl;
       Trace("model-engine-debug") << "   Term reps : ";
       for( size_t i=0; i<it->second.size(); i++ ){
-        Node r = d_quantEngine->getInternalRepresentative( it->second[i], Node::null(), 0 );
+        Node r = fm->getInternalRepresentative(it->second[i], Node::null(), 0);
         if (r.isNull())
         {
           // there was an invalid equivalence class
index 6c8d826cbbfc156d1e4914ebfc6fd6ea384c8a2f..be6101b813a6a3c956a02c41085b1b8c93510a8c 100644 (file)
@@ -131,7 +131,7 @@ bool Instantiate::addInstantiation(Node q,
     {
       // pick the best possible representative for instantiation, based on past
       // use and simplicity of term
-      terms[i] = d_qe->getInternalRepresentative(terms[i], q, i);
+      terms[i] = d_qe->getModel()->getInternalRepresentative(terms[i], q, i);
     }
     Trace("inst-add-debug") << " -> " << terms[i] << std::endl;
     if (terms[i].isNull())
index 7d5c4cf1941190a9ee25d11f2da91af3331fe842..68962de72a91e25e003050e27681ddd817e55560 100644 (file)
@@ -62,7 +62,6 @@ QuantifiersEngine::QuantifiersEngine(
       d_treg(tr),
       d_tr_trie(new inst::TriggerTrie),
       d_model(qm),
-      d_eq_query(new quantifiers::EqualityQueryQuantifiersEngine(qstate, qm)),
       d_instantiate(
           new quantifiers::Instantiate(this, qstate, qim, d_qreg, pnm)),
       d_skolemize(new quantifiers::Skolemize(d_qstate, d_pnm)),
@@ -70,7 +69,7 @@ QuantifiersEngine::QuantifiersEngine(
       d_quants_red(qstate.getUserContext())
 {
   // initialize the utilities
-  d_util.push_back(d_eq_query.get());
+  d_util.push_back(d_model->getEqualityQuery());
   // quantifiers registry must come before the remaining utilities
   d_util.push_back(&d_qreg);
   d_util.push_back(tr.getTermDatabase());
@@ -711,10 +710,6 @@ QuantifiersEngine::Statistics::~Statistics(){
   smtStatisticsRegistry()->unregisterStat(&d_red_alpha_equiv);
 }
 
-Node QuantifiersEngine::getInternalRepresentative( Node a, Node q, int index ){
-  return d_eq_query->getInternalRepresentative(a, q, index);
-}
-
 Node QuantifiersEngine::getNameForQuant(Node q) const
 {
   return d_qreg.getNameForQuant(q);
index 625bac40a75edc3991e760007328a27460f5872f..4d3029ca9ce22581f0856a61eeab023cae19e7f1 100644 (file)
@@ -40,7 +40,6 @@ namespace inst {
 class TriggerTrie;
 }
 namespace quantifiers {
-class EqualityQueryQuantifiersEngine;
 class FirstOrderModel;
 class Instantiate;
 class QModelBuilder;
@@ -148,17 +147,6 @@ public:
  /** mark relevant quantified formula, this will indicate it should be checked
   * before the others */
  void markRelevant(Node q);
- /** get internal representative
-  *
-  * Choose a term that is equivalent to a in the current context that is the
-  * best term for instantiating the index^th variable of quantified formula q.
-  * If no legal term can be found, we return null. This can occur if:
-  * - a's type is not a subtype of the type of the index^th variable of q,
-  * - a is in an equivalent class with all terms that are restricted not to
-  * appear in instantiations of q, e.g. INST_CONSTANT terms for counterexample
-  * guided instantiation.
-  */
- Node getInternalRepresentative(Node a, Node q, int index);
  /**
   * Get quantifiers name, which returns a variable corresponding to the name of
   * quantified formula q if q has a name, or otherwise returns q itself.
@@ -249,8 +237,6 @@ public:
   std::unique_ptr<inst::TriggerTrie> d_tr_trie;
   /** extended model object */
   quantifiers::FirstOrderModel* d_model;
-  /** equality query class */
-  std::unique_ptr<quantifiers::EqualityQueryQuantifiersEngine> d_eq_query;
   /** instantiate utility */
   std::unique_ptr<quantifiers::Instantiate> d_instantiate;
   /** skolemize utility */