summaryrefslogtreecommitdiff
path: root/src/theory/quantifiers
diff options
context:
space:
mode:
Diffstat (limited to 'src/theory/quantifiers')
-rw-r--r--src/theory/quantifiers/fun_def_evaluator.cpp96
-rw-r--r--src/theory/quantifiers/sygus/cegis.cpp29
-rw-r--r--src/theory/quantifiers/sygus/cegis.h8
-rw-r--r--src/theory/quantifiers/sygus/sygus_enumerator.cpp4
-rw-r--r--src/theory/quantifiers/sygus/sygus_eval_unfold.cpp139
-rw-r--r--src/theory/quantifiers/sygus/sygus_eval_unfold.h43
-rw-r--r--src/theory/quantifiers/sygus/sygus_unif_rl.cpp3
-rw-r--r--src/theory/quantifiers/sygus/sygus_unif_strat.cpp3
-rw-r--r--src/theory/quantifiers/sygus/synth_conjecture.cpp5
-rw-r--r--src/theory/quantifiers/sygus/synth_engine.cpp41
-rw-r--r--src/theory/quantifiers/sygus/term_database_sygus.cpp119
-rw-r--r--src/theory/quantifiers/sygus/term_database_sygus.h25
-rw-r--r--src/theory/quantifiers/sygus/type_info.cpp16
13 files changed, 335 insertions, 196 deletions
diff --git a/src/theory/quantifiers/fun_def_evaluator.cpp b/src/theory/quantifiers/fun_def_evaluator.cpp
index 376d0eb47..8eb0ef686 100644
--- a/src/theory/quantifiers/fun_def_evaluator.cpp
+++ b/src/theory/quantifiers/fun_def_evaluator.cpp
@@ -15,6 +15,7 @@
#include "theory/quantifiers/fun_def_evaluator.h"
+#include "options/quantifiers_options.h"
#include "theory/quantifiers/quantifiers_attributes.h"
#include "theory/rewriter.h"
@@ -53,6 +54,8 @@ Node FunDefEvaluator::evaluate(Node n) const
Assert(Rewriter::rewrite(n) == n);
Trace("fd-eval") << "FunDefEvaluator: evaluate " << n << std::endl;
NodeManager* nm = NodeManager::currentNM();
+ std::unordered_map<TNode, unsigned, TNodeHashFunction> funDefCount;
+ std::unordered_map<TNode, unsigned, TNodeHashFunction>::iterator itCount;
std::unordered_map<TNode, Node, TNodeHashFunction> visited;
std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it;
std::map<Node, FunDefInfo>::const_iterator itf;
@@ -75,6 +78,13 @@ Node FunDefEvaluator::evaluate(Node n) const
Trace("fd-eval-debug") << "constant " << cur << std::endl;
visited[cur] = cur;
}
+ else if (cur.getKind() == ITE)
+ {
+ Trace("fd-eval-debug") << "ITE " << cur << std::endl;
+ visited[cur] = Node::null();
+ visit.push_back(cur);
+ visit.push_back(cur[0]);
+ }
else
{
Trace("fd-eval-debug") << "recurse " << cur << std::endl;
@@ -102,6 +112,34 @@ Node FunDefEvaluator::evaluate(Node n) const
{
children.push_back(cur.getOperator());
}
+ else if (ck == ITE)
+ {
+ // get evaluation of condition
+ it = visited.find(cur[0]);
+ Assert(it != visited.end());
+ Assert(!it->second.isNull());
+ if (!it->second.isConst())
+ {
+ Trace("fd-eval") << "FunDefEvaluator: couldn't reduce condition of "
+ "ITE to const, FAIL\n";
+ return Node::null();
+ }
+ // pick child to evaluate depending on condition eval
+ unsigned childIdxToEval = it->second.getConst<bool>() ? 1 : 2;
+ Trace("fd-eval-debug2")
+ << "FunDefEvaluator: result of ITE condition : "
+ << it->second.getConst<bool>() << "\n";
+ // the result will be the result of evaluation the child
+ visited[cur] = cur[childIdxToEval];
+ // push back self and child. The child will be evaluated first and
+ // result will be the result of evaluation child
+ visit.push_back(cur);
+ visit.push_back(cur[childIdxToEval]);
+ Trace("fd-eval-debug2") << "FunDefEvaluator: result will be from : "
+ << cur[childIdxToEval] << "\n";
+ continue;
+ }
+ unsigned child CVC4_UNUSED = 0;
for (const Node& cn : cur)
{
it = visited.find(cn);
@@ -109,20 +147,37 @@ Node FunDefEvaluator::evaluate(Node n) const
Assert(!it->second.isNull());
childChanged = childChanged || cn != it->second;
children.push_back(it->second);
+ Trace("fd-eval-debug2") << "argument " << child++
+ << " eval : " << it->second << std::endl;
}
if (cur.getKind() == APPLY_UF)
{
// need to evaluate it
f = cur.getOperator();
+ Trace("fd-eval-debug2")
+ << "FunDefEvaluator: need to eval " << f << "\n";
itf = d_funDefMap.find(f);
- if (itf == d_funDefMap.end())
+ itCount = funDefCount.find(f);
+ if (itCount == funDefCount.end())
{
- Trace("fd-eval") << "FunDefEvaluator: no definition for " << f
- << ", FAIL" << std::endl;
+ funDefCount[f] = 0;
+ itCount = funDefCount.find(f);
+ }
+ if (itf == d_funDefMap.end()
+ || itCount->second > options::sygusRecFunEvalLimit())
+ {
+ Trace("fd-eval")
+ << "FunDefEvaluator: "
+ << (itf == d_funDefMap.end() ? "no definition for "
+ : "too many evals for ")
+ << f << ", FAIL" << std::endl;
return Node::null();
}
+ ++funDefCount[f];
// get the function definition
Node sbody = itf->second.d_body;
+ Trace("fd-eval-debug2")
+ << "FunDefEvaluator: definition: " << sbody << "\n";
const std::vector<Node>& args = itf->second.d_args;
if (!args.empty())
{
@@ -131,6 +186,17 @@ Node FunDefEvaluator::evaluate(Node n) const
args.begin(), args.end(), children.begin(), children.end());
// rewrite it
sbody = Rewriter::rewrite(sbody);
+ if (Trace.isOn("fd-eval-debug2"))
+ {
+ Trace("fd-eval-debug2")
+ << "FunDefEvaluator: evaluation with args:\n";
+ for (const Node& child : children)
+ {
+ Trace("fd-eval-debug2") << "..." << child << "\n";
+ }
+ Trace("fd-eval-debug2")
+ << "FunDefEvaluator: results in " << sbody << "\n";
+ }
}
// our result is the result of the body
visited[cur] = sbody;
@@ -139,6 +205,8 @@ Node FunDefEvaluator::evaluate(Node n) const
// evaluating the body.
if (!sbody.isConst())
{
+ Trace("fd-eval-debug2") << "FunDefEvaluator: will map " << cur
+ << " from body " << sbody << "\n";
visit.push_back(cur);
visit.push_back(sbody);
}
@@ -150,25 +218,35 @@ Node FunDefEvaluator::evaluate(Node n) const
ret = nm->mkNode(cur.getKind(), children);
ret = Rewriter::rewrite(ret);
}
+ Trace("fd-eval-debug2") << "built from arguments " << ret << "\n";
visited[cur] = ret;
}
}
else if (cur != curEval && !curEval.isConst())
{
Trace("fd-eval-debug") << "from body " << cur << std::endl;
+ Trace("fd-eval-debug") << "and eval " << curEval << std::endl;
// we had to evaluate our body, which should have a definition now
it = visited.find(curEval);
- Assert(it != visited.end());
- // our definition is the result of the body
- visited[cur] = it->second;
+ if (it == visited.end())
+ {
+ Trace("fd-eval-debug2") << "eval without definition\n";
+ // this is the case where curEval was not a constant but it was
+ // irreducible, for example (DT_SYGUS_EVAL e args)
+ visited[cur] = curEval;
+ }
+ else
+ {
+ Trace("fd-eval-debug2")
+ << "eval with definition " << it->second << "\n";
+ visited[cur] = it->second;
}
}
+ }
} while (!visit.empty());
+ Trace("fd-eval") << "FunDefEvaluator: return " << visited[n] << ", SUCCESS\n";
Assert(visited.find(n) != visited.end());
Assert(!visited.find(n)->second.isNull());
- Assert(visited.find(n)->second.isConst());
- Trace("fd-eval") << "FunDefEvaluator: return SUCCESS " << visited[n]
- << std::endl;
return visited[n];
}
diff --git a/src/theory/quantifiers/sygus/cegis.cpp b/src/theory/quantifiers/sygus/cegis.cpp
index aa0af6f1d..c806bb1e7 100644
--- a/src/theory/quantifiers/sygus/cegis.cpp
+++ b/src/theory/quantifiers/sygus/cegis.cpp
@@ -31,12 +31,9 @@ namespace theory {
namespace quantifiers {
Cegis::Cegis(QuantifiersEngine* qe, SynthConjecture* p)
- : SygusModule(qe, p), d_eval_unfold(nullptr), d_using_gr_repair(false)
+ : SygusModule(qe, p), d_eval_unfold(nullptr), d_usingSymCons(false)
{
- if (options::sygusEvalUnfold())
- {
- d_eval_unfold = qe->getTermDatabaseSygus()->getEvalUnfold();
- }
+ d_eval_unfold = qe->getTermDatabaseSygus()->getEvalUnfold();
}
bool Cegis::initialize(Node conj,
@@ -80,7 +77,7 @@ bool Cegis::processInitialize(Node conj,
for (unsigned i = 0; i < csize; i++)
{
Trace("cegis") << "...register enumerator " << candidates[i];
- bool do_repair_const = false;
+ bool useSymCons = false;
if (options::sygusRepairConst())
{
TypeNode ctn = candidates[i].getType();
@@ -88,15 +85,15 @@ bool Cegis::processInitialize(Node conj,
SygusTypeInfo& cti = d_tds->getTypeInfo(ctn);
if (cti.hasSubtermSymbolicCons())
{
- do_repair_const = true;
- // remember that we are doing grammar-based repair
- d_using_gr_repair = true;
- Trace("cegis") << " (using repair)";
+ useSymCons = true;
+ // remember that we are using symbolic constructors
+ d_usingSymCons = true;
+ Trace("cegis") << " (using symbolic constructors)";
}
}
Trace("cegis") << std::endl;
d_tds->registerEnumerator(
- candidates[i], candidates[i], d_parent, erole, do_repair_const);
+ candidates[i], candidates[i], d_parent, erole, useSymCons);
}
return true;
}
@@ -135,7 +132,10 @@ bool Cegis::addEvalLemmas(const std::vector<Node>& candidates,
}
NodeManager* nm = NodeManager::currentNM();
bool addedEvalLemmas = false;
- if (options::sygusRefEval())
+ // Refinement evaluation should not be done for grammars with symbolic
+ // constructors.
+ bool doRefEval = options::sygusRefEval() && !d_usingSymCons;
+ if (doRefEval)
{
Trace("cegqi-engine") << " *** Do refinement lemma evaluation"
<< (doGen ? " with conjecture-specific refinement"
@@ -169,7 +169,8 @@ bool Cegis::addEvalLemmas(const std::vector<Node>& candidates,
}
}
// we only do evaluation unfolding for passive enumerators
- if (doGen && d_eval_unfold != nullptr)
+ bool doEvalUnfold = (doGen && options::sygusEvalUnfold()) || d_usingSymCons;
+ if (doEvalUnfold)
{
Trace("cegqi-engine") << " *** Do evaluation unfolding..." << std::endl;
std::vector<Node> eager_terms, eager_vals, eager_exps;
@@ -239,7 +240,7 @@ bool Cegis::constructCandidates(const std::vector<Node>& enums,
}
}
// if we are using grammar-based repair
- if (d_using_gr_repair)
+ if (d_usingSymCons && options::sygusRepairConst())
{
SygusRepairConst* src = d_parent->getRepairConst();
Assert(src != nullptr);
diff --git a/src/theory/quantifiers/sygus/cegis.h b/src/theory/quantifiers/sygus/cegis.h
index 08cf98c99..adaecc7f6 100644
--- a/src/theory/quantifiers/sygus/cegis.h
+++ b/src/theory/quantifiers/sygus/cegis.h
@@ -204,15 +204,15 @@ class Cegis : public SygusModule
*/
std::unordered_set<unsigned> d_cegis_sample_refine;
- //---------------------------------for sygus repair
- /** are we using grammar-based repair?
+ //---------------------------------for symbolic constructors
+ /** are we using symbolic constants?
*
* This flag is set ot true if at least one of the enumerators allocated
* by this class has been configured to allow model values with symbolic
* constructors, such as the "any constant" constructor.
*/
- bool d_using_gr_repair;
- //---------------------------------end for sygus repair
+ bool d_usingSymCons;
+ //---------------------------------end for symbolic constructors
};
} /* CVC4::theory::quantifiers namespace */
diff --git a/src/theory/quantifiers/sygus/sygus_enumerator.cpp b/src/theory/quantifiers/sygus/sygus_enumerator.cpp
index 472a82e29..e4c23977e 100644
--- a/src/theory/quantifiers/sygus/sygus_enumerator.cpp
+++ b/src/theory/quantifiers/sygus/sygus_enumerator.cpp
@@ -996,6 +996,10 @@ bool SygusEnumerator::TermEnumMasterInterp::initialize(SygusEnumerator* se,
Node SygusEnumerator::TermEnumMasterInterp::getCurrent() { return *d_te; }
bool SygusEnumerator::TermEnumMasterInterp::increment()
{
+ if (d_te.isFinished())
+ {
+ return false;
+ }
SygusEnumerator::TermCache& tc = d_se->d_tcache[d_tn];
Node curr = getCurrent();
tc.addTerm(curr);
diff --git a/src/theory/quantifiers/sygus/sygus_eval_unfold.cpp b/src/theory/quantifiers/sygus/sygus_eval_unfold.cpp
index 5286ab6f7..42ddbbb7d 100644
--- a/src/theory/quantifiers/sygus/sygus_eval_unfold.cpp
+++ b/src/theory/quantifiers/sygus/sygus_eval_unfold.cpp
@@ -14,7 +14,9 @@
#include "theory/quantifiers/sygus/sygus_eval_unfold.h"
+#include "expr/sygus_datatype.h"
#include "options/quantifiers_options.h"
+#include "theory/datatypes/theory_datatypes_utils.h"
#include "theory/quantifiers/sygus/term_database_sygus.h"
using namespace std;
@@ -101,6 +103,10 @@ void SygusEvalUnfold::registerModelValue(Node a,
antec_exp.size() == 1 ? antec_exp[0] : nm->mkNode(AND, antec_exp);
// Node antec = n.eqNode( vn );
TypeNode tn = n.getType();
+ // Check if the sygus type has any symbolic constructors. This will
+ // impact how the unfolding is computed below.
+ SygusTypeInfo& sti = d_tds->getTypeInfo(tn);
+ bool hasSymCons = sti.hasSubtermSymbolicCons();
// n occurs as an evaluation head, thus it has sygus datatype type
Assert(tn.isDatatype());
const Datatype& dt = static_cast<DatatypeType>(tn.toType()).getDatatype();
@@ -148,7 +154,7 @@ void SygusEvalUnfold::registerModelValue(Node a,
do_unfold = true;
}
}
- if (do_unfold)
+ if (do_unfold || hasSymCons)
{
// note that this is replicated for different values
std::map<Node, Node> vtm;
@@ -158,7 +164,10 @@ void SygusEvalUnfold::registerModelValue(Node a,
eval_children.end(), it->second[i].begin(), it->second[i].end());
Node eval_fun = nm->mkNode(DT_SYGUS_EVAL, eval_children);
eval_children.resize(1);
- res = d_tds->unfold(eval_fun, vtm, exp);
+ // If we explicitly asked to unfold, we use single step, otherwise
+ // we use multi step.
+ res = unfold(eval_fun, vtm, exp, true, !do_unfold);
+ Trace("sygus-eval-unfold") << "Unfold returns " << res << std::endl;
expn = exp.size() == 1 ? exp[0] : nm->mkNode(AND, exp);
}
else
@@ -170,6 +179,8 @@ void SygusEvalUnfold::registerModelValue(Node a,
eval_children[0] = vn;
Node eval_fun = nm->mkNode(DT_SYGUS_EVAL, eval_children);
res = d_tds->evaluateWithUnfolding(eval_fun);
+ Trace("sygus-eval-unfold")
+ << "Evaluate with unfolding returns " << res << std::endl;
esit.init(conj, n, res);
eval_children.resize(1);
eval_children[0] = n;
@@ -193,6 +204,130 @@ void SygusEvalUnfold::registerModelValue(Node a,
}
}
+Node SygusEvalUnfold::unfold(Node en,
+ std::map<Node, Node>& vtm,
+ std::vector<Node>& exp,
+ bool track_exp,
+ bool doRec)
+{
+ if (en.getKind() != DT_SYGUS_EVAL)
+ {
+ Assert(en.isConst());
+ return en;
+ }
+ Trace("sygus-eval-unfold-debug")
+ << "Unfold : " << en << ", track exp is " << track_exp << ", doRec is "
+ << doRec << std::endl;
+ Node ev = en[0];
+ if (track_exp)
+ {
+ std::map<Node, Node>::iterator itv = vtm.find(en[0]);
+ Assert(itv != vtm.end());
+ if (itv != vtm.end())
+ {
+ ev = itv->second;
+ }
+ Assert(en[0].getType() == ev.getType());
+ Assert(ev.isConst());
+ }
+ Trace("sygus-eval-unfold-debug")
+ << "Unfold model value is : " << ev << std::endl;
+ AlwaysAssert(ev.getKind() == APPLY_CONSTRUCTOR);
+ std::vector<Node> args;
+ for (unsigned i = 1, nchild = en.getNumChildren(); i < nchild; i++)
+ {
+ args.push_back(en[i]);
+ }
+
+ TypeNode headType = en[0].getType();
+ Type headTypeT = headType.toType();
+ NodeManager* nm = NodeManager::currentNM();
+ const Datatype& dt = headType.getDatatype();
+ unsigned i = datatypes::utils::indexOf(ev.getOperator());
+ if (track_exp)
+ {
+ // explanation
+ Node ee =
+ nm->mkNode(APPLY_TESTER, Node::fromExpr(dt[i].getTester()), en[0]);
+ if (std::find(exp.begin(), exp.end(), ee) == exp.end())
+ {
+ exp.push_back(ee);
+ }
+ }
+ // if we are a symbolic constructor, unfolding returns the subterm itself
+ Node sop = Node::fromExpr(dt[i].getSygusOp());
+ if (sop.getAttribute(SygusAnyConstAttribute()))
+ {
+ Trace("sygus-eval-unfold-debug")
+ << "...it is an any-constant constructor" << std::endl;
+ Assert(dt[i].getNumArgs() == 1);
+ // If the argument to evaluate is itself concrete, then we use its
+ // argument; otherwise we return its selector.
+ if (en[0].getKind() == APPLY_CONSTRUCTOR)
+ {
+ Trace("sygus-eval-unfold-debug")
+ << "...return (from constructor) " << en[0][0] << std::endl;
+ return en[0][0];
+ }
+ else
+ {
+ Node ret = nm->mkNode(
+ APPLY_SELECTOR_TOTAL, dt[i].getSelectorInternal(headTypeT, 0), en[0]);
+ Trace("sygus-eval-unfold-debug")
+ << "...return (from constructor) " << ret << std::endl;
+ return ret;
+ }
+ }
+
+ Assert(!dt.isParametric());
+ std::map<int, Node> pre;
+ for (unsigned j = 0, nargs = dt[i].getNumArgs(); j < nargs; j++)
+ {
+ std::vector<Node> cc;
+ Node s;
+ // get the j^th subfield of en
+ if (en[0].getKind() == APPLY_CONSTRUCTOR)
+ {
+ // if it is a concrete constructor application, as an optimization,
+ // just return the argument
+ s = en[0][j];
+ }
+ else
+ {
+ s = nm->mkNode(
+ APPLY_SELECTOR_TOTAL, dt[i].getSelectorInternal(headTypeT, j), en[0]);
+ }
+ cc.push_back(s);
+ if (track_exp)
+ {
+ // update vtm map
+ vtm[s] = ev[j];
+ }
+ cc.insert(cc.end(), args.begin(), args.end());
+ Node argj = nm->mkNode(DT_SYGUS_EVAL, cc);
+ if (doRec)
+ {
+ Trace("sygus-eval-unfold-debug") << "Recurse on " << s << std::endl;
+ // evaluate recursively
+ argj = unfold(argj, vtm, exp, track_exp, doRec);
+ }
+ pre[j] = argj;
+ }
+ Node ret = d_tds->mkGeneric(dt, i, pre);
+ // apply the appropriate substitution to ret
+ ret = datatypes::utils::applySygusArgs(dt, sop, ret, args);
+ // rewrite
+ ret = Rewriter::rewrite(ret);
+ return ret;
+}
+
+Node SygusEvalUnfold::unfold(Node en)
+{
+ std::map<Node, Node> vtm;
+ std::vector<Node> exp;
+ return unfold(en, vtm, exp, false, false);
+}
+
} // namespace quantifiers
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/quantifiers/sygus/sygus_eval_unfold.h b/src/theory/quantifiers/sygus/sygus_eval_unfold.h
index adc54c6a7..50b361fc4 100644
--- a/src/theory/quantifiers/sygus/sygus_eval_unfold.h
+++ b/src/theory/quantifiers/sygus/sygus_eval_unfold.h
@@ -83,6 +83,49 @@ class SygusEvalUnfold
std::vector<Node>& exps,
std::vector<Node>& terms,
std::vector<Node>& vals);
+ /** unfold
+ *
+ * This method is called when a sygus term d (typically a variable for a SyGuS
+ * enumerator) has a model value specified by the map vtm. The argument en
+ * is an application of kind DT_SYGUS_EVAL, i.e. eval( d, c1, ..., cm ).
+ * Typically, d is a shared selector chain, although it may also be a
+ * non-constant application of a constructor.
+ *
+ * If doRec is false, this method returns the one-step unfolding of this
+ * evaluation function application. An example of a one step unfolding is:
+ * eval( C_+( d1, d2 ), t ) ---> +( eval( d1, t ), eval( d2, t ) )
+ *
+ * This function does this unfolding for a (possibly symbolic) evaluation
+ * head, where the argument "variable to model" vtm stores the model value of
+ * variables from this head. This allows us to track an explanation of the
+ * unfolding in the vector exp when track_exp is true.
+ *
+ * For example, if vtm[d] = C_+( C_x(), C_0() ) and track_exp is true, then
+ * this method applied to eval( d, t ) will return
+ * +( eval( d.0, t ), eval( d.1, t ) ), and is-C_+( d ) is added to exp.
+ *
+ * If the argument doRec is true, we do a multi-step unfolding instead of
+ * a single-step unfolding. For example, if vtm[d] = C_+( C_x(), C_0() ),
+ * then this method applied to eval(d,5) will return 5+0 = 0.
+ *
+ * Furthermore, notice that any-constant constructors are *never* expanded to
+ * their concrete model values. This means that the multi-step unfolding when
+ * vtm[d] = C_+( C_x(), any_constant(n) ), then this method applied to
+ * eval(d,5) will return 5 + d.2.1, where the latter term is a shared selector
+ * chain. In other words, this unfolding elaborates the connection between
+ * the builtin integer field d.2.1 of d and the builtin interpretation of
+ * this sygus term, for the given argument.
+ */
+ Node unfold(Node en,
+ std::map<Node, Node>& vtm,
+ std::vector<Node>& exp,
+ bool track_exp = true,
+ bool doRec = false);
+ /**
+ * Same as above, but without explanation tracking. This is used for concrete
+ * evaluation heads
+ */
+ Node unfold(Node en);
private:
/** sygus term database associated with this utility */
diff --git a/src/theory/quantifiers/sygus/sygus_unif_rl.cpp b/src/theory/quantifiers/sygus/sygus_unif_rl.cpp
index 3f09a4346..5d4aaf7ae 100644
--- a/src/theory/quantifiers/sygus/sygus_unif_rl.cpp
+++ b/src/theory/quantifiers/sygus/sygus_unif_rl.cpp
@@ -105,7 +105,8 @@ Node SygusUnifRl::purifyLemma(Node n,
{
TNode cand = n[0];
Node tmp = n.substitute(cand, it->second);
- nv = d_tds->evaluateWithUnfolding(tmp);
+ // should be concrete, can just use the rewriter
+ nv = Rewriter::rewrite(tmp);
Trace("sygus-unif-rl-purify")
<< "PurifyLemma : model value for " << tmp << " is " << nv << "\n";
}
diff --git a/src/theory/quantifiers/sygus/sygus_unif_strat.cpp b/src/theory/quantifiers/sygus/sygus_unif_strat.cpp
index e74068ace..07997221f 100644
--- a/src/theory/quantifiers/sygus/sygus_unif_strat.cpp
+++ b/src/theory/quantifiers/sygus/sygus_unif_strat.cpp
@@ -15,6 +15,7 @@
#include "theory/quantifiers/sygus/sygus_unif_strat.h"
#include "theory/datatypes/theory_datatypes_utils.h"
+#include "theory/quantifiers/sygus/sygus_eval_unfold.h"
#include "theory/quantifiers/sygus/sygus_unif.h"
#include "theory/quantifiers/sygus/term_database_sygus.h"
#include "theory/quantifiers/term_util.h"
@@ -258,7 +259,7 @@ void SygusUnifStrategy::buildStrategyGraph(TypeNode tn, NodeRole nrole)
Node eut = nm->mkNode(DT_SYGUS_EVAL, echildren);
Trace("sygus-unif-debug2") << " Test evaluation of " << eut << "..."
<< std::endl;
- eut = d_qe->getTermDatabaseSygus()->unfold(eut);
+ eut = d_qe->getTermDatabaseSygus()->getEvalUnfold()->unfold(eut);
Trace("sygus-unif-debug2") << " ...got " << eut;
Trace("sygus-unif-debug2") << ", type : " << eut.getType() << std::endl;
diff --git a/src/theory/quantifiers/sygus/synth_conjecture.cpp b/src/theory/quantifiers/sygus/synth_conjecture.cpp
index 6e69715ef..da4275365 100644
--- a/src/theory/quantifiers/sygus/synth_conjecture.cpp
+++ b/src/theory/quantifiers/sygus/synth_conjecture.cpp
@@ -591,7 +591,8 @@ bool SynthConjecture::doCheck(std::vector<Node>& lems)
Trace("cegqi-debug") << "...squery : " << squery << std::endl;
squery = Rewriter::rewrite(squery);
Trace("cegqi-debug") << "...rewrites to : " << squery << std::endl;
- Assert(squery.isConst() && squery.getConst<bool>());
+ Assert(options::sygusRecFun()
+ || (squery.isConst() && squery.getConst<bool>()));
#endif
return false;
}
@@ -711,7 +712,7 @@ void SynthConjecture::doRefine(std::vector<Node>& lems)
base_lem = base_lem.substitute(
sk_vars.begin(), sk_vars.end(), sk_subs.begin(), sk_subs.end());
Trace("cegqi-refine") << "doRefine : rewrite..." << std::endl;
- base_lem = Rewriter::rewrite(base_lem);
+ base_lem = d_tds->rewriteNode(base_lem);
Trace("cegqi-refine") << "doRefine : register refinement lemma " << base_lem
<< "..." << std::endl;
d_master->registerRefinementLemma(sk_vars, base_lem, lems);
diff --git a/src/theory/quantifiers/sygus/synth_engine.cpp b/src/theory/quantifiers/sygus/synth_engine.cpp
index 9f6954416..4a708e66c 100644
--- a/src/theory/quantifiers/sygus/synth_engine.cpp
+++ b/src/theory/quantifiers/sygus/synth_engine.cpp
@@ -276,28 +276,29 @@ void SynthEngine::registerQuantifier(Node q)
{
Trace("cegqi-debug") << "SynthEngine: Register quantifier : " << q
<< std::endl;
- if (d_quantEngine->getOwner(q) == this)
+ if (d_quantEngine->getOwner(q) != this)
{
- Trace("cegqi") << "Register conjecture : " << q << std::endl;
- if (options::sygusQePreproc())
- {
- d_waiting_conj.push_back(q);
- }
- else
- {
- // assign it now
- assignConjecture(q);
- }
+ return;
}
- if (options::sygusRecFun())
+ if (d_quantEngine->getQuantAttributes()->isFunDef(q))
{
- if (d_quantEngine->getQuantAttributes()->isFunDef(q))
- {
- // If it is a recursive function definition, add it to the function
- // definition evaluator class.
- FunDefEvaluator* fde = d_tds->getFunDefEvaluator();
- fde->assertDefinition(q);
- }
+ Assert(options::sygusRecFun());
+ // If it is a recursive function definition, add it to the function
+ // definition evaluator class.
+ Trace("cegqi") << "Registering function definition : " << q << "\n";
+ FunDefEvaluator* fde = d_tds->getFunDefEvaluator();
+ fde->assertDefinition(q);
+ return;
+ }
+ Trace("cegqi") << "Register conjecture : " << q << std::endl;
+ if (options::sygusQePreproc())
+ {
+ d_waiting_conj.push_back(q);
+ }
+ else
+ {
+ // assign it now
+ assignConjecture(q);
}
}
@@ -321,8 +322,6 @@ bool SynthEngine::checkConjecture(SynthConjecture* conj)
bool addedLemma = false;
for (const Node& lem : cclems)
{
- Trace("cegqi-lemma") << "Cegqi::Lemma : counterexample : " << lem
- << std::endl;
if (d_quantEngine->addLemma(lem))
{
++(d_statistics.d_cegqi_lemmas_ce);
diff --git a/src/theory/quantifiers/sygus/term_database_sygus.cpp b/src/theory/quantifiers/sygus/term_database_sygus.cpp
index 79b4c9caa..d664a462d 100644
--- a/src/theory/quantifiers/sygus/term_database_sygus.cpp
+++ b/src/theory/quantifiers/sygus/term_database_sygus.cpp
@@ -741,9 +741,9 @@ Node TermDbSygus::rewriteNode(Node n) const
{
return fres;
}
- // It may have failed, in which case there are undefined symbols in res.
- // In this case, we revert to the result of rewriting in the return
- // statement below.
+ // It may have failed, in which case there are undefined symbols in res or
+ // we reached the limit of evaluations. In this case, we revert to the
+ // result of rewriting in the return statement below.
}
}
return res;
@@ -953,107 +953,6 @@ unsigned TermDbSygus::getAnchorDepth( Node n ) {
}
}
-Node TermDbSygus::unfold( Node en, std::map< Node, Node >& vtm, std::vector< Node >& exp, bool track_exp ) {
- if (en.getKind() != DT_SYGUS_EVAL)
- {
- Assert(en.isConst());
- return en;
- }
- Trace("sygus-db-debug") << "Unfold : " << en << std::endl;
- Node ev = en[0];
- if (track_exp)
- {
- std::map<Node, Node>::iterator itv = vtm.find(en[0]);
- Assert(itv != vtm.end());
- if (itv != vtm.end())
- {
- ev = itv->second;
- }
- Assert(en[0].getType() == ev.getType());
- Assert(ev.isConst());
- }
- Assert(ev.getKind() == kind::APPLY_CONSTRUCTOR);
- std::vector<Node> args;
- for (unsigned i = 1, nchild = en.getNumChildren(); i < nchild; i++)
- {
- args.push_back(en[i]);
- }
-
- Type headType = en[0].getType().toType();
- NodeManager* nm = NodeManager::currentNM();
- const Datatype& dt = static_cast<DatatypeType>(headType).getDatatype();
- unsigned i = datatypes::utils::indexOf(ev.getOperator());
- if (track_exp)
- {
- // explanation
- Node ee = nm->mkNode(
- kind::APPLY_TESTER, Node::fromExpr(dt[i].getTester()), en[0]);
- if (std::find(exp.begin(), exp.end(), ee) == exp.end())
- {
- exp.push_back(ee);
- }
- }
- // if we are a symbolic constructor, unfolding returns the subterm itself
- Node sop = Node::fromExpr(dt[i].getSygusOp());
- if (sop.getAttribute(SygusAnyConstAttribute()))
- {
- Trace("sygus-db-debug") << "...it is an any-constant constructor"
- << std::endl;
- Assert(dt[i].getNumArgs() == 1);
- if (en[0].getKind() == APPLY_CONSTRUCTOR)
- {
- return en[0][0];
- }
- else
- {
- return nm->mkNode(
- APPLY_SELECTOR_TOTAL, dt[i].getSelectorInternal(headType, 0), en[0]);
- }
- }
-
- Assert(!dt.isParametric());
- std::map<int, Node> pre;
- for (unsigned j = 0, nargs = dt[i].getNumArgs(); j < nargs; j++)
- {
- std::vector<Node> cc;
- Node s;
- // get the j^th subfield of en
- if (en[0].getKind() == kind::APPLY_CONSTRUCTOR)
- {
- // if it is a concrete constructor application, as an optimization,
- // just return the argument
- s = en[0][j];
- }
- else
- {
- s = nm->mkNode(kind::APPLY_SELECTOR_TOTAL,
- dt[i].getSelectorInternal(headType, j),
- en[0]);
- }
- cc.push_back(s);
- if (track_exp)
- {
- // update vtm map
- vtm[s] = ev[j];
- }
- cc.insert(cc.end(), args.begin(), args.end());
- pre[j] = nm->mkNode(DT_SYGUS_EVAL, cc);
- }
- Node ret = mkGeneric(dt, i, pre);
- // apply the appropriate substitution to ret
- ret = datatypes::utils::applySygusArgs(dt, sop, ret, args);
- // rewrite
- ret = Rewriter::rewrite(ret);
- return ret;
-}
-
-Node TermDbSygus::unfold(Node en)
-{
- std::map<Node, Node> vtm;
- std::vector<Node> exp;
- return unfold(en, vtm, exp, false);
-}
-
Node TermDbSygus::evaluateBuiltin(TypeNode tn,
Node bn,
std::vector<Node>& args,
@@ -1105,6 +1004,8 @@ Node TermDbSygus::evaluateWithUnfolding(
Trace("dt-eval-unfold-debug")
<< "Optimize: evaluate constant head " << ret << std::endl;
// can just do direct evaluation here
+ // notice we prefer this code to the rewriter since it may use
+ // the evaluator
std::vector<Node> args;
bool success = true;
for (unsigned i = 1, nchild = ret.getNumChildren(); i < nchild; i++)
@@ -1127,7 +1028,7 @@ Node TermDbSygus::evaluateWithUnfolding(
return rete;
}
}
- ret = unfold( ret );
+ ret = d_eval_unfold->unfold(ret);
}
if( ret.getNumChildren()>0 ){
std::vector< Node > children;
@@ -1136,7 +1037,7 @@ Node TermDbSygus::evaluateWithUnfolding(
}
bool childChanged = false;
for( unsigned i=0; i<ret.getNumChildren(); i++ ){
- Node nc = evaluateWithUnfolding( ret[i], visited );
+ Node nc = evaluateWithUnfolding(ret[i], visited);
childChanged = childChanged || nc!=ret[i];
children.push_back( nc );
}
@@ -1152,9 +1053,10 @@ Node TermDbSygus::evaluateWithUnfolding(
}
}
-Node TermDbSygus::evaluateWithUnfolding( Node n ) {
+Node TermDbSygus::evaluateWithUnfolding(Node n)
+{
std::unordered_map<Node, Node, NodeHashFunction> visited;
- return evaluateWithUnfolding( n, visited );
+ return evaluateWithUnfolding(n, visited);
}
bool TermDbSygus::isEvaluationPoint(Node n) const
@@ -1180,4 +1082,3 @@ bool TermDbSygus::isEvaluationPoint(Node n) const
}/* CVC4::theory::quantifiers namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
-
diff --git a/src/theory/quantifiers/sygus/term_database_sygus.h b/src/theory/quantifiers/sygus/term_database_sygus.h
index 0ec883537..76b5039f6 100644
--- a/src/theory/quantifiers/sygus/term_database_sygus.h
+++ b/src/theory/quantifiers/sygus/term_database_sygus.h
@@ -453,31 +453,6 @@ class TermDbSygus {
static Node getAnchor( Node n );
static unsigned getAnchorDepth( Node n );
- public:
- /** unfold
- *
- * This method returns the one-step unfolding of an evaluation function
- * application. An example of a one step unfolding is:
- * eval( C_+( d1, d2 ), t ) ---> +( eval( d1, t ), eval( d2, t ) )
- *
- * This function does this unfolding for a (possibly symbolic) evaluation
- * head, where the argument "variable to model" vtm stores the model value of
- * variables from this head. This allows us to track an explanation of the
- * unfolding in the vector exp when track_exp is true.
- *
- * For example, if vtm[d] = C_+( C_x(), C_0() ) and track_exp is true, then
- * this method applied to eval( d, t ) will return
- * +( eval( d.0, t ), eval( d.1, t ) ), and is-C_+( d ) is added to exp.
- */
- Node unfold(Node en,
- std::map<Node, Node>& vtm,
- std::vector<Node>& exp,
- bool track_exp = true);
- /**
- * Same as above, but without explanation tracking. This is used for concrete
- * evaluation heads
- */
- Node unfold(Node en);
};
}/* CVC4::theory::quantifiers namespace */
diff --git a/src/theory/quantifiers/sygus/type_info.cpp b/src/theory/quantifiers/sygus/type_info.cpp
index 1ff0457c4..71ccd60c9 100644
--- a/src/theory/quantifiers/sygus/type_info.cpp
+++ b/src/theory/quantifiers/sygus/type_info.cpp
@@ -140,17 +140,17 @@ void SygusTypeInfo::initialize(TermDbSygus* tds, TypeNode tn)
d_sym_cons_any_constant = i;
d_has_subterm_sym_cons = true;
}
- // TODO (as part of #1170): we still do not properly catch type
- // errors in sygus grammars for arguments of builtin operators.
- // The challenge is that we easily ask for expected argument types of
- // builtin operators e.g. PLUS. Hence the call to mkGeneric below
- // will throw a type exception.
d_ops[n] = i;
d_arg_ops[i] = n;
Trace("sygus-db") << std::endl;
- // ensure that terms that this constructor encodes are
- // of the type specified in the datatype. This will fail if
- // e.g. bitvector-and is a constructor of an integer grammar.
+ // We must properly catch type errors in sygus grammars for arguments of
+ // builtin operators. The challenge is that we easily ask for expected
+ // argument types of builtin operators e.g. PLUS. Hence we use a call to
+ // mkGeneric below. This ensures that terms that this constructor encodes
+ // are of the type specified in the datatype. This will fail if
+ // e.g. bitvector-and is a constructor of an integer grammar. Our (version
+ // 2) SyGuS parser ensures that sygus constructors are built from well-typed
+ // terms, so the term created by mkGeneric will also be well-typed here.
Node g = tds->mkGeneric(dt, i);
TypeNode gtn = g.getType();
AlwaysAssert(gtn.isSubtypeOf(btn))
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback