Generalize CandidateRewriteDatabase to ExprMiner (#2340)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Fri, 14 Sep 2018 02:48:25 +0000 (21:48 -0500)
committerGitHub <noreply@github.com>
Fri, 14 Sep 2018 02:48:25 +0000 (21:48 -0500)
src/Makefile.am
src/options/quantifiers_options.toml
src/theory/quantifiers/candidate_rewrite_database.cpp
src/theory/quantifiers/candidate_rewrite_database.h
src/theory/quantifiers/expr_miner.cpp [new file with mode: 0644]
src/theory/quantifiers/expr_miner.h [new file with mode: 0644]
src/theory/quantifiers/expr_miner_manager.cpp [new file with mode: 0644]
src/theory/quantifiers/expr_miner_manager.h [new file with mode: 0644]
src/theory/quantifiers/sygus/ce_guided_conjecture.cpp
src/theory/quantifiers/sygus/ce_guided_conjecture.h
test/regress/regress1/rr-verify/bv-term.sy

index 77fd455bbf1ea2cf11039232c7617c6849380ad5..a8edbf1fd93f1ac83a3cacc632e438c3e996291f 100644 (file)
@@ -470,6 +470,10 @@ libcvc4_la_SOURCES = \
        theory/quantifiers/equality_query.h \
        theory/quantifiers/equality_infer.cpp \
        theory/quantifiers/equality_infer.h \
+       theory/quantifiers/expr_miner.cpp \
+       theory/quantifiers/expr_miner.h \
+       theory/quantifiers/expr_miner_manager.cpp \
+       theory/quantifiers/expr_miner_manager.h \
        theory/quantifiers/extended_rewrite.cpp \
        theory/quantifiers/extended_rewrite.h \
        theory/quantifiers/first_order_model.cpp \
index a4fca6d3c90d2437b6f49a0aa28fdffe63767f3a..7b58f955a9175166e342336b356dc2cf71a27bda 100644 (file)
@@ -1306,11 +1306,11 @@ header = "options/quantifiers_options.h"
   help       = "use satisfiability check to verify correctness of candidate rewrites"
 
 [[option]]
-  name       = "sygusRewSynthCheckTimeout"
+  name       = "sygusExprMinerCheckTimeout"
   category   = "regular"
-  long       = "sygus-rr-synth-check-timeout=N"
+  long       = "sygus-expr-miner-check-timeout=N"
   type       = "unsigned long"
-  help       = "timeout (in milliseconds) for the satisfiability check to verify correctness of candidate rewrites"
+  help       = "timeout (in milliseconds) for satisfiability checks in expression miners"
 
 # CEGQI applied to general quantified formulas
 
index e5df8db8a423dd0cc65430efe4937f350a4f2d35..3b7aab0b249b3fcb0d42b19fbdaf41ab1d7deee0 100644 (file)
@@ -36,40 +36,36 @@ CandidateRewriteDatabase::CandidateRewriteDatabase()
     : d_qe(nullptr),
       d_tds(nullptr),
       d_ext_rewrite(nullptr),
-      d_using_sygus(false)
+      d_using_sygus(false),
+      d_silent(false)
 {
 }
-void CandidateRewriteDatabase::initialize(ExtendedRewriter* er,
-                                          TypeNode tn,
-                                          std::vector<Node>& vars,
-                                          unsigned nsamples,
-                                          bool unique_type_ids)
+void CandidateRewriteDatabase::initialize(const std::vector<Node>& vars,
+                                          SygusSampler* ss)
 {
+  Assert(ss != nullptr);
   d_candidate = Node::null();
-  d_type = tn;
   d_using_sygus = false;
   d_qe = nullptr;
   d_tds = nullptr;
-  d_ext_rewrite = er;
-  d_sampler.initialize(tn, vars, nsamples, unique_type_ids);
-  d_crewrite_filter.initialize(&d_sampler, nullptr, false);
+  d_ext_rewrite = nullptr;
+  d_crewrite_filter.initialize(ss, nullptr, false);
+  ExprMiner::initialize(vars, ss);
 }
 
-void CandidateRewriteDatabase::initializeSygus(QuantifiersEngine* qe,
+void CandidateRewriteDatabase::initializeSygus(const std::vector<Node>& vars,
+                                               QuantifiersEngine* qe,
                                                Node f,
-                                               unsigned nsamples,
-                                               bool useSygusType)
+                                               SygusSampler* ss)
 {
+  Assert(ss != nullptr);
   d_candidate = f;
-  d_type = f.getType();
-  Assert(d_type.isDatatype());
-  Assert(static_cast<DatatypeType>(d_type.toType()).getDatatype().isSygus());
   d_using_sygus = true;
   d_qe = qe;
   d_tds = d_qe->getTermDatabaseSygus();
-  d_ext_rewrite = d_tds->getExtRewriter();
-  d_sampler.initializeSygus(d_tds, f, nsamples, useSygusType);
-  d_crewrite_filter.initialize(&d_sampler, d_tds, true);
+  d_ext_rewrite = nullptr;
+  d_crewrite_filter.initialize(ss, d_tds, false);
+  ExprMiner::initialize(vars, ss);
 }
 
 bool CandidateRewriteDatabase::addTerm(Node sol,
@@ -77,7 +73,7 @@ bool CandidateRewriteDatabase::addTerm(Node sol,
                                        bool& rew_print)
 {
   bool is_unique_term = true;
-  Node eq_sol = d_sampler.registerTerm(sol);
+  Node eq_sol = d_sampler->registerTerm(sol);
   // eq_sol is a candidate solution that is equivalent to sol
   if (eq_sol != sol)
   {
@@ -116,81 +112,23 @@ bool CandidateRewriteDatabase::addTerm(Node sol,
 
         Node crr = solbr.eqNode(eq_solr).negate();
         Trace("rr-check") << "Check candidate rewrite : " << crr << std::endl;
-        // quantify over the free variables in crr
-        std::vector<Node> fvs;
-        TermUtil::computeVarContains(crr, fvs);
-        std::map<Node, unsigned> fv_index;
-        std::vector<Node> sks;
-        if (!fvs.empty())
-        {
-          // map to skolems
-          for (unsigned i = 0, size = fvs.size(); i < size; i++)
-          {
-            Node v = fvs[i];
-            fv_index[v] = i;
-            std::map<Node, Node>::iterator itf = d_fv_to_skolem.find(v);
-            if (itf == d_fv_to_skolem.end())
-            {
-              Node sk = nm->mkSkolem("rrck", v.getType());
-              d_fv_to_skolem[v] = sk;
-              sks.push_back(sk);
-            }
-            else
-            {
-              sks.push_back(itf->second);
-            }
-          }
-          crr = crr.substitute(fvs.begin(), fvs.end(), sks.begin(), sks.end());
-        }
 
         // Notice we don't set produce-models. rrChecker takes the same
         // options as the SmtEngine we belong to, where we ensure that
         // produce-models is set.
-        bool needExport = true;
+        bool needExport = false;
         ExprManagerMapCollection varMap;
         ExprManager em(nm->getOptions());
         std::unique_ptr<SmtEngine> rrChecker;
-        Result r;
-        if (options::sygusRewSynthCheckTimeout.wasSetByUser())
-        {
-          // To support a separate timeout for the subsolver, we need to create
-          // a separate ExprManager with its own options. This requires that
-          // the expressions sent to the subsolver can be exported from on
-          // ExprManager to another. If the export fails, we throw an
-          // OptionException.
-          try
-          {
-            rrChecker.reset(new SmtEngine(&em));
-            rrChecker->setTimeLimit(options::sygusRewSynthCheckTimeout(), true);
-            rrChecker->setLogic(smt::currentSmtEngine()->getLogicInfo());
-            Expr eccr = crr.toExpr().exportTo(&em, varMap);
-            rrChecker->assertFormula(eccr);
-            r = rrChecker->checkSat();
-          }
-          catch (const CVC4::ExportUnsupportedException& e)
-          {
-            std::stringstream msg;
-            msg << "Unable to export " << crr
-                << " but exporting expressions is required for "
-                   "--sygus-rr-synth-check-timeout.";
-            throw OptionException(msg.str());
-          }
-        }
-        else
-        {
-          needExport = false;
-          rrChecker.reset(new SmtEngine(nm->toExprManager()));
-          rrChecker->assertFormula(crr.toExpr());
-          r = rrChecker->checkSat();
-        }
-
+        initializeChecker(rrChecker, em, varMap, crr, needExport);
+        Result r = rrChecker->checkSat();
         Trace("rr-check") << "...result : " << r << std::endl;
         if (r.asSatisfiabilityResult().isSat() == Result::SAT)
         {
           Trace("rr-check") << "...rewrite does not hold for: " << std::endl;
           is_unique_term = true;
           std::vector<Node> vars;
-          d_sampler.getVariables(vars);
+          d_sampler->getVariables(vars);
           std::vector<Node> pt;
           for (const Node& v : vars)
           {
@@ -200,8 +138,8 @@ bool CandidateRewriteDatabase::addTerm(Node sol,
             // looking up the model value
             if (v.getKind() == BOUND_VARIABLE)
             {
-              std::map<Node, unsigned>::iterator itf = fv_index.find(v);
-              if (itf == fv_index.end())
+              std::map<Node, Node>::iterator itf = d_fv_to_skolem.find(v);
+              if (itf == d_fv_to_skolem.end())
               {
                 // not in conjecture, can use arbitrary value
                 val = v.getType().mkGroundTerm();
@@ -209,7 +147,7 @@ bool CandidateRewriteDatabase::addTerm(Node sol,
               else
               {
                 // get the model value of its skolem
-                refv = sks[itf->second];
+                refv = itf->second;
               }
             }
             if (val.isNull())
@@ -229,10 +167,10 @@ bool CandidateRewriteDatabase::addTerm(Node sol,
             Trace("rr-check") << "  " << v << " -> " << val << std::endl;
             pt.push_back(val);
           }
-          d_sampler.addSamplePoint(pt);
+          d_sampler->addSamplePoint(pt);
           // add the solution again
           // by construction of the above point, we should be unique now
-          Node eq_sol_new = d_sampler.registerTerm(sol);
+          Node eq_sol_new = d_sampler->registerTerm(sol);
           Assert(eq_sol_new == sol);
         }
         else
@@ -252,19 +190,23 @@ bool CandidateRewriteDatabase::addTerm(Node sol,
         // The analog of terms sol and eq_sol are equivalent under
         // sample points but do not rewrite to the same term. Hence,
         // this indicates a candidate rewrite.
-        out << "(" << (verified ? "" : "candidate-") << "rewrite ";
-        if (d_using_sygus)
-        {
-          Printer* p = Printer::getPrinter(options::outputLanguage());
-          p->toStreamSygus(out, sol);
-          out << " ";
-          p->toStreamSygus(out, eq_sol);
-        }
-        else
+        if (!d_silent)
         {
-          out << sol << " " << eq_sol;
+          out << "(" << (verified ? "" : "candidate-") << "rewrite ";
+          if (d_using_sygus)
+          {
+            Printer* p = Printer::getPrinter(options::outputLanguage());
+            p->toStreamSygus(out, sol);
+            out << " ";
+            p->toStreamSygus(out, eq_sol);
+          }
+          else
+          {
+            out << sol << " " << eq_sol;
+          }
+          out << ")" << std::endl;
         }
-        out << ")" << std::endl;
+        // we count this as printed, despite not literally printing it
         rew_print = true;
         // debugging information
         if (Trace.isOn("sygus-rr-debug"))
@@ -319,6 +261,13 @@ bool CandidateRewriteDatabase::addTerm(Node sol, std::ostream& out)
   return addTerm(sol, out, rew_print);
 }
 
+void CandidateRewriteDatabase::setSilent(bool flag) { d_silent = flag; }
+
+void CandidateRewriteDatabase::setExtendedRewriter(ExtendedRewriter* er)
+{
+  d_ext_rewrite = er;
+}
+
 CandidateRewriteDatabaseGen::CandidateRewriteDatabaseGen(
     std::vector<Node>& vars, unsigned nsamples)
     : d_qe(nullptr), d_vars(vars.begin(), vars.end()), d_nsamples(nsamples)
@@ -347,7 +296,8 @@ bool CandidateRewriteDatabaseGen::addTerm(Node n, std::ostream& out)
   {
     Trace("synth-rr-dbg") << "Initialize database for " << tn << std::endl;
     // initialize with the extended rewriter owned by this class
-    d_cdbs[tn].initialize(er, tn, d_vars, d_nsamples, true);
+    d_cdbs[tn].initialize(d_vars, &d_sampler[tn]);
+    d_cdbs[tn].setExtendedRewriter(er);
     itc = d_cdbs.find(tn);
     Trace("synth-rr-dbg") << "...finish." << std::endl;
   }
index 7f51043e23f724bbfcb0379389cfeeacb88f436b..5b8ffbd9486b2580272d15186a46531308934240 100644 (file)
@@ -22,6 +22,7 @@
 #include <unordered_set>
 #include <vector>
 #include "theory/quantifiers/candidate_rewrite_filter.h"
+#include "theory/quantifiers/expr_miner.h"
 #include "theory/quantifiers/sygus_sampler.h"
 
 namespace CVC4 {
@@ -40,31 +41,14 @@ namespace quantifiers {
  * rule filtering (based on congruence, matching, variable ordering) is also
  * managed by the sygus sampler object.
  */
-class CandidateRewriteDatabase
+class CandidateRewriteDatabase : public ExprMiner
 {
  public:
   CandidateRewriteDatabase();
   ~CandidateRewriteDatabase() {}
-  /**  Initialize this class
-   *
-   * er : pointer to the extended rewriter (if any) we are using to compute
-   * candidate rewrites,
-   * tn : the return type of terms we will be testing with this class,
-   * vars : the variables we are testing substitutions for,
-   * nsamples : number of sample points this class will test,
-   * unique_type_ids : if this is set to true, then each variable is treated
-   * as unique. This affects whether or not a rewrite rule is considered
-   * redundant or not. For example the rewrite f(y)=y is redundant if
-   * f(x)=x has also been printed as a rewrite and x and y have the same type
-   * id (see SygusSampler for details). On the other hand, when a candidate
-   * rewrite database is initialized with sygus below, the type ids of the
-   * (sygus formal argument list) variables are always computed and used.
-   */
-  void initialize(ExtendedRewriter* er,
-                  TypeNode tn,
-                  std::vector<Node>& vars,
-                  unsigned nsamples,
-                  bool unique_type_ids = false);
+  /**  Initialize this class */
+  void initialize(const std::vector<Node>& var,
+                  SygusSampler* ss = nullptr) override;
   /**  Initialize this class
    *
    * Serves the same purpose as the above function, but we will be using
@@ -75,19 +59,12 @@ class CandidateRewriteDatabase
    * database when computing candidate rewrites,
    * f : a term of some SyGuS datatype type whose values we will be
    * testing under the free variables in the grammar of f. This is the
-   * "candidate variable" CegConjecture::d_candidates,
-   * nsamples : number of sample points this class will test,
-   * useSygusType : whether we will register terms with this sampler that have
-   * the same type as f. If this flag is false, then we will be registering
-   * terms of the analog of the type of f, that is, the builtin type that
-   * f's type encodes in the deep embedding.
-   *
-   * These arguments are used to initialize the sygus sampler class.
+   * "candidate variable" CegConjecture::d_candidates.
    */
-  void initializeSygus(QuantifiersEngine* qe,
+  void initializeSygus(const std::vector<Node>& vars,
+                       QuantifiersEngine* qe,
                        Node f,
-                       unsigned nsamples,
-                       bool useSygusType);
+                       SygusSampler* ss = nullptr);
   /** add term
    *
    * Notifies this class that the solution sol was enumerated. This may
@@ -97,34 +74,27 @@ class CandidateRewriteDatabase
    * true if this class printed a rewrite.
    */
   bool addTerm(Node sol, std::ostream& out, bool& rew_print);
-  bool addTerm(Node sol, std::ostream& out);
+  bool addTerm(Node sol, std::ostream& out) override;
+  /** sets whether this class should output candidate rewrites it finds */
+  void setSilent(bool flag);
+  /** set the (extended) rewriter used by this class */
+  void setExtendedRewriter(ExtendedRewriter* er);
 
  private:
   /** reference to quantifier engine */
   QuantifiersEngine* d_qe;
-  /** pointer to the sygus term database of d_qe */
+  /** (required) pointer to the sygus term database of d_qe */
   TermDbSygus* d_tds;
-  /** pointer to the extended rewriter object we are using */
+  /** an extended rewriter object */
   ExtendedRewriter* d_ext_rewrite;
-  /** the (sygus or builtin) type of terms we are testing */
-  TypeNode d_type;
   /** the function-to-synthesize we are testing (if sygus) */
   Node d_candidate;
   /** whether we are using sygus */
   bool d_using_sygus;
-  /** sygus sampler objects for each program variable
-   *
-   * This is used for the sygusRewSynth() option to synthesize new candidate
-   * rewrite rules.
-   */
-  SygusSampler d_sampler;
   /** candidate rewrite filter */
   CandidateRewriteFilter d_crewrite_filter;
-  /**
-   * Cache of skolems for each free variable that appears in a synthesis check
-   * (for --sygus-rr-synth-check).
-   */
-  std::map<Node, Node> d_fv_to_skolem;
+  /** if true, we silence the output of candidate rewrites */
+  bool d_silent;
 };
 
 /**
@@ -154,6 +124,8 @@ class CandidateRewriteDatabaseGen
   QuantifiersEngine* d_qe;
   /** the variables */
   std::vector<Node> d_vars;
+  /** sygus sampler object for each type */
+  std::map<TypeNode, SygusSampler> d_sampler;
   /** the number of samples */
   unsigned d_nsamples;
   /** candidate rewrite databases for each type */
diff --git a/src/theory/quantifiers/expr_miner.cpp b/src/theory/quantifiers/expr_miner.cpp
new file mode 100644 (file)
index 0000000..0e85428
--- /dev/null
@@ -0,0 +1,115 @@
+/*********************                                                        */
+/*! \file expr_miner.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ **   Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved.  See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of expr_miner
+ **/
+
+#include "theory/quantifiers/expr_miner.h"
+
+#include "options/quantifiers_options.h"
+#include "smt/smt_engine.h"
+#include "smt/smt_engine_scope.h"
+#include "theory/quantifiers/term_util.h"
+
+using namespace std;
+using namespace CVC4::kind;
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+void ExprMiner::initialize(const std::vector<Node>& vars, SygusSampler* ss)
+{
+  d_sampler = ss;
+  d_vars.insert(d_vars.end(), vars.begin(), vars.end());
+}
+
+Node ExprMiner::convertToSkolem(Node n)
+{
+  std::vector<Node> fvs;
+  TermUtil::computeVarContains(n, fvs);
+  if (fvs.empty())
+  {
+    return n;
+  }
+  std::vector<Node> sfvs;
+  std::vector<Node> sks;
+  // map to skolems
+  NodeManager* nm = NodeManager::currentNM();
+  for (unsigned i = 0, size = fvs.size(); i < size; i++)
+  {
+    Node v = fvs[i];
+    // only look at the sampler variables
+    if (std::find(d_vars.begin(), d_vars.end(), v) != d_vars.end())
+    {
+      sfvs.push_back(v);
+      std::map<Node, Node>::iterator itf = d_fv_to_skolem.find(v);
+      if (itf == d_fv_to_skolem.end())
+      {
+        Node sk = nm->mkSkolem("rrck", v.getType());
+        d_fv_to_skolem[v] = sk;
+        sks.push_back(sk);
+      }
+      else
+      {
+        sks.push_back(itf->second);
+      }
+    }
+  }
+  return n.substitute(sfvs.begin(), sfvs.end(), sks.begin(), sks.end());
+}
+
+void ExprMiner::initializeChecker(std::unique_ptr<SmtEngine>& checker,
+                                  ExprManager& em,
+                                  ExprManagerMapCollection& varMap,
+                                  Node query,
+                                  bool& needExport)
+{
+  // Convert bound variables to skolems. This ensures the satisfiability
+  // check is ground.
+  Node squery = convertToSkolem(query);
+  NodeManager* nm = NodeManager::currentNM();
+  if (options::sygusExprMinerCheckTimeout.wasSetByUser())
+  {
+    // To support a separate timeout for the subsolver, we need to create
+    // a separate ExprManager with its own options. This requires that
+    // the expressions sent to the subsolver can be exported from on
+    // ExprManager to another. If the export fails, we throw an
+    // OptionException.
+    try
+    {
+      checker.reset(new SmtEngine(&em));
+      checker->setTimeLimit(options::sygusExprMinerCheckTimeout(), true);
+      checker->setLogic(smt::currentSmtEngine()->getLogicInfo());
+      Expr equery = squery.toExpr().exportTo(&em, varMap);
+      checker->assertFormula(equery);
+    }
+    catch (const CVC4::ExportUnsupportedException& e)
+    {
+      std::stringstream msg;
+      msg << "Unable to export " << squery
+          << " but exporting expressions is required for "
+             "--sygus-rr-synth-check-timeout.";
+      throw OptionException(msg.str());
+    }
+    needExport = true;
+  }
+  else
+  {
+    needExport = false;
+    checker.reset(new SmtEngine(nm->toExprManager()));
+    checker->assertFormula(squery.toExpr());
+  }
+}
+
+}  // namespace quantifiers
+}  // namespace theory
+}  // namespace CVC4
diff --git a/src/theory/quantifiers/expr_miner.h b/src/theory/quantifiers/expr_miner.h
new file mode 100644 (file)
index 0000000..c09f40d
--- /dev/null
@@ -0,0 +1,101 @@
+/*********************                                                        */
+/*! \file expr_miner.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ **   Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved.  See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief expr_miner
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__EXPRESSION_MINER_H
+#define __CVC4__THEORY__QUANTIFIERS__EXPRESSION_MINER_H
+
+#include <map>
+#include <memory>
+#include <vector>
+#include "expr/expr_manager.h"
+#include "expr/node.h"
+#include "smt/smt_engine.h"
+#include "theory/quantifiers/sygus_sampler.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+/** Expression miner
+ *
+ * This is a virtual base class for modules that "mines" certain information
+ * from (enumerated) expressions. This includes:
+ * - candidate rewrite rules (--sygus-rr-synth)
+ */
+class ExprMiner
+{
+ public:
+  ExprMiner() : d_sampler(nullptr) {}
+  virtual ~ExprMiner() {}
+  /** initialize
+   *
+   * This initializes this expression miner. The argument vars indicates the
+   * free variables of terms that will be added to this class. The argument
+   * sampler gives an (optional) pointer to a sampler, which is used to
+   * sample tuples of valuations of these variables.
+   */
+  virtual void initialize(const std::vector<Node>& vars,
+                          SygusSampler* ss = nullptr);
+  /** add term
+   *
+   * This registers term n with this expression miner. The output stream out
+   * is provided as an argument for the purposes of outputting the result of
+   * the expression mining done by this class. For example, candidate-rewrite
+   * output is printed on out by the candidate rewrite generator miner.
+   */
+  virtual bool addTerm(Node n, std::ostream& out) = 0;
+
+ protected:
+  /** the set of variables used by this class */
+  std::vector<Node> d_vars;
+  /** pointer to the sygus sampler object we are using */
+  SygusSampler* d_sampler;
+  /**
+   * Maps to skolems for each free variable that appears in a check. This is
+   * used during initializeChecker so that query (which may contain free
+   * variables) is converted to a formula without free variables.
+   */
+  std::map<Node, Node> d_fv_to_skolem;
+  /** convert */
+  Node convertToSkolem(Node n);
+  /** initialize checker
+   *
+   * This function initializes the smt engine smte to check the satisfiability
+   * of the argument "query", which is a formula whose free variables (of
+   * kind BOUND_VARIABLE) are a subset of d_vars.
+   *
+   * The arguments em and varMap are used for supporting cases where we
+   * want smte to use a different expression manager instead of the current
+   * expression manager. The motivation for this so that different options can
+   * be set for the subcall.
+   *
+   * We update the flag needExport to true if smte is using the expression
+   * manager em. In this case, subsequent expressions extracted from smte
+   * (for instance, model values) must be exported to the current expression
+   * manager.
+   */
+  void initializeChecker(std::unique_ptr<SmtEngine>& smte,
+                         ExprManager& em,
+                         ExprManagerMapCollection& varMap,
+                         Node query,
+                         bool& needExport);
+};
+
+}  // namespace quantifiers
+}  // namespace theory
+}  // namespace CVC4
+
+#endif /* __CVC4__THEORY__QUANTIFIERS__EXPRESSION_MINER_H */
diff --git a/src/theory/quantifiers/expr_miner_manager.cpp b/src/theory/quantifiers/expr_miner_manager.cpp
new file mode 100644 (file)
index 0000000..8c11678
--- /dev/null
@@ -0,0 +1,96 @@
+/*********************                                                        */
+/*! \file expr_miner_manager.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ **   Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved.  See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of expression miner manager.
+ **/
+
+#include "theory/quantifiers/expr_miner_manager.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+ExpressionMinerManager::ExpressionMinerManager()
+    : d_doRewSynth(false),
+      d_use_sygus_type(false),
+      d_qe(nullptr),
+      d_tds(nullptr)
+{
+}
+
+void ExpressionMinerManager::initialize(const std::vector<Node>& vars,
+                                        TypeNode tn,
+                                        unsigned nsamples,
+                                        bool unique_type_ids)
+{
+  d_doRewSynth = false;
+  d_sygus_fun = Node::null();
+  d_use_sygus_type = false;
+  d_qe = nullptr;
+  d_tds = nullptr;
+  // initialize the sampler
+  d_sampler.initialize(tn, vars, nsamples, unique_type_ids);
+}
+
+void ExpressionMinerManager::initializeSygus(QuantifiersEngine* qe,
+                                             Node f,
+                                             unsigned nsamples,
+                                             bool useSygusType)
+{
+  d_doRewSynth = false;
+  d_sygus_fun = f;
+  d_use_sygus_type = useSygusType;
+  d_qe = qe;
+  d_tds = qe->getTermDatabaseSygus();
+  // initialize the sampler
+  d_sampler.initializeSygus(d_tds, f, nsamples, useSygusType);
+}
+
+void ExpressionMinerManager::enableRewriteRuleSynth()
+{
+  if (d_doRewSynth)
+  {
+    // already enabled
+    return;
+  }
+  d_doRewSynth = true;
+  std::vector<Node> vars;
+  d_sampler.getVariables(vars);
+  // initialize the candidate rewrite database
+  if (!d_sygus_fun.isNull())
+  {
+    Assert(d_qe != nullptr);
+    d_crd.initializeSygus(vars, d_qe, d_sygus_fun, &d_sampler);
+  }
+  else
+  {
+    d_crd.initialize(vars, &d_sampler);
+  }
+  d_crd.setExtendedRewriter(&d_ext_rew);
+  d_crd.setSilent(false);
+}
+
+bool ExpressionMinerManager::addTerm(Node sol,
+                                     std::ostream& out,
+                                     bool& rew_print)
+{
+  return d_crd.addTerm(sol, out, rew_print);
+}
+
+bool ExpressionMinerManager::addTerm(Node sol, std::ostream& out)
+{
+  bool rew_print = false;
+  return addTerm(sol, out, rew_print);
+}
+
+}  // namespace quantifiers
+}  // namespace theory
+}  // namespace CVC4
diff --git a/src/theory/quantifiers/expr_miner_manager.h b/src/theory/quantifiers/expr_miner_manager.h
new file mode 100644 (file)
index 0000000..668d04b
--- /dev/null
@@ -0,0 +1,107 @@
+/*********************                                                        */
+/*! \file expr_miner_manager.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ **   Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved.  See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Expression miner manager, which manages individual expression miners.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__EXPR_MINER_MANAGER_H
+#define __CVC4__THEORY__QUANTIFIERS__EXPR_MINER_MANAGER_H
+
+#include "expr/node.h"
+#include "theory/quantifiers/candidate_rewrite_database.h"
+#include "theory/quantifiers/extended_rewrite.h"
+#include "theory/quantifiers/sygus_sampler.h"
+#include "theory/quantifiers_engine.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+/** ExpressionMinerManager
+ *
+ * This class manages a set of expression miners. It provides a common place
+ * to register expressions so that multiple mining algorithms can be run in
+ * coordination, possibly sharing information and utilities like a common
+ * sampling object.
+ */
+class ExpressionMinerManager
+{
+ public:
+  ExpressionMinerManager();
+  ~ExpressionMinerManager() {}
+  /**  Initialize this class
+   *
+   * Initializes this class, informing it that the free variables of terms
+   * added to this class via addTerm will have free variables that are a subset
+   * of vars, and have type tn. All expression miners in this class with be
+   * initialized with this variable list. The arguments nsamples and
+   * unique_type_ids are used for initializing the sampler class of this manager
+   * (see SygusSampler::initialize for details).
+   */
+  void initialize(const std::vector<Node>& vars,
+                  TypeNode tn,
+                  unsigned nsamples,
+                  bool unique_type_ids = false);
+  /** Initialize this class, sygus version
+   *
+   * Initializes this class, informing it that the terms added to this class
+   * via calls to addTerm will be generated by the grammar of f. The method
+   * takes a pointer to the quantifiers engine qe. If the argument useSygusType
+   * is true, the terms added to this class are the sygus datatype terms.
+   * If useSygusType is false, the terms are the builtin equivalent of these
+   * terms. The argument nsamples is used to initialize the sampler.
+   */
+  void initializeSygus(QuantifiersEngine* qe,
+                       Node f,
+                       unsigned nsamples,
+                       bool useSygusType);
+  /** enable rewrite rule synthesis (--sygus-rr-synth) */
+  void enableRewriteRuleSynth();
+  /** add term
+   *
+   * Expression miners may print information on the output stream out, for
+   * instance, candidate-rewrites. The method returns true if the term sol is
+   * distinct (up to T-equivalence) with all previous terms added to this class,
+   * which is computed based on the miners that this manager enables.
+   */
+  bool addTerm(Node sol, std::ostream& out);
+  /**
+   * Same as above, but the argument rew_print is set to true if a rewrite rule
+   * was printed on the output stream out.
+   */
+  bool addTerm(Node sol, std::ostream& out, bool& rew_print);
+
+ private:
+  /** whether we are doing rewrite synthesis */
+  bool d_doRewSynth;
+  /** the sygus function passed to initializeSygus, if any */
+  Node d_sygus_fun;
+  /** whether we are using sygus types */
+  bool d_use_sygus_type;
+  /** pointer to the quantifiers engine, used if d_use_sygus is true */
+  QuantifiersEngine* d_qe;
+  /** the sygus term database of d_qe */
+  TermDbSygus* d_tds;
+  /** candidate rewrite database */
+  CandidateRewriteDatabase d_crd;
+  /** sygus sampler object */
+  SygusSampler d_sampler;
+  /** extended rewriter object */
+  ExtendedRewriter d_ext_rew;
+};
+
+}  // namespace quantifiers
+}  // namespace theory
+}  // namespace CVC4
+
+#endif /* __CVC4__THEORY__QUANTIFIERS__EXPR_MINER_MANAGER_H */
index 0a212598bec71389855dda7dd14d0adb6fe18b6d..d8329395dd4616a967894b6310b230ace499e0e9 100644 (file)
@@ -723,16 +723,20 @@ void CegConjecture::printSynthSolution( std::ostream& out, bool singleInvocation
 
       if (status != 0 && options::sygusRewSynth())
       {
-        std::map<Node, CandidateRewriteDatabase>::iterator its =
-            d_crrdb.find(prog);
-        if (its == d_crrdb.end())
+        std::map<Node, ExpressionMinerManager>::iterator its =
+            d_exprm.find(prog);
+        if (its == d_exprm.end())
         {
-          d_crrdb[prog].initializeSygus(
+          d_exprm[prog].initializeSygus(
               d_qe, d_candidates[i], options::sygusSamples(), true);
-          its = d_crrdb.find(prog);
+          if (options::sygusRewSynth())
+          {
+            d_exprm[prog].enableRewriteRuleSynth();
+          }
+          its = d_exprm.find(prog);
         }
         bool rew_print = false;
-        is_unique_term = d_crrdb[prog].addTerm(sol, out, rew_print);
+        is_unique_term = d_exprm[prog].addTerm(sol, out, rew_print);
         if (rew_print)
         {
           ++(cei->d_statistics.d_candidate_rewrites_print);
index 612a2b4ce0af0189deb5dbaa7c325823d80bac07..88902e7212a566cbb701cb70af06c03bc908a8d4 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <memory>
 
-#include "theory/quantifiers/candidate_rewrite_database.h"
+#include "theory/quantifiers/expr_miner_manager.h"
 #include "theory/quantifiers/sygus/ce_guided_single_inv.h"
 #include "theory/quantifiers/sygus/cegis.h"
 #include "theory/quantifiers/sygus/cegis_unif.h"
@@ -28,7 +28,6 @@
 #include "theory/quantifiers/sygus/sygus_pbe.h"
 #include "theory/quantifiers/sygus/sygus_process_conj.h"
 #include "theory/quantifiers/sygus/sygus_repair_const.h"
-#include "theory/quantifiers/sygus_sampler.h"
 #include "theory/quantifiers_engine.h"
 
 namespace CVC4 {
@@ -262,12 +261,16 @@ private:
    */
   void printAndContinueStream();
   //-------------------------------- end sygus stream
-  /** candidate rewrite objects for each program variable
+  /** expression miner managers for each function-to-synthesize
+   *
+   * Notice that for each function-to-synthesize, we enumerate a stream of
+   * candidate solutions, where each of these streams is independent. Thus,
+   * we maintain separate expression miner managers for each of them.
    *
    * This is used for the sygusRewSynth() option to synthesize new candidate
    * rewrite rules.
    */
-  std::map<Node, CandidateRewriteDatabase> d_crrdb;
+  std::map<Node, ExpressionMinerManager> d_exprm;
 };
 
 } /* namespace CVC4::theory::quantifiers */
index 025479f246a79f668e61dd05c839fe90863daeab..f310396d220e46cd68129c1c2320dfcb076b94ec 100644 (file)
@@ -1,6 +1,7 @@
 ; COMMAND-LINE: --sygus-rr --sygus-samples=1000 --sygus-abort-size=2 --sygus-rr-verify-abort --no-sygus-sym-break
+; COMMAND-LINE: --sygus-rr-synth --sygus-samples=1000 --sygus-abort-size=2 --sygus-rr-verify-abort --sygus-rr-synth-check
 ; EXPECT: (error "Maximum term size (2) for enumerative SyGuS exceeded.")
-; SCRUBBER: grep -v -E '(\(define-fun|\(candidate-rewrite)'
+; SCRUBBER: grep -v -E '(\(define-fun|\(candidate-rewrite|\(rewrite)'
 ; EXIT: 1
 
 (set-logic BV)