Refactor mode options for Unif+PI (#3531)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Thu, 5 Dec 2019 15:19:56 +0000 (09:19 -0600)
committerGitHub <noreply@github.com>
Thu, 5 Dec 2019 15:19:56 +0000 (09:19 -0600)
19 files changed:
src/options/options_handler.cpp
src/options/options_handler.h
src/options/quantifiers_modes.h
src/options/quantifiers_options.toml
src/smt/smt_engine.cpp
src/theory/quantifiers/sygus/cegis_unif.cpp
src/theory/quantifiers/sygus/cegis_unif.h
src/theory/quantifiers/sygus/sygus_grammar_cons.cpp
src/theory/quantifiers/sygus/sygus_unif_rl.cpp
src/theory/quantifiers/sygus/sygus_unif_rl.h
src/theory/quantifiers/sygus/synth_conjecture.cpp
test/regress/regress0/sygus/let-ringer.sy
test/regress/regress1/quantifiers/horn-simple.smt2
test/regress/regress1/sygus/car_3.lus.sy
test/regress/regress1/sygus/cegis-unif-inv-eq-fair.sy
test/regress/regress1/sygus/cegisunif-depth1.sy
test/regress/regress1/sygus/constant-dec-tree-bug.sy
test/regress/regress1/sygus/planning-unif.sy
test/regress/regress2/sygus/cegisunif-depth1-bv.sy

index faf35857374042bdcaf302b517ac6cd4d9020a8a..35827d3b04963963a5bf2559c1cc72033add14f6 100644 (file)
@@ -569,6 +569,27 @@ auto (default) \n\
 \n\
 ";
 
+const std::string OptionsHandler::s_sygusUnifPiHelp =
+    "\
+Modes for piecewise-independent unification supported by --sygus-unif-pi:\n\
+\n\
+none  \n\
++ Do not use piecewise-independent unification.\n\
+\n\
+complete \n\
++ Use complete approach for piecewise-independent unification (see Section 3\n\
+of Barbosa et al FMCAD 2019).\n\
+\n\
+cond-enum  \n\
++ Use unconstrained condition enumeration for piecewise-independent\n\
+unification (see Section 4 of Barbosa et al FMCAD 2019).\n\
+\n\
+cond-enum-igain \n\
++ Same as cond-enum, but additionally uses an information gain heuristic\n\
+when doing decision tree learning.\n\
+\n\
+";
+
 const std::string OptionsHandler::s_sygusGrammarConsHelp =
     "\
 Modes for default SyGuS grammars, supported by --sygus-grammar-cons:\n\
@@ -1141,6 +1162,37 @@ OptionsHandler::stringToSygusGrammarConsMode(std::string option,
   }
 }
 
+theory::quantifiers::SygusUnifPiMode OptionsHandler::stringToSygusUnifPiMode(
+    std::string option, std::string optarg)
+{
+  if (optarg == "none")
+  {
+    return theory::quantifiers::SYGUS_UNIF_PI_NONE;
+  }
+  else if (optarg == "complete")
+  {
+    return theory::quantifiers::SYGUS_UNIF_PI_COMPLETE;
+  }
+  else if (optarg == "cond-enum")
+  {
+    return theory::quantifiers::SYGUS_UNIF_PI_CENUM;
+  }
+  else if (optarg == "cond-enum-igain")
+  {
+    return theory::quantifiers::SYGUS_UNIF_PI_CENUM_IGAIN;
+  }
+  else if (optarg == "help")
+  {
+    puts(s_sygusUnifPiHelp.c_str());
+    exit(1);
+  }
+  else
+  {
+    throw OptionException(std::string("unknown option for --sygus-unif-pi: `")
+                          + optarg + "'.  Try --sygus-unif-pi help.");
+  }
+}
+
 theory::quantifiers::MacrosQuantMode OptionsHandler::stringToMacrosQuantMode(
     std::string option, std::string optarg)
 {
index eae61c5b20afcc8b50c9fb7416f59b167ca15e30..2e372a00c4d7c27b7a92b8777c7634b4ec582cb9 100644 (file)
@@ -122,6 +122,8 @@ public:
       std::string option, std::string optarg);
   theory::quantifiers::SygusActiveGenMode stringToSygusActiveGenMode(
       std::string option, std::string optarg);
+  theory::quantifiers::SygusUnifPiMode stringToSygusUnifPiMode(
+      std::string option, std::string optarg);
   theory::quantifiers::SygusGrammarConsMode stringToSygusGrammarConsMode(
       std::string option, std::string optarg);
   theory::quantifiers::MacrosQuantMode stringToMacrosQuantMode(
@@ -277,6 +279,7 @@ public:
   static const std::string s_sygusFilterSolHelp;
   static const std::string s_sygusInvTemplHelp;
   static const std::string s_sygusActiveGenHelp;
+  static const std::string s_sygusUnifPiHelp;
   static const std::string s_sygusGrammarConsHelp;
   static const std::string s_termDbModeHelp;
   static const std::string s_theoryOfModeHelp;
index 9ff2ac19658f6df5c566662372294f07eecef0cf..1a256b0bc8ed9e533f294ef656448d8a571a8155 100644 (file)
@@ -342,6 +342,24 @@ enum QuantRepMode {
   QUANT_REP_MODE_DEPTH,
 };
 
+/**
+ * Modes for piecewise-independent unification for synthesis (see Barbosa et al
+ * FMCAD 2019).
+ */
+enum SygusUnifPiMode
+{
+  /** do not do piecewise-independent unification for synthesis */
+  SYGUS_UNIF_PI_NONE,
+  /** use (finite-model) complete piecewise-independent unification */
+  SYGUS_UNIF_PI_COMPLETE,
+  /** use approach based on condition enumeration for piecewise-independent
+     unification */
+  SYGUS_UNIF_PI_CENUM,
+  /** use approach based on condition enumeration with information gain
+     heuristics for piecewise-independent unification */
+  SYGUS_UNIF_PI_CENUM_IGAIN,
+};
+
 }/* CVC4::theory::quantifiers namespace */
 }/* CVC4::theory namespace */
 
index 171af1e47efc4951d3e0c3d5cbd42c44996ec3b3..e7a24cf3ea6a81095e2157f101056a917fa47217 100644 (file)
@@ -950,20 +950,15 @@ header = "options/quantifiers_options.h"
   help       = "abort if constant repair techniques are not applicable"
 
 [[option]]
-  name       = "sygusUnif"
+  name       = "sygusUnifPi"
   category   = "regular"
-  long       = "sygus-unif"
-  type       = "bool"
-  default    = "false"
-  help       = "Unification-based function synthesis"
-
-[[option]]
-  name       = "sygusUnifCondIndependent"
-  category   = "regular"
-  long       = "sygus-unif-cond-independent"
-  type       = "bool"
-  default    = "false"
-  help       = "Synthesize conditions indepedently from return values (may generate bigger solutions)"
+  long       = "sygus-unif-pi=MODE"
+  type       = "CVC4::theory::quantifiers::SygusUnifPiMode"
+  default    = "CVC4::theory::quantifiers::SYGUS_UNIF_PI_NONE"
+  handler    = "stringToSygusUnifPiMode"
+  includes   = ["options/quantifiers_modes.h"]
+  read_only  = true
+  help       = "mode for synthesis via piecewise-indepedent unification"
 
 [[option]]
   name       = "sygusUnifShuffleCond"
@@ -973,14 +968,6 @@ header = "options/quantifiers_options.h"
   default    = "false"
   help       = "Shuffle condition pool when building solutions (may change solutions sizes)"
 
-[[option]]
-  name       = "sygusUnifBooleanHeuristicDt"
-  category   = "regular"
-  long       = "sygus-unif-boolean-heuristic-dt"
-  type       = "bool"
-  default    = "false"
-  help       = "Build boolean solutions using heuristic decision tree learning (generates smaller solutions)"
-
 [[option]]
   name       = "sygusUnifCondIndNoRepeatSol"
   category   = "regular"
index c47506510ddac8a731830e7569b480461e1b014c..075c8fa005b7a1f3fe4518f3ef68b350011f0805 100644 (file)
@@ -1923,16 +1923,6 @@ void SmtEngine::setDefaults() {
         options::cbqi.set(true);
       }
     }
-    // setting unif requirements
-    if (options::sygusUnifBooleanHeuristicDt()
-        && !options::sygusUnifCondIndependent())
-    {
-      options::sygusUnifCondIndependent.set(true);
-    }
-    if (options::sygusUnifCondIndependent() && !options::sygusUnif())
-    {
-      options::sygusUnif.set(true);
-    }
   }
   if (options::sygusInference())
   {
index 399a9576c5def5e00098a780c7fd26dbdd740bbd..8da328eb6a8c02577d1e26265b499cd973b5fe67 100644 (file)
@@ -151,7 +151,7 @@ bool CegisUnif::getEnumValues(const std::vector<Node>& enums,
         // set enums for condition enumerators
         if (index == 1)
         {
-          if (options::sygusUnifCondIndependent())
+          if (usingConditionPool())
           {
             Assert(es.size() == 1);
             // whether valueus exhausted
@@ -228,6 +228,11 @@ bool CegisUnif::getEnumValues(const std::vector<Node>& enums,
   return !addedUnifEnumSymBreakLemma;
 }
 
+bool CegisUnif::usingConditionPool() const
+{
+  return d_sygus_unif.usingConditionPool();
+}
+
 void CegisUnif::setConditions(
     const std::map<Node, std::vector<Node>>& unif_cenums,
     const std::map<Node, std::vector<Node>>& unif_cvalues,
@@ -250,7 +255,7 @@ void CegisUnif::setConditions(
       // d_sygus_unif.setConditions(e, cost_lit, unif_cenums[e],
       // unif_cvalues[e]); if condition enumerator had value and it is being
       // passively generated, exclude this value
-      if (options::sygusUnifCondIndependent() && !itc->second.empty())
+      if (usingConditionPool() && !itc->second.empty())
       {
         Node eu = itc->second[0];
         Assert(d_tds->isEnumerator(eu));
@@ -321,7 +326,7 @@ bool CegisUnif::processConstructCandidates(const std::vector<Node>& enums,
     // if condition values are being indepedently enumerated, they should be
     // communicated to the decision tree strategies indepedently of we
     // proceeding to attempt solution building
-    if (options::sygusUnifCondIndependent())
+    if (usingConditionPool())
     {
       setConditions(unif_cenums, unif_cvalues, lems);
     }
@@ -353,7 +358,7 @@ bool CegisUnif::processConstructCandidates(const std::vector<Node>& enums,
   }
 
   // TODO tie this to the lemma for getting a new condition value
-  Assert(options::sygusUnifCondIndependent() || !lemmas.empty());
+  Assert(usingConditionPool() || !lemmas.empty());
   for (const Node& lem : lemmas)
   {
     Trace("cegis-unif-lemma")
@@ -400,6 +405,9 @@ CegisUnifEnumDecisionStrategy::CegisUnifEnumDecisionStrategy(
 {
   d_initialized = false;
   d_tds = d_qe->getTermDatabaseSygus();
+  SygusUnifPiMode mode = options::sygusUnifPi();
+  d_useCondPool =
+      mode == SYGUS_UNIF_PI_CENUM || mode == SYGUS_UNIF_PI_CENUM_IGAIN;
 }
 
 Node CegisUnifEnumDecisionStrategy::mkLiteral(unsigned n)
@@ -415,7 +423,7 @@ Node CegisUnifEnumDecisionStrategy::mkLiteral(unsigned n)
     TypeNode ct = c.getType();
     Node eu = nm->mkSkolem("eu", ct);
     Node ceu;
-    if (!options::sygusUnifCondIndependent() && !ci.second.d_enums[0].empty())
+    if (!d_useCondPool && !ci.second.d_enums[0].empty())
     {
       // make a new conditional enumerator as well, starting the
       // second type around
@@ -554,7 +562,7 @@ void CegisUnifEnumDecisionStrategy::initialize(
       DecisionManager::STRAT_QUANT_CEGIS_UNIF_NUM_ENUMS, this);
 
   // create single condition enumerator for each decision tree strategy
-  if (options::sygusUnifCondIndependent())
+  if (d_useCondPool)
   {
     // allocate a condition enumerator for each candidate
     for (std::pair<const Node, StrategyPtInfo>& ci : d_ce_info)
@@ -576,7 +584,7 @@ void CegisUnifEnumDecisionStrategy::getEnumeratorsForStrategyPt(
   if (index == 1)
   {
     // we always use (cost-1) conditions, or 1 if in the indepedent case
-    num_enums = !options::sygusUnifCondIndependent() ? num_enums - 1 : 1;
+    num_enums = !d_useCondPool ? num_enums - 1 : 1;
   }
   if (num_enums > 0)
   {
@@ -622,7 +630,7 @@ void CegisUnifEnumDecisionStrategy::setUpEnumerator(Node e,
   // if we are using a single independent enumerator for conditions, then we
   // allocate an active guard, and are eligible to use variable-agnostic
   // enumeration.
-  if (options::sygusUnifCondIndependent() && index == 1)
+  if (d_useCondPool && index == 1)
   {
     erole = ROLE_ENUM_POOL;
   }
index ac859750fa97190fce8d946a6bc14f92549edc3e..d476d5fb3ed23f7b1aed18c82150be440922bd9a 100644 (file)
@@ -103,6 +103,11 @@ class CegisUnifEnumDecisionStrategy : public DecisionStrategyFmf
   TermDbSygus* d_tds;
   /** reference to the parent conjecture */
   SynthConjecture* d_parent;
+  /**
+   * Whether we are using condition pool enumeration (Section 4 of Barbosa et al
+   * FMCAD 2019). This is determined by option::sygusUnifPi().
+   */
+  bool d_useCondPool;
   /** whether this module has been initialized */
   bool d_initialized;
   /** null node */
@@ -294,6 +299,12 @@ class CegisUnif : public Cegis
                      std::map<Node, std::vector<Node>>& unif_cenums,
                      std::map<Node, std::vector<Node>>& unif_cvalues,
                      std::vector<Node>& lems);
+
+  /**
+   * Whether we are using condition pool enumeration (Section 4 of Barbosa et al
+   * FMCAD 2019). This is determined by option::sygusUnifPi().
+   */
+  bool usingConditionPool() const;
   /**
    * Sygus unif utility. This class implements the core algorithm (e.g. decision
    * tree learning) that this module relies upon.
index 5e4513ff3653f5e32ea267439c4f44091cef19ba..84b160bb3ecf360514aa21877e8e745b646f8dff 100644 (file)
@@ -1187,7 +1187,7 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
       // TODO #1935 ITEs are added to Boolean grammars so that we can infer
       // unification strategies. We can do away with this if we can infer
       // unification strategies from and/or/not
-      if (k == ITE && !options::sygusUnif())
+      if (k == ITE && options::sygusUnifPi() == SYGUS_UNIF_PI_NONE)
       {
         continue;
       }
index 5d4aaf7aedca65c3c82755ef0d6e6b224987be23..1a491394f8f30dc185f2fd17b5c2f9867a9a43b0 100644 (file)
@@ -29,7 +29,10 @@ namespace CVC4 {
 namespace theory {
 namespace quantifiers {
 
-SygusUnifRl::SygusUnifRl(SynthConjecture* p) : d_parent(p) {}
+SygusUnifRl::SygusUnifRl(SynthConjecture* p)
+    : d_parent(p), d_useCondPool(false), d_useCondPoolIGain(false)
+{
+}
 SygusUnifRl::~SygusUnifRl() {}
 void SygusUnifRl::initializeCandidate(
     QuantifiersEngine* qe,
@@ -57,6 +60,11 @@ void SygusUnifRl::initializeCandidate(
     d_cand_to_eval_hds[f].clear();
     d_cand_to_hd_count[f] = 0;
   }
+  // check whether we are using condition enumeration
+  SygusUnifPiMode mode = options::sygusUnifPi();
+  d_useCondPool =
+      mode == SYGUS_UNIF_PI_CENUM || mode == SYGUS_UNIF_PI_CENUM_IGAIN;
+  d_useCondPoolIGain = mode == SYGUS_UNIF_PI_CENUM_IGAIN;
 }
 
 void SygusUnifRl::notifyEnumeration(Node e, Node v, std::vector<Node>& lemmas)
@@ -348,8 +356,7 @@ Node SygusUnifRl::constructSol(
   }
   EnumTypeInfoStrat* etis = snode.d_strats[itd->second.getStrategyIndex()];
   Node sol = itd->second.buildSol(etis->d_cons, lemmas);
-  Assert(options::sygusUnifCondIndependent() || !sol.isNull()
-         || !lemmas.empty());
+  Assert(d_useCondPool || !sol.isNull() || !lemmas.empty());
   return sol;
 }
 
@@ -386,6 +393,11 @@ std::vector<Node> SygusUnifRl::getEvalPointHeads(Node c)
   return it->second;
 }
 
+bool SygusUnifRl::usingConditionPool() const { return d_useCondPool; }
+bool SygusUnifRl::usingConditionPoolInfoGain() const
+{
+  return d_useCondPoolIGain;
+}
 void SygusUnifRl::registerStrategy(
     Node f,
     std::vector<Node>& enums,
@@ -516,7 +528,7 @@ void SygusUnifRl::DecisionTreeInfo::setConditions(
   d_enums.insert(d_enums.end(), enums.begin(), enums.end());
   d_conds.insert(d_conds.end(), conds.begin(), conds.end());
   // add to condition pool
-  if (options::sygusUnifCondIndependent())
+  if (d_unif->usingConditionPool())
   {
     d_cond_mvs.insert(conds.begin(), conds.end());
     if (Trace.isOn("sygus-unif-cond-pool"))
@@ -552,8 +564,8 @@ Node SygusUnifRl::DecisionTreeInfo::buildSol(Node cons,
                           << " conditions..." << std::endl;
   // reset the trie
   d_pt_sep.d_trie.clear();
-  return options::sygusUnifCondIndependent() ? buildSolAllCond(cons, lemmas)
-                                             : buildSolMinCond(cons, lemmas);
+  return d_unif->usingConditionPool() ? buildSolAllCond(cons, lemmas)
+                                      : buildSolMinCond(cons, lemmas);
 }
 
 Node SygusUnifRl::DecisionTreeInfo::buildSolAllCond(Node cons,
@@ -840,7 +852,7 @@ Node SygusUnifRl::DecisionTreeInfo::extractSol(Node cons,
                                                std::map<Node, Node>& hd_mv)
 {
   // rebuild decision tree using heuristic learning
-  if (options::sygusUnifBooleanHeuristicDt())
+  if (d_unif->usingConditionPoolInfoGain())
   {
     recomputeSolHeuristically(hd_mv);
   }
index c5b02a481642c251f52f46d7624a74486fc5c30d..827919308a519ba9e5b91fa42dc84df9ad1959ee 100644 (file)
@@ -103,9 +103,21 @@ class SygusUnifRl : public SygusUnif
   /** retrieve the head of evaluation points for candidate c, if any */
   std::vector<Node> getEvalPointHeads(Node c);
 
+  /**
+   * Whether we are using condition pool enumeration (Section 4 of Barbosa et al
+   * FMCAD 2019). This is determined by option::sygusUnifPi().
+   */
+  bool usingConditionPool() const;
+  /** Whether we are additionally using information gain.  */
+  bool usingConditionPoolInfoGain() const;
+
  protected:
   /** reference to the parent conjecture */
   SynthConjecture* d_parent;
+  /** Whether we are using condition pool enumeration */
+  bool d_useCondPool;
+  /** Whether we are additionally using information gain heuristics */
+  bool d_useCondPoolIGain;
   /* Functions-to-synthesize (a.k.a. candidates) with unification strategies */
   std::unordered_set<Node, NodeHashFunction> d_unif_candidates;
   /** construct sol */
index da427536567a15ad8c42a56a12aadc20b3bcff78..c980e541382fc816bd3bac446dd0efcc41710527 100644 (file)
@@ -65,7 +65,7 @@ SynthConjecture::SynthConjecture(QuantifiersEngine* qe, SynthEngine* p)
   {
     d_modules.push_back(d_ceg_pbe.get());
   }
-  if (options::sygusUnif())
+  if (options::sygusUnifPi() != SYGUS_UNIF_PI_NONE)
   {
     d_modules.push_back(d_ceg_cegisUnif.get());
   }
index c02d2b31f3ee1564700510df9c61d58799c7b866..1bb85bed916bd12d63eed16fb76a838afa747345 100644 (file)
@@ -1,6 +1,6 @@
 ; EXPECT: unsat
 ; COMMAND-LINE: --cegqi-si=all --sygus-out=status
-; COMMAND-LINE: --cegqi-si=all --sygus-unif --sygus-out=status
+; COMMAND-LINE: --cegqi-si=all --sygus-unif-pi=complete --sygus-out=status
 (set-logic LIA)
 (define-fun g ((x Int)) Int (ite (= x 1) 15 19))
 (define-fun letf ((z Int) (w Int) (s Int) (x Int)) Int (+ z (+ x (+ x (+ s (+ 1 (+ (g w) z)))))))
index 6c5039c2b7d8680382ace1d8613a424506e8349b..b851d2e19fcb233c5d8c1524a87cd17fb53da1fa 100644 (file)
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --sygus-unif --sygus-infer
+; COMMAND-LINE: --sygus-unif-pi=complete --sygus-infer
 ; EXPECT: sat
 (set-logic UFLIA)
 (set-info :status sat)
index 088613f218dec51874b58251fa7ea657bb9e0c1d..9432d31312f3879d19a6af676984267537fb55dc 100755 (executable)
@@ -1,5 +1,5 @@
 ; EXPECT: unsat
-; COMMAND-LINE: --sygus-out=status --sygus-unif --sygus-unif-cond-independent --sygus-unif-boolean-heuristic-dt --decision=justification
+; COMMAND-LINE: --sygus-out=status --sygus-unif-pi=cond-enum-igain --decision=justification
 
 (set-logic LIA)
 
index 7d1c3523428821bd7de860318df10fa560a4bffa..df0214316f5ae8f2eebe10866b01bde6ada612cf 100644 (file)
@@ -1,5 +1,5 @@
 ; EXPECT: unsat
-; COMMAND-LINE: --sygus-unif --sygus-bool-ite-return-const --sygus-out=status
+; COMMAND-LINE: --sygus-unif-pi=complete --sygus-bool-ite-return-const --sygus-out=status
 (set-logic LIA)
 
 (define-fun
index 1e810fea3f4a4f9980a957f50067b40527a96321..9f6f65907847d109428325eebd9e5e7283c22652 100644 (file)
@@ -1,5 +1,5 @@
 ; EXPECT: unsat
-; COMMAND-LINE: --sygus-unif --sygus-out=status
+; COMMAND-LINE: --sygus-unif-pi=complete --sygus-out=status
 (set-logic LIA)
 
 (synth-fun f ((x Int) (y Int)) Int
index 15df2d5079667417a1d2f30ccd31e1979452821d..7229dea2ee43aba14e1ad9e510b05f332145c2f8 100644 (file)
@@ -1,5 +1,5 @@
 ; EXPECT: unsat
-; COMMAND-LINE: --sygus-out=status --sygus-unif
+; COMMAND-LINE: --sygus-out=status --sygus-unif-pi=complete
 
 (set-logic SAT)
 (synth-fun u ((x Int)) Int)
index 39c89dc53a80ce21d5dd252fb58b04f6dcfa55a5..3a715501aaf3676e3f20fe6469e97a8e7eb59d59 100644 (file)
@@ -1,5 +1,5 @@
 ; EXPECT: unsat
-; COMMAND-LINE: --sygus-unif --sygus-out=status
+; COMMAND-LINE: --sygus-unif-pi=complete --sygus-out=status
 (set-logic LIA)
 
 (define-fun get-y ((currPoint Int)) Int 
index 4b0cefcda050db8aac22ef47598f10da4a51a1d0..6b647b77dbb17bd7a84a341c281e7ca8845cbe62 100644 (file)
@@ -1,5 +1,5 @@
 ; EXPECT: unsat
-; COMMAND-LINE: --sygus-unif --sygus-out=status
+; COMMAND-LINE: --sygus-unif-pi=complete --sygus-out=status
 (set-logic BV)
 
 (synth-fun f ((x (BitVec 64)) (y (BitVec 64))) (BitVec 64)