summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL.md3
-rwxr-xr-xconfigure.sh6
-rw-r--r--src/api/cvc4cpp.cpp27
-rw-r--r--src/api/cvc4cpp.h23
-rw-r--r--src/options/options_handler.cpp7
-rw-r--r--src/options/quantifiers_modes.h2
-rw-r--r--src/options/quantifiers_options.toml4
-rw-r--r--src/theory/datatypes/datatypes_sygus.cpp63
-rw-r--r--src/theory/quantifiers/sygus/cegis.cpp24
-rw-r--r--src/theory/quantifiers/sygus/cegis_unif.cpp21
-rw-r--r--src/theory/quantifiers/sygus/enum_stream_substitution.cpp13
-rw-r--r--src/theory/quantifiers/sygus/enum_stream_substitution.h8
-rw-r--r--src/theory/quantifiers/sygus/sygus_enumerator.cpp183
-rw-r--r--src/theory/quantifiers/sygus/sygus_enumerator.h17
-rw-r--r--src/theory/quantifiers/sygus/sygus_grammar_cons.cpp378
-rw-r--r--src/theory/quantifiers/sygus/sygus_grammar_cons.h3
-rw-r--r--src/theory/quantifiers/sygus/sygus_pbe.cpp18
-rw-r--r--src/theory/quantifiers/sygus/synth_conjecture.cpp88
-rw-r--r--src/theory/quantifiers/sygus/synth_conjecture.h26
-rw-r--r--src/theory/quantifiers/sygus/term_database_sygus.cpp128
-rw-r--r--src/theory/quantifiers/sygus/term_database_sygus.h61
-rw-r--r--src/theory/strings/theory_strings_preprocess.cpp20
-rw-r--r--src/theory/strings/theory_strings_rewriter.cpp2
-rw-r--r--test/regress/CMakeLists.txt6
-rw-r--r--test/regress/README.md20
-rw-r--r--test/regress/regress0/bug217.smt21
-rw-r--r--test/regress/regress0/bv/ackermann3.smt223
-rw-r--r--test/regress/regress0/bv/ackermann4.smt216
-rw-r--r--test/regress/regress0/bv/bool-to-bv.smt27
-rw-r--r--test/regress/regress0/bv/bv-to-bool1.smt (renamed from test/regress/regress0/bv/bv-to-bool.smt)0
-rw-r--r--test/regress/regress0/bv/bv-to-bool2.smt211
-rw-r--r--test/regress/regress0/quantifiers/macros-real-arg.smt23
-rw-r--r--test/regress/regress0/strings/unsound-repl-rewrite.smt28
-rw-r--r--test/regress/regress1/sygus/commutative-stream.sy2
-rw-r--r--test/unit/api/CMakeLists.txt4
-rw-r--r--test/unit/api/api_guards_black.h473
-rw-r--r--test/unit/api/solver_black.h230
-rw-r--r--test/unit/api/sort_black.h279
-rw-r--r--test/unit/api/term_black.h37
-rw-r--r--test/unit/theory/theory_strings_rewriter_white.h12
40 files changed, 1360 insertions, 897 deletions
diff --git a/INSTALL.md b/INSTALL.md
index 98cef2061..dc0de6cb4 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -151,7 +151,8 @@ provided with CVC4.
### CxxTest Unit Testing Framework (Unit Tests)
[CxxTest](http://cxxtest.com) is required to optionally run CVC4's unit tests
-(included with the distribution). See [Testing](testing) below for more details.
+(included with the distribution).
+See [Testing CVC4](#Testing-CVC4) below for more details.
## Building CVC4
diff --git a/configure.sh b/configure.sh
index 1cc104c94..d5f466ec6 100755
--- a/configure.sh
+++ b/configure.sh
@@ -53,7 +53,7 @@ The following flags enable optional packages (disable with --no-<option name>).
--glpk use GLPK simplex solver
--abc use the ABC AIG library
--cadical use the CaDiCaL SAT solver
- --cryptominisat use the CryptoMiniSat sat solver
+ --cryptominisat use the CryptoMiniSat SAT solver
--lfsc use the LFSC proof checker
--symfpu use SymFPU for floating point solver
--portfolio build the multithreaded portfolio version of CVC4
@@ -197,8 +197,8 @@ do
--debug-symbols) debug_symbols=ON;;
--no-debug-symbols) debug_symbols=OFF;;
- --debug-context-memory-manager) debug_context_mm=ON;;
- --no-debug-context-memory-manager) debug_context_mm=OFF;;
+ --debug-context-mm) debug_context_mm=ON;;
+ --no-debug-context-mm) debug_context_mm=OFF;;
--dumping) dumping=ON;;
--no-dumping) dumping=OFF;;
diff --git a/src/api/cvc4cpp.cpp b/src/api/cvc4cpp.cpp
index be7c5c665..b4d3b013d 100644
--- a/src/api/cvc4cpp.cpp
+++ b/src/api/cvc4cpp.cpp
@@ -749,15 +749,6 @@ Sort::Sort(const CVC4::Type& t) : d_type(new CVC4::Type(t)) {}
Sort::~Sort() {}
-Sort& Sort::operator=(const Sort& s)
-{
- if (this != &s)
- {
- *d_type = *s.d_type;
- }
- return *this;
-}
-
bool Sort::operator==(const Sort& s) const { return *d_type == *s.d_type; }
bool Sort::operator!=(const Sort& s) const { return *d_type != *s.d_type; }
@@ -1008,15 +999,6 @@ Term::Term(const CVC4::Expr& e) : d_expr(new CVC4::Expr(e)) {}
Term::~Term() {}
-Term& Term::operator=(const Term& t)
-{
- if (this != &t)
- {
- *d_expr = *t.d_expr;
- }
- return *this;
-}
-
bool Term::operator==(const Term& t) const { return *d_expr == *t.d_expr; }
bool Term::operator!=(const Term& t) const { return *d_expr != *t.d_expr; }
@@ -1180,15 +1162,6 @@ OpTerm::OpTerm(const CVC4::Expr& e) : d_expr(new CVC4::Expr(e)) {}
OpTerm::~OpTerm() {}
-OpTerm& OpTerm::operator=(const OpTerm& t)
-{
- if (this != &t)
- {
- *d_expr = *t.d_expr;
- }
- return *this;
-}
-
bool OpTerm::operator==(const OpTerm& t) const { return *d_expr == *t.d_expr; }
bool OpTerm::operator!=(const OpTerm& t) const { return *d_expr != *t.d_expr; }
diff --git a/src/api/cvc4cpp.h b/src/api/cvc4cpp.h
index fc07a1cd7..aebeffb0d 100644
--- a/src/api/cvc4cpp.h
+++ b/src/api/cvc4cpp.h
@@ -197,13 +197,6 @@ class CVC4_PUBLIC Sort
~Sort();
/**
- * Assignment operator.
- * @param s the sort to assign to this sort
- * @return this sort after assignment
- */
- Sort& operator=(const Sort& s);
-
- /**
* Comparison for structural equality.
* @param s the sort to compare to
* @return true if the sorts are equal
@@ -554,14 +547,6 @@ class CVC4_PUBLIC Term
~Term();
/**
- * Assignment operator, makes a copy of the given term.
- * Both terms must belong to the same solver object.
- * @param t the term to assign
- * @return the reference to this term after assignment
- */
- Term& operator=(const Term& t);
-
- /**
* Syntactic equality operator.
* Return true if both terms are syntactically identical.
* Both terms must belong to the same solver object.
@@ -844,14 +829,6 @@ class CVC4_PUBLIC OpTerm
~OpTerm();
/**
- * Assignment operator, makes a copy of the given operator term.
- * Both terms must belong to the same solver object.
- * @param t the term to assign
- * @return the reference to this operator term after assignment
- */
- OpTerm& operator=(const OpTerm& t);
-
- /**
* Syntactic equality operator.
* Return true if both operator terms are syntactically identical.
* Both operator terms must belong to the same solver object.
diff --git a/src/options/options_handler.cpp b/src/options/options_handler.cpp
index e4c0276ea..565f28334 100644
--- a/src/options/options_handler.cpp
+++ b/src/options/options_handler.cpp
@@ -538,6 +538,9 @@ enum \n\
var-agnostic \n\
+ Use sygus solver to enumerate terms that are agnostic to variables. \n\
\n\
+auto (default) \n\
++ Internally decide the best policy for each enumerator. \n\
+\n\
";
const std::string OptionsHandler::s_macrosQuantHelp = "\
@@ -987,6 +990,10 @@ OptionsHandler::stringToSygusActiveGenMode(std::string option,
{
return theory::quantifiers::SYGUS_ACTIVE_GEN_VAR_AGNOSTIC;
}
+ else if (optarg == "auto")
+ {
+ return theory::quantifiers::SYGUS_ACTIVE_GEN_AUTO;
+ }
else if (optarg == "help")
{
puts(s_sygusActiveGenHelp.c_str());
diff --git a/src/options/quantifiers_modes.h b/src/options/quantifiers_modes.h
index 392393a91..05388cdf6 100644
--- a/src/options/quantifiers_modes.h
+++ b/src/options/quantifiers_modes.h
@@ -272,6 +272,8 @@ enum SygusActiveGenMode
SYGUS_ACTIVE_GEN_ENUM,
/** use variable-agnostic enumerators */
SYGUS_ACTIVE_GEN_VAR_AGNOSTIC,
+ /** internally decide the best policy for each enumerator */
+ SYGUS_ACTIVE_GEN_AUTO,
};
enum MacrosQuantMode {
diff --git a/src/options/quantifiers_options.toml b/src/options/quantifiers_options.toml
index 0b28c6a27..c555c37bf 100644
--- a/src/options/quantifiers_options.toml
+++ b/src/options/quantifiers_options.toml
@@ -1044,7 +1044,7 @@ header = "options/quantifiers_options.h"
category = "regular"
long = "sygus-active-gen=MODE"
type = "CVC4::theory::quantifiers::SygusActiveGenMode"
- default = "CVC4::theory::quantifiers::SYGUS_ACTIVE_GEN_NONE"
+ default = "CVC4::theory::quantifiers::SYGUS_ACTIVE_GEN_AUTO"
handler = "stringToSygusActiveGenMode"
includes = ["options/quantifiers_modes.h"]
read_only = true
@@ -1135,7 +1135,7 @@ header = "options/quantifiers_options.h"
category = "regular"
long = "sygus-pbe-multi-fair"
type = "bool"
- default = "true"
+ default = "false"
help = "when using multiple enumerators, ensure that we only register value of minimial term size"
[[option]]
diff --git a/src/theory/datatypes/datatypes_sygus.cpp b/src/theory/datatypes/datatypes_sygus.cpp
index a7763bff1..4c7dcec9a 100644
--- a/src/theory/datatypes/datatypes_sygus.cpp
+++ b/src/theory/datatypes/datatypes_sygus.cpp
@@ -1304,7 +1304,8 @@ void SygusSymBreakNew::preRegisterTerm( TNode n, std::vector< Node >& lemmas )
}
}
-void SygusSymBreakNew::registerSizeTerm( Node e, std::vector< Node >& lemmas ) {
+void SygusSymBreakNew::registerSizeTerm(Node e, std::vector<Node>& lemmas)
+{
if (d_register_st.find(e) != d_register_st.end())
{
// already registered
@@ -1545,15 +1546,32 @@ void SygusSymBreakNew::check( std::vector< Node >& lemmas ) {
{
// symmetry breaking lemmas should only be for enumerators
Assert(d_register_st[a]);
- std::vector<Node> sbl;
- d_tds->getSymBreakLemmas(a, sbl);
- for (const Node& lem : sbl)
+ // If this is a non-basic enumerator, process its symmetry breaking
+ // clauses. Since this class is not responsible for basic enumerators,
+ // their symmetry breaking clauses are ignored.
+ if (!d_tds->isBasicEnumerator(a))
{
- TypeNode tn = d_tds->getTypeForSymBreakLemma(lem);
- unsigned sz = d_tds->getSizeForSymBreakLemma(lem);
- registerSymBreakLemma(tn, lem, sz, a, lemmas);
+ std::vector<Node> sbl;
+ d_tds->getSymBreakLemmas(a, sbl);
+ for (const Node& lem : sbl)
+ {
+ if (d_tds->isSymBreakLemmaTemplate(lem))
+ {
+ // register the lemma template
+ TypeNode tn = d_tds->getTypeForSymBreakLemma(lem);
+ unsigned sz = d_tds->getSizeForSymBreakLemma(lem);
+ registerSymBreakLemma(tn, lem, sz, a, lemmas);
+ }
+ else
+ {
+ Trace("dt-sygus-debug")
+ << "DT sym break lemma : " << lem << std::endl;
+ // it is a normal lemma
+ lemmas.push_back(lem);
+ }
+ }
+ d_tds->clearSymBreakLemmas(a);
}
- d_tds->clearSymBreakLemmas(a);
}
}
if (!lemmas.empty())
@@ -1563,9 +1581,20 @@ void SygusSymBreakNew::check( std::vector< Node >& lemmas ) {
}
// register search values, add symmetry breaking lemmas if applicable
- for( std::map< Node, bool >::iterator it = d_register_st.begin(); it != d_register_st.end(); ++it ){
- if( it->second ){
- Node prog = it->first;
+ std::vector<Node> es;
+ d_tds->getEnumerators(es);
+ bool needsRecheck = false;
+ // for each enumerator registered to d_tds
+ for (Node& prog : es)
+ {
+ if (d_register_st.find(prog) == d_register_st.end())
+ {
+ // not yet registered, do so now
+ registerSizeTerm(prog, lemmas);
+ needsRecheck = true;
+ }
+ else
+ {
Trace("dt-sygus-debug") << "Checking model value of " << prog << "..."
<< std::endl;
Assert(prog.getType().isDatatype());
@@ -1624,14 +1653,12 @@ void SygusSymBreakNew::check( std::vector< Node >& lemmas ) {
prog.setAttribute(ssbo, !isExc);
}
}
- //register any measured terms that we haven't encountered yet (should only be invoked on first call to check
- Trace("sygus-sb") << "Register size terms..." << std::endl;
- std::vector< Node > mts;
- d_tds->getEnumerators(mts);
- for( unsigned i=0; i<mts.size(); i++ ){
- registerSizeTerm( mts[i], lemmas );
+ Trace("sygus-sb") << "SygusSymBreakNew::check: finished." << std::endl;
+ if (needsRecheck)
+ {
+ Trace("sygus-sb") << " SygusSymBreakNew::rechecking..." << std::endl;
+ return check(lemmas);
}
- Trace("sygus-sb") << " SygusSymBreakNew::check: finished." << std::endl;
if (Trace.isOn("cegqi-engine") && !d_szinfo.empty())
{
diff --git a/src/theory/quantifiers/sygus/cegis.cpp b/src/theory/quantifiers/sygus/cegis.cpp
index 79bec60ee..6aca71ca3 100644
--- a/src/theory/quantifiers/sygus/cegis.cpp
+++ b/src/theory/quantifiers/sygus/cegis.cpp
@@ -69,17 +69,10 @@ bool Cegis::processInitialize(Node n,
{
Trace("cegis") << "Initialize cegis..." << std::endl;
unsigned csize = candidates.size();
- // We only can use actively-generated enumerators if there is only one
- // function-to-synthesize. Otherwise, we would have to generate a "product" of
- // two actively-generated enumerators. That is, given a conjecture with two
- // functions-to-synthesize with enumerators e_f and e_g, if:
- // e_f -> t1, ..., tn
- // e_g -> s1, ..., sm
- // This module would expect constructCandidates calls (e_f,e_g) -> (ti, sj)
- // for each i,j. We do not do this and revert to the default behavior of
- // this module instead.
- bool isActiveGen =
- options::sygusActiveGenMode() != SYGUS_ACTIVE_GEN_NONE && csize == 1;
+ // The role of enumerators is to be either the single solution or part of
+ // a solution involving multiple enumerators.
+ EnumeratorRole erole =
+ csize == 1 ? ROLE_ENUM_SINGLE_SOLUTION : ROLE_ENUM_MULTI_SOLUTION;
// initialize an enumerator for each candidate
for (unsigned i = 0; i < csize; i++)
{
@@ -98,13 +91,8 @@ bool Cegis::processInitialize(Node n,
}
}
Trace("cegis") << std::endl;
- // variable agnostic enumerators require an active guard
- d_tds->registerEnumerator(candidates[i],
- candidates[i],
- d_parent,
- isActiveGen,
- do_repair_const,
- isActiveGen);
+ d_tds->registerEnumerator(
+ candidates[i], candidates[i], d_parent, erole, do_repair_const);
}
return true;
}
diff --git a/src/theory/quantifiers/sygus/cegis_unif.cpp b/src/theory/quantifiers/sygus/cegis_unif.cpp
index dbde79aae..18e313bf0 100644
--- a/src/theory/quantifiers/sygus/cegis_unif.cpp
+++ b/src/theory/quantifiers/sygus/cegis_unif.cpp
@@ -44,7 +44,12 @@ bool CegisUnif::processInitialize(Node n,
std::map<Node, Node> pt_to_cond;
// strategy lemmas for each strategy point
std::map<Node, std::vector<Node>> strategy_lemmas;
- // Initialize strategies for all functions-to-synhesize
+ // Initialize strategies for all functions-to-synthesize
+ // The role of non-unification enumerators is to be either the single solution
+ // or part of a solution involving multiple enumerators.
+ EnumeratorRole eroleNonUnif = candidates.size() == 1
+ ? ROLE_ENUM_SINGLE_SOLUTION
+ : ROLE_ENUM_MULTI_SOLUTION;
for (const Node& f : candidates)
{
// Init UNIF util for this candidate
@@ -53,7 +58,7 @@ bool CegisUnif::processInitialize(Node n,
if (!d_sygus_unif.usingUnif(f))
{
Trace("cegis-unif") << "* non-unification candidate : " << f << std::endl;
- d_tds->registerEnumerator(f, f, d_parent);
+ d_tds->registerEnumerator(f, f, d_parent, eroleNonUnif);
d_non_unif_candidates.push_back(f);
}
else
@@ -462,7 +467,8 @@ Node CegisUnifEnumDecisionStrategy::mkLiteral(unsigned n)
exclude_cons,
term_irrelevant);
d_virtual_enum = nm->mkSkolem("_ve", vtn);
- d_tds->registerEnumerator(d_virtual_enum, Node::null(), d_parent);
+ d_tds->registerEnumerator(
+ d_virtual_enum, Node::null(), d_parent, ROLE_ENUM_CONSTRAINED);
}
// if new_size is a power of two, then isPow2 returns log2(new_size)+1
// otherwise, this returns 0. In the case it returns 0, we don't care
@@ -606,20 +612,17 @@ void CegisUnifEnumDecisionStrategy::setUpEnumerator(Node e,
}
// register the enumerator
si.d_enums[index].push_back(e);
- bool mkActiveGuard = false;
- bool isActiveGen = false;
+ EnumeratorRole erole = ROLE_ENUM_CONSTRAINED;
// 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)
{
- mkActiveGuard = true;
- isActiveGen = options::sygusActiveGenMode() != SYGUS_ACTIVE_GEN_NONE;
+ erole = ROLE_ENUM_POOL;
}
Trace("cegis-unif-enum") << "* Registering new enumerator " << e
<< " to strategy point " << si.d_pt << "\n";
- d_tds->registerEnumerator(
- e, si.d_pt, d_parent, mkActiveGuard, false, isActiveGen);
+ d_tds->registerEnumerator(e, si.d_pt, d_parent, erole, false);
}
void CegisUnifEnumDecisionStrategy::registerEvalPts(
diff --git a/src/theory/quantifiers/sygus/enum_stream_substitution.cpp b/src/theory/quantifiers/sygus/enum_stream_substitution.cpp
index 24770ade0..e8daa4256 100644
--- a/src/theory/quantifiers/sygus/enum_stream_substitution.cpp
+++ b/src/theory/quantifiers/sygus/enum_stream_substitution.cpp
@@ -608,8 +608,17 @@ bool EnumStreamSubstitution::CombinationState::getNextCombination()
}
void EnumStreamConcrete::initialize(Node e) { d_ess.initialize(e.getType()); }
-void EnumStreamConcrete::addValue(Node v) { d_ess.resetValue(v); }
-Node EnumStreamConcrete::getNext() { return d_ess.getNext(); }
+void EnumStreamConcrete::addValue(Node v)
+{
+ d_ess.resetValue(v);
+ d_currTerm = d_ess.getNext();
+}
+bool EnumStreamConcrete::increment()
+{
+ d_currTerm = d_ess.getNext();
+ return !d_currTerm.isNull();
+}
+Node EnumStreamConcrete::getCurrent() { return d_currTerm; }
} // namespace quantifiers
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/quantifiers/sygus/enum_stream_substitution.h b/src/theory/quantifiers/sygus/enum_stream_substitution.h
index 38fa0627b..476a364ea 100644
--- a/src/theory/quantifiers/sygus/enum_stream_substitution.h
+++ b/src/theory/quantifiers/sygus/enum_stream_substitution.h
@@ -286,12 +286,16 @@ class EnumStreamConcrete : public EnumValGenerator
void initialize(Node e) override;
/** get that value v was enumerated */
void addValue(Node v) override;
- /** get the next value enumerated by this class */
- Node getNext() override;
+ /** increment */
+ bool increment() override;
+ /** get the current value enumerated by this class */
+ Node getCurrent() override;
private:
/** stream substitution utility */
EnumStreamSubstitution d_ess;
+ /** the current term generated by this class */
+ Node d_currTerm;
};
} // namespace quantifiers
diff --git a/src/theory/quantifiers/sygus/sygus_enumerator.cpp b/src/theory/quantifiers/sygus/sygus_enumerator.cpp
index 61ab9007a..5c3e44a33 100644
--- a/src/theory/quantifiers/sygus/sygus_enumerator.cpp
+++ b/src/theory/quantifiers/sygus/sygus_enumerator.cpp
@@ -25,21 +25,78 @@ namespace theory {
namespace quantifiers {
SygusEnumerator::SygusEnumerator(TermDbSygus* tds, SynthConjecture* p)
- : d_tds(tds),
- d_parent(p),
- d_tlEnum(nullptr),
- d_abortSize(-1),
- d_firstTime(false)
+ : d_tds(tds), d_parent(p), d_tlEnum(nullptr), d_abortSize(-1)
{
}
void SygusEnumerator::initialize(Node e)
{
+ Trace("sygus-enum") << "SygusEnumerator::initialize " << e << std::endl;
d_enum = e;
d_etype = d_enum.getType();
+ Assert(d_etype.isDatatype());
+ Assert(d_etype.getDatatype().isSygus());
d_tlEnum = getMasterEnumForType(d_etype);
d_abortSize = options::sygusAbortSize();
- d_firstTime = true;
+
+ // Get the statically registered symmetry breaking clauses for e, see if they
+ // can be used for speeding up the enumeration.
+ NodeManager* nm = NodeManager::currentNM();
+ std::vector<Node> sbl;
+ d_tds->getSymBreakLemmas(e, sbl);
+ Node ag = d_tds->getActiveGuardForEnumerator(e);
+ Node truen = nm->mkConst(true);
+ // use TNode for substitute below
+ TNode agt = ag;
+ TNode truent = truen;
+ Assert(d_tcache.find(d_etype) != d_tcache.end());
+ const Datatype& dt = d_etype.getDatatype();
+ for (const Node& lem : sbl)
+ {
+ if (!d_tds->isSymBreakLemmaTemplate(lem))
+ {
+ // substitute its active guard by true and rewrite
+ Node slem = lem.substitute(agt, truent);
+ slem = Rewriter::rewrite(slem);
+ // break into conjuncts
+ std::vector<Node> sblc;
+ if (slem.getKind() == AND)
+ {
+ for (const Node& slemc : slem)
+ {
+ sblc.push_back(slemc);
+ }
+ }
+ else
+ {
+ sblc.push_back(slem);
+ }
+ for (const Node& sbl : sblc)
+ {
+ Trace("sygus-enum")
+ << " symmetry breaking lemma : " << sbl << std::endl;
+ // if its a negation of a unit top-level tester, then this specifies
+ // that we should not enumerate terms whose top symbol is that
+ // constructor
+ if (sbl.getKind() == NOT)
+ {
+ Node a;
+ int tst = datatypes::DatatypesRewriter::isTester(sbl[0], a);
+ if (tst >= 0)
+ {
+ if (a == e)
+ {
+ Node cons = Node::fromExpr(dt[tst].getConstructor());
+ Trace("sygus-enum") << " ...unit exclude constructor #" << tst
+ << ", constructor " << cons << std::endl;
+ d_sbExcTlCons.insert(cons);
+ }
+ }
+ }
+ // other symmetry breaking lemmas such as disjunctions are not used
+ }
+ }
+ }
}
void SygusEnumerator::addValue(Node v)
@@ -47,17 +104,9 @@ void SygusEnumerator::addValue(Node v)
// do nothing
}
-Node SygusEnumerator::getNext()
+bool SygusEnumerator::increment() { return d_tlEnum->increment(); }
+Node SygusEnumerator::getCurrent()
{
- if (d_firstTime)
- {
- d_firstTime = false;
- }
- else if (!d_tlEnum->increment())
- {
- // no more values
- return Node::null();
- }
if (d_abortSize >= 0)
{
int cs = static_cast<int>(d_tlEnum->getCurrentSize());
@@ -70,14 +119,30 @@ Node SygusEnumerator::getNext()
}
}
Node ret = d_tlEnum->getCurrent();
- Trace("sygus-enum") << "Enumerate : " << d_tds->sygusToBuiltin(ret)
- << std::endl;
+ if (!ret.isNull() && !d_sbExcTlCons.empty())
+ {
+ Assert(ret.hasOperator());
+ // might be excluded by an externally provided symmetry breaking clause
+ if (d_sbExcTlCons.find(ret.getOperator()) != d_sbExcTlCons.end())
+ {
+ Trace("sygus-enum-exc")
+ << "Exclude (external) : " << d_tds->sygusToBuiltin(ret) << std::endl;
+ ret = Node::null();
+ }
+ }
+ if (Trace.isOn("sygus-enum"))
+ {
+ Trace("sygus-enum") << "Enumerate : ";
+ TermDbSygus::toStreamSygus("sygus-enum", ret);
+ Trace("sygus-enum") << std::endl;
+ }
return ret;
}
SygusEnumerator::TermCache::TermCache()
: d_tds(nullptr),
d_pbe(nullptr),
+ d_isSygusType(false),
d_numConClasses(0),
d_sizeEnum(0),
d_isComplete(false)
@@ -241,33 +306,37 @@ bool SygusEnumerator::TermCache::addTerm(Node n)
d_terms.push_back(n);
return true;
}
- Node bn = d_tds->sygusToBuiltin(n);
- Node bnr = d_tds->getExtRewriter()->extendedRewrite(bn);
- // must be unique up to rewriting
- if (d_bterms.find(bnr) != d_bterms.end())
- {
- Trace("sygus-enum-exc") << "Exclude: " << bn << std::endl;
- return false;
- }
- // if we are doing PBE symmetry breaking
- if (d_pbe != nullptr)
+ Assert(!n.isNull());
+ if (options::sygusSymBreakDynamic())
{
- // Is it equivalent under examples?
- Node bne = d_pbe->addSearchVal(d_tn, d_enum, bnr);
- if (!bne.isNull())
+ Node bn = d_tds->sygusToBuiltin(n);
+ Node bnr = d_tds->getExtRewriter()->extendedRewrite(bn);
+ // must be unique up to rewriting
+ if (d_bterms.find(bnr) != d_bterms.end())
{
- if (bnr != bne)
+ Trace("sygus-enum-exc") << "Exclude: " << bn << std::endl;
+ return false;
+ }
+ // if we are doing PBE symmetry breaking
+ if (d_pbe != nullptr)
+ {
+ // Is it equivalent under examples?
+ Node bne = d_pbe->addSearchVal(d_tn, d_enum, bnr);
+ if (!bne.isNull())
{
- Trace("sygus-enum-exc") << "Exclude (by examples): " << bn
- << ", since we already have " << bne
- << "!=" << bnr << std::endl;
- return false;
+ if (bnr != bne)
+ {
+ Trace("sygus-enum-exc") << "Exclude (by examples): " << bn
+ << ", since we already have " << bne
+ << "!=" << bnr << std::endl;
+ return false;
+ }
}
}
+ Trace("sygus-enum-terms") << "tc(" << d_tn << "): term " << bn << std::endl;
+ d_bterms.insert(bnr);
}
- Trace("sygus-enum-terms") << "tc(" << d_tn << "): term " << bn << std::endl;
d_terms.push_back(n);
- d_bterms.insert(bnr);
return true;
}
void SygusEnumerator::TermCache::pushEnumSizeIndex()
@@ -302,7 +371,12 @@ void SygusEnumerator::TermCache::setComplete() { d_isComplete = true; }
unsigned SygusEnumerator::TermEnum::getCurrentSize() { return d_currSize; }
SygusEnumerator::TermEnum::TermEnum() : d_se(nullptr), d_currSize(0) {}
SygusEnumerator::TermEnumSlave::TermEnumSlave()
- : TermEnum(), d_sizeLim(0), d_index(0), d_indexNextEnd(0), d_master(nullptr)
+ : TermEnum(),
+ d_sizeLim(0),
+ d_index(0),
+ d_indexNextEnd(0),
+ d_hasIndexNextEnd(false),
+ d_master(nullptr)
{
}
@@ -384,7 +458,7 @@ bool SygusEnumerator::TermEnumSlave::validateIndex()
Trace("sygus-enum-debug2") << "slave(" << d_tn << ") : validate index...\n";
SygusEnumerator::TermCache& tc = d_se->d_tcache[d_tn];
// ensure that index is in the range
- if (d_index >= tc.getNumTerms())
+ while (d_index >= tc.getNumTerms())
{
Assert(d_index == tc.getNumTerms());
Trace("sygus-enum-debug2") << "slave(" << d_tn << ") : force master...\n";
@@ -494,6 +568,7 @@ SygusEnumerator::TermEnum* SygusEnumerator::getMasterEnumForType(TypeNode tn)
SygusEnumerator::TermEnumMaster::TermEnumMaster()
: TermEnum(),
d_isIncrementing(false),
+ d_currTermSet(false),
d_consClassNum(0),
d_ccWeight(0),
d_consNum(0),
@@ -515,6 +590,7 @@ bool SygusEnumerator::TermEnumMaster::initialize(SygusEnumerator* se,
d_currChildSize = 0;
d_ccCons.clear();
d_isIncrementing = false;
+ d_currTermSet = false;
bool ret = increment();
Trace("sygus-enum-debug") << "master(" << tn
<< "): finish init, ret = " << ret << "\n";
@@ -523,10 +599,11 @@ bool SygusEnumerator::TermEnumMaster::initialize(SygusEnumerator* se,
Node SygusEnumerator::TermEnumMaster::getCurrent()
{
- if (!d_currTerm.isNull())
+ if (d_currTermSet)
{
return d_currTerm;
}
+ d_currTermSet = true;
// construct based on the children
std::vector<Node> children;
const Datatype& dt = d_tn.getDatatype();
@@ -538,7 +615,13 @@ Node SygusEnumerator::TermEnumMaster::getCurrent()
for (unsigned i = 0, nargs = dt[cnum].getNumArgs(); i < nargs; i++)
{
Assert(d_children.find(i) != d_children.end());
- children.push_back(d_children[i].getCurrent());
+ Node cc = d_children[i].getCurrent();
+ if (cc.isNull())
+ {
+ d_currTerm = cc;
+ return cc;
+ }
+ children.push_back(cc);
}
d_currTerm = NodeManager::currentNM()->mkNode(APPLY_CONSTRUCTOR, children);
return d_currTerm;
@@ -705,21 +788,27 @@ bool SygusEnumerator::TermEnumMaster::incrementInternal()
Assert(d_childrenValid == d_ccTypes.size());
// do we have more constructors for the given children?
- while (d_consNum < d_ccCons.size())
+ if (d_consNum < d_ccCons.size())
{
Trace("sygus-enum-debug2") << "master(" << d_tn << "): try constructor "
<< d_consNum << std::endl;
// increment constructor index
// we will build for the current constructor and the given children
d_consNum++;
+ d_currTermSet = false;
d_currTerm = Node::null();
Node c = getCurrent();
- if (tc.addTerm(c))
+ if (!c.isNull())
{
- return true;
+ if (!tc.addTerm(c))
+ {
+ // the term was not unique based on rewriting
+ Trace("sygus-enum-debug2") << "master(" << d_tn
+ << "): failed addTerm\n";
+ d_currTerm = Node::null();
+ }
}
- Trace("sygus-enum-debug2") << "master(" << d_tn << "): failed addTerm\n";
- // the term was not unique based on rewriting
+ return true;
}
// finished constructors for this set of children, must increment children
diff --git a/src/theory/quantifiers/sygus/sygus_enumerator.h b/src/theory/quantifiers/sygus/sygus_enumerator.h
index 10a44da03..af6bb03f0 100644
--- a/src/theory/quantifiers/sygus/sygus_enumerator.h
+++ b/src/theory/quantifiers/sygus/sygus_enumerator.h
@@ -50,8 +50,10 @@ class SygusEnumerator : public EnumValGenerator
void initialize(Node e) override;
/** Inform this generator that abstract value v was enumerated. */
void addValue(Node v) override;
+ /** increment */
+ bool increment() override;
/** Get the next concrete value generated by this class. */
- Node getNext() override;
+ Node getCurrent() override;
private:
/** pointer to term database sygus */
@@ -322,6 +324,8 @@ class SygusEnumerator : public EnumValGenerator
bool d_isIncrementing;
/** cache for getCurrent() */
Node d_currTerm;
+ /** is d_currTerm set */
+ bool d_currTermSet;
//----------------------------- current constructor class information
/** the next constructor class we are using */
unsigned d_consClassNum;
@@ -429,10 +433,17 @@ class SygusEnumerator : public EnumValGenerator
TermEnum* d_tlEnum;
/** the abort size, caches the value of --sygus-abort-size */
int d_abortSize;
- /** this flag is true for the first time to getNext() after initialize(e) */
- bool d_firstTime;
/** get master enumerator for type tn */
TermEnum* getMasterEnumForType(TypeNode tn);
+ //-------------------------------- externally specified symmetry breaking
+ /** set of constructors we disallow at top level
+ *
+ * A constructor C is disallowed at the top level if a symmetry breaking
+ * lemma that entails ~is-C( d_enum ) was registered to
+ * TermDbSygus::registerSymBreakLemma.
+ */
+ std::unordered_set<Node, NodeHashFunction> d_sbExcTlCons;
+ //-------------------------------- end externally specified symmetry breaking
};
} // namespace quantifiers
diff --git a/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp b/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp
index 47c701cf6..d6dfb3d26 100644
--- a/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp
+++ b/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp
@@ -374,18 +374,24 @@ void CegGrammarConstructor::mkSygusConstantsForType(TypeNode type,
// TODO #1178 : add other missing types
}
-void CegGrammarConstructor::collectSygusGrammarTypesFor( TypeNode range, std::vector< TypeNode >& types, std::map< TypeNode, std::vector< DatatypeConstructorArg > >& sels ){
+void CegGrammarConstructor::collectSygusGrammarTypesFor(
+ TypeNode range, std::vector<TypeNode>& types)
+{
if( !range.isBoolean() ){
if( std::find( types.begin(), types.end(), range )==types.end() ){
Trace("sygus-grammar-def") << "...will make grammar for " << range << std::endl;
types.push_back( range );
if( range.isDatatype() ){
- const Datatype& dt = ((DatatypeType)range.toType()).getDatatype();
- for( unsigned i=0; i<dt.getNumConstructors(); i++ ){
- for( unsigned j=0; j<dt[i].getNumArgs(); j++ ){
- TypeNode crange = TypeNode::fromType( ((SelectorType)dt[i][j].getType()).getRangeType() );
- sels[crange].push_back( dt[i][j] );
- collectSygusGrammarTypesFor( crange, types, sels );
+ const Datatype& dt = range.getDatatype();
+ for (unsigned i = 0, size = dt.getNumConstructors(); i < size; ++i)
+ {
+ for (unsigned j = 0, size_args = dt[i].getNumArgs(); j < size_args;
+ ++j)
+ {
+ collectSygusGrammarTypesFor(
+ TypeNode::fromType(static_cast<SelectorType>(dt[i][j].getType())
+ .getRangeType()),
+ types);
}
}
}
@@ -408,76 +414,87 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
<< range << std::endl;
// collect the variables
std::vector<Node> sygus_vars;
- if( !bvl.isNull() ){
- for( unsigned i=0; i<bvl.getNumChildren(); i++ ){
+ if (!bvl.isNull())
+ {
+ for (unsigned i = 0, size = bvl.getNumChildren(); i < size; ++i)
+ {
if (term_irrelevant.find(bvl[i]) == term_irrelevant.end())
{
sygus_vars.push_back(bvl[i]);
}
else
{
- Trace("sygus-grammar-def") << "...synth var " << bvl[i]
- << " has been marked irrelevant."
- << std::endl;
+ Trace("sygus-grammar-def")
+ << "...synth var " << bvl[i] << " has been marked irrelevant."
+ << std::endl;
}
}
}
- //if( !range.isBoolean() && !range.isInteger() && !range.isBitVector() && !range.isDatatype() ){
- // parseError("No default grammar for type.");
- //}
- std::vector< std::vector< Expr > > ops;
+ // operators for each constructor in type
+ std::vector<std::vector<Expr>> ops;
+ // names for the operators
+ std::vector<std::vector<std::string>> cnames;
+ // argument types of operators
+ std::vector<std::vector<std::vector<Type>>> cargs;
+ // set of callbacks for each constructor
+ std::vector<std::vector<std::shared_ptr<SygusPrintCallback>>> pcs;
+ // weights for each constructor
+ std::vector<std::vector<int>> weights;
+ // index of top datatype, i.e. the datatype for the range type
int startIndex = -1;
std::map< Type, Type > sygus_to_builtin;
- std::vector< TypeNode > types;
- std::map< TypeNode, std::vector< DatatypeConstructorArg > > sels;
- //types for each of the variables of parametric sort
- for( unsigned i=0; i<sygus_vars.size(); i++ ){
- collectSygusGrammarTypesFor( sygus_vars[i].getType(), types, sels );
+ std::vector<TypeNode> types;
+ // collect connected types for each of the variables
+ for (unsigned i = 0, size = sygus_vars.size(); i < size; ++i)
+ {
+ collectSygusGrammarTypesFor(sygus_vars[i].getType(), types);
}
- //types connected to range
- collectSygusGrammarTypesFor( range, types, sels );
+ // collect connected types to range
+ collectSygusGrammarTypesFor(range, types);
- //name of boolean sort
+ // create placeholder for boolean type (kept apart since not collected)
std::stringstream ssb;
ssb << fun << "_Bool";
std::string dbname = ssb.str();
Type unres_bt = mkUnresolvedType(ssb.str(), unres).toType();
+ // create placeholders for collected types
std::vector< Type > unres_types;
std::map< TypeNode, Type > type_to_unres;
- for( unsigned i=0; i<types.size(); i++ ){
+ for (unsigned i = 0, size = types.size(); i < size; ++i)
+ {
std::stringstream ss;
ss << fun << "_" << types[i];
std::string dname = ss.str();
datatypes.push_back(Datatype(dname));
ops.push_back(std::vector< Expr >());
+ cnames.push_back(std::vector<std::string>());
+ cargs.push_back(std::vector<std::vector<Type>>());
+ pcs.push_back(std::vector<std::shared_ptr<SygusPrintCallback>>());
+ weights.push_back(std::vector<int>());
//make unresolved type
Type unres_t = mkUnresolvedType(dname, unres).toType();
unres_types.push_back(unres_t);
type_to_unres[types[i]] = unres_t;
sygus_to_builtin[unres_t] = types[i].toType();
}
- for( unsigned i=0; i<types.size(); i++ ){
+ for (unsigned i = 0, size = types.size(); i < size; ++i)
+ {
Trace("sygus-grammar-def") << "Make grammar for " << types[i] << " " << unres_types[i] << std::endl;
- std::vector<std::string> cnames;
- std::vector<std::vector<CVC4::Type> > cargs;
- /* Print callbacks for each constructor */
- std::vector<std::shared_ptr<SygusPrintCallback>> pcs;
- /* Weights for each constructor */
- std::vector<int> weights;
Type unres_t = unres_types[i];
//add variables
- for( unsigned j=0; j<sygus_vars.size(); j++ ){
+ for (unsigned j = 0, size_j = sygus_vars.size(); j < size_j; ++j)
+ {
if( sygus_vars[j].getType()==types[i] ){
std::stringstream ss;
ss << sygus_vars[j];
Trace("sygus-grammar-def") << "...add for variable " << ss.str() << std::endl;
ops[i].push_back( sygus_vars[j].toExpr() );
- cnames.push_back( ss.str() );
- cargs.push_back( std::vector< CVC4::Type >() );
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ cnames[i].push_back(ss.str());
+ cargs[i].push_back(std::vector<Type>());
+ pcs[i].push_back(nullptr);
+ weights[i].push_back(-1);
}
}
//add constants
@@ -486,33 +503,35 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
std::map< TypeNode, std::vector< Node > >::iterator itec = extra_cons.find( types[i] );
if( itec!=extra_cons.end() ){
//consts.insert( consts.end(), itec->second.begin(), itec->second.end() );
- for( unsigned j=0; j<itec->second.size(); j++ ){
+ for (unsigned j = 0, size_j = itec->second.size(); j < size_j; ++j)
+ {
if( std::find( consts.begin(), consts.end(), itec->second[j] )==consts.end() ){
consts.push_back( itec->second[j] );
}
}
}
- for( unsigned j=0; j<consts.size(); j++ ){
+ for (unsigned j = 0, size_j = consts.size(); j < size_j; ++j)
+ {
std::stringstream ss;
ss << consts[j];
Trace("sygus-grammar-def") << "...add for constant " << ss.str() << std::endl;
ops[i].push_back( consts[j].toExpr() );
- cnames.push_back( ss.str() );
- cargs.push_back( std::vector< CVC4::Type >() );
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ cnames[i].push_back(ss.str());
+ cargs[i].push_back(std::vector<Type>());
+ pcs[i].push_back(nullptr);
+ weights[i].push_back(-1);
}
- //ITE
- CVC4::Kind k = kind::ITE;
+ // ITE
+ Kind k = ITE;
Trace("sygus-grammar-def") << "...add for " << k << std::endl;
ops[i].push_back(nm->operatorOf(k).toExpr());
- cnames.push_back( kind::kindToString(k) );
- cargs.push_back( std::vector< CVC4::Type >() );
- cargs.back().push_back(unres_bt);
- cargs.back().push_back(unres_t);
- cargs.back().push_back(unres_t);
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ cnames[i].push_back(kindToString(k));
+ cargs[i].push_back(std::vector<Type>());
+ cargs[i].back().push_back(unres_bt);
+ cargs[i].back().push_back(unres_t);
+ cargs[i].back().push_back(unres_t);
+ pcs[i].push_back(nullptr);
+ weights[i].push_back(-1);
if (types[i].isReal())
{
@@ -521,16 +540,17 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
Kind k = j == 0 ? PLUS : MINUS;
Trace("sygus-grammar-def") << "...add for " << k << std::endl;
ops[i].push_back(nm->operatorOf(k).toExpr());
- cnames.push_back(kind::kindToString(k));
- cargs.push_back(std::vector<CVC4::Type>());
- cargs.back().push_back(unres_t);
- cargs.back().push_back(unres_t);
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ cnames[i].push_back(kindToString(k));
+ cargs[i].push_back(std::vector<Type>());
+ cargs[i].back().push_back(unres_t);
+ cargs[i].back().push_back(unres_t);
+ pcs[i].push_back(nullptr);
+ weights[i].push_back(-1);
}
if (!types[i].isInteger())
{
- Trace("sygus-grammar-def") << "...Dedicate to Real\n";
+ Trace("sygus-grammar-def")
+ << " ...create auxiliary Positive Integers grammar\n";
/* Creating type for positive integers */
std::stringstream ss;
ss << fun << "_PosInt";
@@ -546,7 +566,8 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
/* Add operator 1 */
Trace("sygus-grammar-def") << "\t...add for 1 to Pos_Int\n";
ops_pos_int.push_back(nm->mkConst(Rational(1)).toExpr());
- ss << "_1";
+ ss.str("");
+ ss << "1";
cnames_pos_int.push_back(ss.str());
cargs_pos_int.push_back(std::vector<Type>());
/* Add operator PLUS */
@@ -558,23 +579,23 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
cargs_pos_int.back().push_back(unres_pos_int_t);
cargs_pos_int.back().push_back(unres_pos_int_t);
datatypes.back().setSygus(types[i].toType(), bvl.toExpr(), true, true);
- for (unsigned j = 0; j < ops_pos_int.size(); j++)
+ for (unsigned j = 0, size_j = ops_pos_int.size(); j < size_j; ++j)
{
datatypes.back().addSygusConstructor(
ops_pos_int[j], cnames_pos_int[j], cargs_pos_int[j]);
}
Trace("sygus-grammar-def")
- << "...built datatype " << datatypes.back() << " ";
+ << " ...built datatype " << datatypes.back() << " ";
/* Adding division at root */
k = DIVISION;
Trace("sygus-grammar-def") << "\t...add for " << k << std::endl;
ops[i].push_back(nm->operatorOf(k).toExpr());
- cnames.push_back(kindToString(k));
- cargs.push_back(std::vector<Type>());
- cargs.back().push_back(unres_t);
- cargs.back().push_back(unres_pos_int_t);
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ cnames[i].push_back(kindToString(k));
+ cargs[i].push_back(std::vector<Type>());
+ cargs[i].back().push_back(unres_t);
+ cargs[i].back().push_back(unres_pos_int_t);
+ pcs[i].push_back(nullptr);
+ weights[i].push_back(-1);
}
}
else if (types[i].isBitVector())
@@ -585,11 +606,11 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
{
Trace("sygus-grammar-def") << "...add for " << k << std::endl;
ops[i].push_back(nm->operatorOf(k).toExpr());
- cnames.push_back(kindToString(k));
- cargs.push_back(std::vector<Type>());
- cargs.back().push_back(unres_t);
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ cnames[i].push_back(kindToString(k));
+ cargs[i].push_back(std::vector<Type>());
+ cargs[i].back().push_back(unres_t);
+ pcs[i].push_back(nullptr);
+ weights[i].push_back(-1);
}
// binary apps
std::vector<Kind> bin_kinds = {BITVECTOR_AND,
@@ -609,56 +630,65 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
{
Trace("sygus-grammar-def") << "...add for " << k << std::endl;
ops[i].push_back(nm->operatorOf(k).toExpr());
- cnames.push_back(kindToString(k));
- cargs.push_back(std::vector<Type>());
- cargs.back().push_back(unres_t);
- cargs.back().push_back(unres_t);
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ cnames[i].push_back(kindToString(k));
+ cargs[i].push_back(std::vector<Type>());
+ cargs[i].back().push_back(unres_t);
+ cargs[i].back().push_back(unres_t);
+ pcs[i].push_back(nullptr);
+ weights[i].push_back(-1);
}
}
else if (types[i].isDatatype())
{
Trace("sygus-grammar-def") << "...add for constructors" << std::endl;
- const Datatype& dt = ((DatatypeType)types[i].toType()).getDatatype();
- for( unsigned k=0; k<dt.getNumConstructors(); k++ ){
+ const Datatype& dt = types[i].getDatatype();
+ for (unsigned k = 0, size_k = dt.getNumConstructors(); k < size_k; ++k)
+ {
Trace("sygus-grammar-def") << "...for " << dt[k].getName() << std::endl;
ops[i].push_back( dt[k].getConstructor() );
- cnames.push_back( dt[k].getName() );
- cargs.push_back( std::vector< CVC4::Type >() );
- for( unsigned j=0; j<dt[k].getNumArgs(); j++ ){
- TypeNode crange = TypeNode::fromType( ((SelectorType)dt[k][j].getType()).getRangeType() );
- //Assert( type_to_unres.find(crange)!=type_to_unres.end() );
- cargs.back().push_back( type_to_unres[crange] );
+ cnames[i].push_back(dt[k].getName());
+ cargs[i].push_back(std::vector<Type>());
+ Trace("sygus-grammar-def") << "...add for selectors" << std::endl;
+ for (unsigned j = 0, size_j = dt[k].getNumArgs(); j < size_j; ++j)
+ {
+ Trace("sygus-grammar-def")
+ << "...for " << dt[k][j].getName() << std::endl;
+ TypeNode crange = TypeNode::fromType(
+ static_cast<SelectorType>(dt[k][j].getType()).getRangeType());
+ Assert(type_to_unres.find(crange) != type_to_unres.end());
+ cargs[i].back().push_back(type_to_unres[crange]);
+ // add to the selector type the selector operator
+
+ Assert(std::find(types.begin(), types.end(), crange) != types.end());
+ unsigned i_selType = std::distance(
+ types.begin(), std::find(types.begin(), types.end(), crange));
+ TypeNode arg_type = TypeNode::fromType(
+ static_cast<SelectorType>(dt[k][j].getType()).getDomain());
+ ops[i_selType].push_back(dt[k][j].getSelector());
+ cnames[i_selType].push_back(dt[k][j].getName());
+ cargs[i_selType].push_back(std::vector<Type>());
+ Assert(type_to_unres.find(arg_type) != type_to_unres.end());
+ cargs[i_selType].back().push_back(type_to_unres[arg_type]);
+ pcs[i_selType].push_back(nullptr);
+ weights[i_selType].push_back(-1);
}
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ pcs[i].push_back(nullptr);
+ weights[i].push_back(-1);
}
}else{
std::stringstream sserr;
sserr << "No implementation for default Sygus grammar of type " << types[i] << std::endl;
throw LogicException(sserr.str());
}
- //add for all selectors to this type
- if( !sels[types[i]].empty() ){
- Trace("sygus-grammar-def") << "...add for selectors" << std::endl;
- for( unsigned j=0; j<sels[types[i]].size(); j++ ){
- Trace("sygus-grammar-def") << "...for " << sels[types[i]][j].getName() << std::endl;
- TypeNode arg_type = TypeNode::fromType( ((SelectorType)sels[types[i]][j].getType()).getDomain() );
- ops[i].push_back( sels[types[i]][j].getSelector() );
- cnames.push_back( sels[types[i]][j].getName() );
- cargs.push_back( std::vector< CVC4::Type >() );
- //Assert( type_to_unres.find(arg_type)!=type_to_unres.end() );
- cargs.back().push_back( type_to_unres[arg_type] );
- pcs.push_back(nullptr);
- weights.push_back(-1);
- }
- }
+ }
+ // make datatypes
+ for (unsigned i = 0, size = types.size(); i < size; ++i)
+ {
Trace("sygus-grammar-def") << "...make datatype " << datatypes[i] << std::endl;
datatypes[i].setSygus( types[i].toType(), bvl.toExpr(), true, true );
std::map<TypeNode, std::vector<Node>>::iterator itexc =
exc_cons.find(types[i]);
- for (unsigned j = 0, size = ops[i].size(); j < size; j++)
+ for (unsigned j = 0, size = ops[i].size(); j < size; ++j)
{
// add the constructor if it is not excluded
Node opn = Node::fromExpr(ops[i][j]);
@@ -667,12 +697,10 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
== itexc->second.end())
{
datatypes[i].addSygusConstructor(
- ops[i][j], cnames[j], cargs[j], pcs[j], weights[j]);
+ ops[i][j], cnames[i][j], cargs[i][j], pcs[i][j], weights[i][j]);
}
}
- Trace("sygus-grammar-def")
- << "...built datatype " << datatypes[i] << " ";
- //sorts.push_back( types[i] );
+ Trace("sygus-grammar-def") << "...built datatype " << datatypes[i] << " ";
//set start index if applicable
if( types[i]==range ){
startIndex = i;
@@ -683,94 +711,96 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
TypeNode btype = nm->booleanType();
datatypes.push_back(Datatype(dbname));
ops.push_back(std::vector<Expr>());
- std::vector<std::string> cnames;
- std::vector<std::vector< Type > > cargs;
- /* Print callbacks for each constructor */
- std::vector<std::shared_ptr<SygusPrintCallback>> pcs;
- /* Weights for each constructor */
- std::vector<int> weights;
+ cnames.push_back(std::vector<std::string>());
+ cargs.push_back(std::vector<std::vector<Type>>());
+ pcs.push_back(std::vector<std::shared_ptr<SygusPrintCallback>>());
+ weights.push_back(std::vector<int>());
Trace("sygus-grammar-def") << "Make grammar for " << btype << " " << datatypes.back() << std::endl;
//add variables
- for( unsigned i=0; i<sygus_vars.size(); i++ ){
+ for (unsigned i = 0, size = sygus_vars.size(); i < size; ++i)
+ {
if( sygus_vars[i].getType().isBoolean() ){
std::stringstream ss;
ss << sygus_vars[i];
Trace("sygus-grammar-def") << "...add for variable " << ss.str() << std::endl;
ops.back().push_back( sygus_vars[i].toExpr() );
- cnames.push_back( ss.str() );
- cargs.push_back( std::vector< CVC4::Type >() );
- pcs.push_back(nullptr);
- weights.push_back(1);
+ cnames.back().push_back(ss.str());
+ cargs.back().push_back(std::vector<Type>());
+ pcs.back().push_back(nullptr);
+ // make boolean variables weight as non-nullary constructors
+ weights.back().push_back(1);
}
}
- //add constants
+ // add constants
std::vector<Node> consts;
mkSygusConstantsForType(btype, consts);
- for (unsigned j = 0; j < consts.size(); j++)
+ for (unsigned i = 0, size = consts.size(); i < size; ++i)
{
std::stringstream ss;
- ss << consts[j];
+ ss << consts[i];
Trace("sygus-grammar-def") << "...add for constant " << ss.str()
<< std::endl;
- ops.back().push_back(consts[j].toExpr());
- cnames.push_back(ss.str());
- cargs.push_back(std::vector<CVC4::Type>());
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ ops.back().push_back(consts[i].toExpr());
+ cnames.back().push_back(ss.str());
+ cargs.back().push_back(std::vector<Type>());
+ pcs.back().push_back(nullptr);
+ weights.back().push_back(-1);
}
- //add predicates for types
- for( unsigned i=0; i<types.size(); i++ ){
+ // add predicates for types
+ for (unsigned i = 0, size = types.size(); i < size; ++i)
+ {
Trace("sygus-grammar-def") << "...add predicates for " << types[i] << std::endl;
//add equality per type
- CVC4::Kind k = kind::EQUAL;
+ Kind k = EQUAL;
Trace("sygus-grammar-def") << "...add for " << k << std::endl;
ops.back().push_back(nm->operatorOf(k).toExpr());
std::stringstream ss;
- ss << kind::kindToString(k) << "_" << types[i];
- cnames.push_back(ss.str());
- cargs.push_back( std::vector< CVC4::Type >() );
- cargs.back().push_back(unres_types[i]);
- cargs.back().push_back(unres_types[i]);
- pcs.push_back(nullptr);
- weights.push_back(-1);
- //type specific predicates
+ ss << kindToString(k) << "_" << types[i];
+ cnames.back().push_back(ss.str());
+ cargs.back().push_back(std::vector<Type>());
+ cargs.back().back().push_back(unres_types[i]);
+ cargs.back().back().push_back(unres_types[i]);
+ pcs.back().push_back(nullptr);
+ weights.back().push_back(-1);
+ // type specific predicates
if (types[i].isReal())
{
- CVC4::Kind k = kind::LEQ;
+ Kind k = LEQ;
Trace("sygus-grammar-def") << "...add for " << k << std::endl;
ops.back().push_back(nm->operatorOf(k).toExpr());
- cnames.push_back(kind::kindToString(k));
- cargs.push_back( std::vector< CVC4::Type >() );
- cargs.back().push_back(unres_types[i]);
- cargs.back().push_back(unres_types[i]);
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ cnames.back().push_back(kindToString(k));
+ cargs.back().push_back(std::vector<Type>());
+ cargs.back().back().push_back(unres_types[i]);
+ cargs.back().back().push_back(unres_types[i]);
+ pcs.back().push_back(nullptr);
+ weights.back().push_back(-1);
}
else if (types[i].isBitVector())
{
Kind k = BITVECTOR_ULT;
Trace("sygus-grammar-def") << "...add for " << k << std::endl;
ops.back().push_back(nm->operatorOf(k).toExpr());
- cnames.push_back(kindToString(k));
- cargs.push_back(std::vector<Type>());
- cargs.back().push_back(unres_types[i]);
- cargs.back().push_back(unres_types[i]);
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ cnames.back().push_back(kindToString(k));
+ cargs.back().push_back(std::vector<Type>());
+ cargs.back().back().push_back(unres_types[i]);
+ cargs.back().back().push_back(unres_types[i]);
+ pcs.back().push_back(nullptr);
+ weights.back().push_back(-1);
}
else if (types[i].isDatatype())
{
//add for testers
Trace("sygus-grammar-def") << "...add for testers" << std::endl;
- const Datatype& dt = ((DatatypeType)types[i].toType()).getDatatype();
- for( unsigned k=0; k<dt.getNumConstructors(); k++ ){
+ const Datatype& dt = types[i].getDatatype();
+ for (unsigned k = 0, size_k = dt.getNumConstructors(); k < size_k; ++k)
+ {
Trace("sygus-grammar-def") << "...for " << dt[k].getTesterName() << std::endl;
ops.back().push_back(dt[k].getTester());
- cnames.push_back(dt[k].getTesterName());
- cargs.push_back( std::vector< CVC4::Type >() );
- cargs.back().push_back(unres_types[i]);
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ cnames.back().push_back(dt[k].getTesterName());
+ cargs.back().push_back(std::vector<Type>());
+ cargs.back().back().push_back(unres_types[i]);
+ pcs.back().push_back(nullptr);
+ weights.back().push_back(-1);
}
}
}
@@ -790,19 +820,19 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
}
Trace("sygus-grammar-def") << "...add for " << k << std::endl;
ops.back().push_back(nm->operatorOf(k).toExpr());
- cnames.push_back(kindToString(k));
- cargs.push_back(std::vector<CVC4::Type>());
- cargs.back().push_back(unres_bt);
+ cnames.back().push_back(kindToString(k));
+ cargs.back().push_back(std::vector<Type>());
+ cargs.back().back().push_back(unres_bt);
if (k != NOT)
{
- cargs.back().push_back(unres_bt);
+ cargs.back().back().push_back(unres_bt);
if (k == ITE)
{
- cargs.back().push_back(unres_bt);
+ cargs.back().back().push_back(unres_bt);
}
}
- pcs.push_back(nullptr);
- weights.push_back(-1);
+ pcs.back().push_back(nullptr);
+ weights.back().push_back(-1);
}
}
if( range==btype ){
@@ -810,15 +840,19 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
}
Trace("sygus-grammar-def") << "...make datatype " << datatypes.back() << std::endl;
datatypes.back().setSygus( btype.toType(), bvl.toExpr(), true, true );
- for( unsigned j=0; j<ops.back().size(); j++ ){
- datatypes.back().addSygusConstructor(
- ops.back()[j], cnames[j], cargs[j], pcs[j], weights[j]);
+ for (unsigned i = 0, size = ops.back().size(); i < size; ++i)
+ {
+ datatypes.back().addSygusConstructor(ops.back()[i],
+ cnames.back()[i],
+ cargs.back()[i],
+ pcs.back()[i],
+ weights.back()[i]);
}
- //sorts.push_back( btype );
+ Trace("sygus-grammar-def") << "...built datatype " << datatypes.back() << " ";
Trace("sygus-grammar-def") << "...finished make default grammar for " << fun << " " << range << std::endl;
-
+ // make first datatype be the top level datatype
if( startIndex>0 ){
- CVC4::Datatype tmp_dt = datatypes[0];
+ Datatype tmp_dt = datatypes[0];
datatypes[0] = datatypes[startIndex];
datatypes[startIndex] = tmp_dt;
}
diff --git a/src/theory/quantifiers/sygus/sygus_grammar_cons.h b/src/theory/quantifiers/sygus/sygus_grammar_cons.h
index 0c5b67656..3afc4c689 100644
--- a/src/theory/quantifiers/sygus/sygus_grammar_cons.h
+++ b/src/theory/quantifiers/sygus/sygus_grammar_cons.h
@@ -131,7 +131,8 @@ public:
// helper for mkSygusDefaultGrammar (makes unresolved type for mutually recursive datatype construction)
static TypeNode mkUnresolvedType(const std::string& name, std::set<Type>& unres);
// collect the list of types that depend on type range
- static void collectSygusGrammarTypesFor( TypeNode range, std::vector< TypeNode >& types, std::map< TypeNode, std::vector< DatatypeConstructorArg > >& sels );
+ static void collectSygusGrammarTypesFor(TypeNode range,
+ std::vector<TypeNode>& types);
/** helper function for function mkSygusDefaultType
* Collects a set of mutually recursive datatypes "datatypes" corresponding to
* encoding type "range" to SyGuS.
diff --git a/src/theory/quantifiers/sygus/sygus_pbe.cpp b/src/theory/quantifiers/sygus/sygus_pbe.cpp
index b49c29c53..ee7247121 100644
--- a/src/theory/quantifiers/sygus/sygus_pbe.cpp
+++ b/src/theory/quantifiers/sygus/sygus_pbe.cpp
@@ -179,7 +179,6 @@ bool SygusPbe::initialize(Node n,
return false;
}
}
- bool isActiveGen = options::sygusActiveGenMode() != SYGUS_ACTIVE_GEN_NONE;
for (const Node& c : candidates)
{
Assert(d_examples.find(c) != d_examples.end());
@@ -203,7 +202,7 @@ bool SygusPbe::initialize(Node n,
for (const Node& e : d_candidate_to_enum[c])
{
TypeNode etn = e.getType();
- d_tds->registerEnumerator(e, c, d_parent, true, false, isActiveGen);
+ d_tds->registerEnumerator(e, c, d_parent, ROLE_ENUM_POOL, false);
d_enum_to_candidate[e] = c;
TNode te = e;
// initialize static symmetry breaking lemmas for it
@@ -229,13 +228,24 @@ bool SygusPbe::initialize(Node n,
{
lem = lem.substitute(tsp, te);
}
- disj.push_back(lem);
+ if (std::find(disj.begin(), disj.end(), lem) == disj.end())
+ {
+ disj.push_back(lem);
+ }
}
}
+ // add its active guard
+ Node ag = d_tds->getActiveGuardForEnumerator(e);
+ Assert(!ag.isNull());
+ disj.push_back(ag.negate());
Node lem = disj.size() == 1 ? disj[0] : nm->mkNode(OR, disj);
Trace("sygus-pbe") << " static redundant op lemma : " << lem
<< std::endl;
- lemmas.push_back(lem);
+ // Register as a symmetry breaking lemma with the term database.
+ // This will either be processed via a lemma on the output channel
+ // of the sygus extension of the datatypes solver, or internally
+ // encoded as a constraint to an active enumerator.
+ d_tds->registerSymBreakLemma(e, lem, etn, 0, false);
}
}
Trace("sygus-pbe") << "Initialize " << d_examples[c].size()
diff --git a/src/theory/quantifiers/sygus/synth_conjecture.cpp b/src/theory/quantifiers/sygus/synth_conjecture.cpp
index 21079aedc..2bfde2d80 100644
--- a/src/theory/quantifiers/sygus/synth_conjecture.cpp
+++ b/src/theory/quantifiers/sygus/synth_conjecture.cpp
@@ -346,14 +346,17 @@ bool SynthConjecture::doCheck(std::vector<Node>& lems)
{
// get the model value of the relevant terms from the master module
std::vector<Node> enum_values;
- bool fullModel = getEnumeratedValues(terms, enum_values);
+ bool activeIncomplete = false;
+ bool fullModel = getEnumeratedValues(terms, enum_values, activeIncomplete);
// if the master requires a full model and the model is partial, we fail
if (!d_master->allowPartialModel() && !fullModel)
{
// we retain the values in d_ev_active_gen_waiting
Trace("cegqi-engine") << "...partial model, fail." << std::endl;
- return true;
+ // if we are partial due to an active enumerator, we may still succeed
+ // on the next call
+ return !activeIncomplete;
}
// the waiting values are passed to the module below, clear
d_ev_active_gen_waiting.clear();
@@ -396,7 +399,7 @@ bool SynthConjecture::doCheck(std::vector<Node>& lems)
if (emptyModel)
{
Trace("cegqi-engine") << "...empty model, fail." << std::endl;
- return true;
+ return !activeIncomplete;
}
Assert(candidate_values.empty());
constructed_cand = d_master->constructCandidates(
@@ -650,7 +653,8 @@ void SynthConjecture::preregisterConjecture(Node q)
}
bool SynthConjecture::getEnumeratedValues(std::vector<Node>& n,
- std::vector<Node>& v)
+ std::vector<Node>& v,
+ bool& activeIncomplete)
{
std::vector<Node> ncheck = n;
n.clear();
@@ -670,7 +674,7 @@ bool SynthConjecture::getEnumeratedValues(std::vector<Node>& n,
continue;
}
}
- Node nv = getEnumeratedValue(e);
+ Node nv = getEnumeratedValue(e, activeIncomplete);
n.push_back(e);
v.push_back(nv);
ret = ret && !nv.isNull();
@@ -692,42 +696,50 @@ class EnumValGeneratorBasic : public EnumValGenerator
/** initialize (do nothing) */
void initialize(Node e) override {}
/** initialize (do nothing) */
- void addValue(Node v) override {}
+ void addValue(Node v) override { d_currTerm = *d_te; }
/**
* Get next returns the next (T-rewriter-unique) value based on the type
* enumerator.
*/
- Node getNext() override
+ bool increment() override
{
+ ++d_te;
if (d_te.isFinished())
{
- return Node::null();
+ d_currTerm = Node::null();
+ return false;
}
- Node next = *d_te;
- ++d_te;
- Node nextb = d_tds->sygusToBuiltin(next);
+ d_currTerm = *d_te;
if (options::sygusSymBreakDynamic())
{
+ Node nextb = d_tds->sygusToBuiltin(d_currTerm);
nextb = d_tds->getExtRewriter()->extendedRewrite(nextb);
+ if (d_cache.find(nextb) == d_cache.end())
+ {
+ d_cache.insert(nextb);
+ // only return the current term if not unique
+ }
+ else
+ {
+ d_currTerm = Node::null();
+ }
}
- if (d_cache.find(nextb) == d_cache.end())
- {
- d_cache.insert(nextb);
- return next;
- }
- return getNext();
+ return true;
}
-
+ /** get the current term */
+ Node getCurrent() override { return d_currTerm; }
private:
/** pointer to term database sygus */
TermDbSygus* d_tds;
/** the type enumerator */
TypeEnumerator d_te;
+ /** the current term */
+ Node d_currTerm;
/** cache of (enumerated) builtin values we have enumerated so far */
std::unordered_set<Node, NodeHashFunction> d_cache;
};
-Node SynthConjecture::getEnumeratedValue(Node e)
+Node SynthConjecture::getEnumeratedValue(Node e, bool& activeIncomplete)
{
bool isEnum = d_tds->isEnumerator(e);
@@ -761,15 +773,18 @@ Node SynthConjecture::getEnumeratedValue(Node e)
else
{
// Actively-generated enumerators are currently either variable agnostic
- // or basic.
+ // or basic. The auto mode always prefers the optimized enumerator over
+ // the basic one.
Assert(d_tds->isBasicEnumerator(e));
- if (options::sygusActiveGenMode() == SYGUS_ACTIVE_GEN_ENUM)
+ if (options::sygusActiveGenMode() == SYGUS_ACTIVE_GEN_ENUM_BASIC)
{
- d_evg[e].reset(new SygusEnumerator(d_tds, this));
+ d_evg[e].reset(new EnumValGeneratorBasic(d_tds, e.getType()));
}
else
{
- d_evg[e].reset(new EnumValGeneratorBasic(d_tds, e.getType()));
+ Assert(options::sygusActiveGenMode() == SYGUS_ACTIVE_GEN_ENUM
+ || options::sygusActiveGenMode() == SYGUS_ACTIVE_GEN_AUTO);
+ d_evg[e].reset(new SygusEnumerator(d_tds, this));
}
}
Trace("sygus-active-gen")
@@ -790,6 +805,7 @@ Node SynthConjecture::getEnumeratedValue(Node e)
// Check if there is an (abstract) value absE we were actively generating
// values based on.
Node absE = d_ev_curr_active_gen[e];
+ bool firstTime = false;
if (absE.isNull())
{
// None currently exist. The next abstract value is the model value for e.
@@ -804,9 +820,22 @@ Node SynthConjecture::getEnumeratedValue(Node e)
}
d_ev_curr_active_gen[e] = absE;
iteg->second->addValue(absE);
+ firstTime = true;
}
- Node v = iteg->second->getNext();
- if (v.isNull())
+ bool inc = true;
+ if (!firstTime)
+ {
+ inc = iteg->second->increment();
+ }
+ Node v;
+ if (inc)
+ {
+ v = iteg->second->getCurrent();
+ }
+ Trace("sygus-active-gen-debug") << "...generated " << v
+ << ", with increment success : " << inc
+ << std::endl;
+ if (!inc)
{
// No more concrete values generated from absE.
NodeManager* nm = NodeManager::currentNM();
@@ -852,7 +881,14 @@ Node SynthConjecture::getEnumeratedValue(Node e)
else
{
// We are waiting to send e -> v to the module that requested it.
- d_ev_active_gen_waiting[e] = v;
+ if (v.isNull())
+ {
+ activeIncomplete = true;
+ }
+ else
+ {
+ d_ev_active_gen_waiting[e] = v;
+ }
if (Trace.isOn("sygus-active-gen"))
{
Trace("sygus-active-gen") << "Active-gen : " << e << " : ";
diff --git a/src/theory/quantifiers/sygus/synth_conjecture.h b/src/theory/quantifiers/sygus/synth_conjecture.h
index ef1b4459f..3a43eb83d 100644
--- a/src/theory/quantifiers/sygus/synth_conjecture.h
+++ b/src/theory/quantifiers/sygus/synth_conjecture.h
@@ -49,8 +49,14 @@ class EnumValGenerator
virtual void initialize(Node e) = 0;
/** Inform this generator that abstract value v was enumerated. */
virtual void addValue(Node v) = 0;
- /** Get the next concrete value generated by this class. */
- virtual Node getNext() = 0;
+ /**
+ * Increment this value generator. If this returns false, then we are out of
+ * values. If this returns true, getCurrent(), if non-null, returns the
+ * current term.
+ */
+ virtual bool increment() = 0;
+ /** Get the current concrete value generated by this class. */
+ virtual Node getCurrent() = 0;
};
/** a synthesis conjecture
@@ -193,15 +199,25 @@ class SynthConjecture
* Get model values for terms n, store in vector v. This method returns true
* if and only if all values added to v are non-null.
*
+ * The argument activeIncomplete indicates whether n contains an active
+ * enumerator that is currently not finished enumerating values, but returned
+ * null on a call to getEnumeratedValue. This value is used for determining
+ * whether we should call getEnumeratedValues again within a call to
+ * SynthConjecture::check.
+ *
* It removes terms from n that correspond to "inactive" enumerators, that
* is, enumerators whose values have been exhausted.
*/
- bool getEnumeratedValues(std::vector<Node>& n, std::vector<Node>& v);
+ bool getEnumeratedValues(std::vector<Node>& n,
+ std::vector<Node>& v,
+ bool& activeIncomplete);
/**
* Get model value for term n. If n has a value that was excluded by
- * datatypes sygus symmetry breaking, this method returns null.
+ * datatypes sygus symmetry breaking, this method returns null. It sets
+ * activeIncomplete to true if there is an actively-generated enumerator whose
+ * current value is null but it has not finished generating values.
*/
- Node getEnumeratedValue(Node n);
+ Node getEnumeratedValue(Node n, bool& activeIncomplete);
/** enumerator generators for each actively-generated enumerator */
std::map<Node, std::unique_ptr<EnumValGenerator> > d_evg;
/**
diff --git a/src/theory/quantifiers/sygus/term_database_sygus.cpp b/src/theory/quantifiers/sygus/term_database_sygus.cpp
index 435e1a00f..9198f7e56 100644
--- a/src/theory/quantifiers/sygus/term_database_sygus.cpp
+++ b/src/theory/quantifiers/sygus/term_database_sygus.cpp
@@ -58,6 +58,19 @@ void TypeNodeIdTrie::assignIds(std::map<Node, unsigned>& assign,
}
}
+std::ostream& operator<<(std::ostream& os, EnumeratorRole r)
+{
+ switch (r)
+ {
+ case ROLE_ENUM_POOL: os << "POOL"; break;
+ case ROLE_ENUM_SINGLE_SOLUTION: os << "SINGLE_SOLUTION"; break;
+ case ROLE_ENUM_MULTI_SOLUTION: os << "MULTI_SOLUTION"; break;
+ case ROLE_ENUM_CONSTRAINED: os << "CONSTRAINED"; break;
+ default: os << "enum_" << static_cast<unsigned>(r); break;
+ }
+ return os;
+}
+
TermDbSygus::TermDbSygus(context::Context* c, QuantifiersEngine* qe)
: d_quantEngine(qe),
d_syexp(new SygusExplain(this)),
@@ -454,9 +467,8 @@ void TermDbSygus::registerSygusType( TypeNode tn ) {
void TermDbSygus::registerEnumerator(Node e,
Node f,
SynthConjecture* conj,
- bool mkActiveGuard,
- bool useSymbolicCons,
- bool isActiveGen)
+ EnumeratorRole erole,
+ bool useSymbolicCons)
{
if (d_enum_to_conjecture.find(e) != d_enum_to_conjecture.end())
{
@@ -470,13 +482,6 @@ void TermDbSygus::registerEnumerator(Node e,
d_enum_to_conjecture[e] = conj;
d_enum_to_synth_fun[e] = f;
NodeManager* nm = NodeManager::currentNM();
- if( mkActiveGuard ){
- // make the guard
- Node ag = nm->mkSkolem("eG", nm->booleanType());
- // must ensure it is a literal immediately here
- ag = d_quantEngine->getValuation().ensureLiteral(ag);
- d_enum_to_active_guard[e] = ag;
- }
Trace("sygus-db") << " registering symmetry breaking clauses..."
<< std::endl;
@@ -554,6 +559,66 @@ void TermDbSygus::registerEnumerator(Node e,
}
Trace("sygus-db") << " ...finished" << std::endl;
+ // determine if we are actively-generated
+ bool isActiveGen = false;
+ if (options::sygusActiveGenMode() != SYGUS_ACTIVE_GEN_NONE)
+ {
+ if (erole == ROLE_ENUM_MULTI_SOLUTION || erole == ROLE_ENUM_CONSTRAINED)
+ {
+ // If the enumerator is a solution for a conjecture with multiple
+ // functions, we do not use active generation. If we did, we would have to
+ // generate a "product" of two actively-generated enumerators. That is,
+ // given a conjecture with two functions-to-synthesize with enumerators
+ // e_f and e_g, and if these enumerators generated:
+ // e_f -> t1, ..., tn
+ // e_g -> s1, ..., sm
+ // The sygus module in charge of this conjecture would expect
+ // constructCandidates calls of the form
+ // (e_f,e_g) -> (ti, sj)
+ // for each i,j. We instead use passive enumeration in this case.
+ //
+ // If the enumerator is constrained, it cannot be actively generated.
+ }
+ else if (erole == ROLE_ENUM_POOL)
+ {
+ // If the enumerator is used for generating a pool of values, we always
+ // use active generation.
+ isActiveGen = true;
+ }
+ else if (erole == ROLE_ENUM_SINGLE_SOLUTION)
+ {
+ // If the enumerator is the single function-to-synthesize, if auto is
+ // enabled, we infer whether it is better to enable active generation.
+ if (options::sygusActiveGenMode() == SYGUS_ACTIVE_GEN_AUTO)
+ {
+ // We use active generation if the grammar of the enumerator does not
+ // have ITE and is not Boolean. Experimentally, it is better to
+ // use passive generation for these cases since it enables useful
+ // search space pruning techniques, e.g. evaluation unfolding,
+ // conjecture-specific symmetry breaking. Also, if sygus-stream is
+ // enabled, we always use active generation, since the use cases of
+ // sygus stream are to find many solutions to an easy problem, where
+ // the bottleneck often becomes the large number of "exclude the current
+ // solution" clauses.
+ const Datatype& dt = et.getDatatype();
+ if (options::sygusStream()
+ || (!hasKind(et, ITE) && !dt.getSygusType().isBoolean()))
+ {
+ isActiveGen = true;
+ }
+ }
+ else
+ {
+ isActiveGen = true;
+ }
+ }
+ else
+ {
+ Unreachable("Unknown enumerator mode in registerEnumerator");
+ }
+ }
+ Trace("sygus-db") << "isActiveGen for " << e << ", role = " << erole
+ << " returned " << isActiveGen << std::endl;
// Currently, actively-generated enumerators are either basic or variable
// agnostic.
bool isVarAgnostic =
@@ -607,6 +672,22 @@ void TermDbSygus::registerEnumerator(Node e,
}
d_enum_active_gen[e] = isActiveGen;
d_enum_basic[e] = isActiveGen && !isVarAgnostic;
+
+ // We make an active guard if we will be explicitly blocking solutions for
+ // the enumerator. This is the case if the role of the enumerator is to
+ // populate a pool of terms, or (some cases) of when it is actively generated.
+ if (isActiveGen || erole == ROLE_ENUM_POOL)
+ {
+ // make the guard
+ Node ag = nm->mkSkolem("eG", nm->booleanType());
+ // must ensure it is a literal immediately here
+ ag = d_quantEngine->getValuation().ensureLiteral(ag);
+ // must ensure that it is asserted as a literal before we begin solving
+ Node lem = nm->mkNode(OR, ag, ag.negate());
+ d_quantEngine->getOutputChannel().requirePhase(ag, true);
+ d_quantEngine->getOutputChannel().lemma(lem);
+ d_enum_to_active_guard[e] = ag;
+ }
}
bool TermDbSygus::isEnumerator(Node e) const
@@ -694,14 +775,13 @@ void TermDbSygus::getEnumerators(std::vector<Node>& mts)
}
}
-void TermDbSygus::registerSymBreakLemma(Node e,
- Node lem,
- TypeNode tn,
- unsigned sz)
+void TermDbSygus::registerSymBreakLemma(
+ Node e, Node lem, TypeNode tn, unsigned sz, bool isTempl)
{
d_enum_to_sb_lemmas[e].push_back(lem);
d_sb_lemma_to_type[lem] = tn;
d_sb_lemma_to_size[lem] = sz;
+ d_sb_lemma_to_isTempl[lem] = isTempl;
}
bool TermDbSygus::hasSymBreakLemmas(std::vector<Node>& enums) const
@@ -740,6 +820,13 @@ unsigned TermDbSygus::getSizeForSymBreakLemma(Node lem) const
return it->second;
}
+bool TermDbSygus::isSymBreakLemmaTemplate(Node lem) const
+{
+ std::map<Node, bool>::const_iterator it = d_sb_lemma_to_isTempl.find(lem);
+ Assert(it != d_sb_lemma_to_isTempl.end());
+ return it->second;
+}
+
void TermDbSygus::clearSymBreakLemmas(Node e) { d_enum_to_sb_lemmas.erase(e); }
bool TermDbSygus::isRegistered(TypeNode tn) const
@@ -756,9 +843,16 @@ void TermDbSygus::toStreamSygus(const char* c, Node n)
{
if (Trace.isOn(c))
{
- std::stringstream ss;
- Printer::getPrinter(options::outputLanguage())->toStreamSygus(ss, n);
- Trace(c) << ss.str();
+ if (n.isNull())
+ {
+ Trace(c) << n;
+ }
+ else
+ {
+ std::stringstream ss;
+ Printer::getPrinter(options::outputLanguage())->toStreamSygus(ss, n);
+ Trace(c) << ss.str();
+ }
}
}
diff --git a/src/theory/quantifiers/sygus/term_database_sygus.h b/src/theory/quantifiers/sygus/term_database_sygus.h
index 713e322a4..7a522ded6 100644
--- a/src/theory/quantifiers/sygus/term_database_sygus.h
+++ b/src/theory/quantifiers/sygus/term_database_sygus.h
@@ -48,6 +48,23 @@ class TypeNodeIdTrie
void assignIds(std::map<Node, unsigned>& assign, unsigned& idCount);
};
+/** role for registering an enumerator */
+enum EnumeratorRole
+{
+ /** The enumerator populates a pool of terms (e.g. for PBE). */
+ ROLE_ENUM_POOL,
+ /** The enumerator is the single solution of the problem. */
+ ROLE_ENUM_SINGLE_SOLUTION,
+ /**
+ * The enumerator is part of the solution of the problem (e.g. multiple
+ * functions to synthesize).
+ */
+ ROLE_ENUM_MULTI_SOLUTION,
+ /** The enumerator must satisfy some set of constraints */
+ ROLE_ENUM_CONSTRAINED,
+};
+std::ostream& operator<<(std::ostream& os, EnumeratorRole r);
+
// TODO :issue #1235 split and document this class
class TermDbSygus {
public:
@@ -80,29 +97,32 @@ class TermDbSygus {
//------------------------------enumerators
/**
* Register a variable e that we will do enumerative search on.
+ *
* conj : the conjecture that the enumeration of e is for.
- * f : the synth-fun that the enumeration of e is for.
- * mkActiveGuard : whether we want to make an active guard for e
- * (see d_enum_to_active_guard),
- * useSymbolicCons : whether we want model values for e to include symbolic
- * constructors like the "any constant" variable.
- * isActiveGen : if this flag is true, the enumerator will be
- * actively-generated based on the mode specified by --sygus-active-gen.
+ *
+ * f : the synth-fun that the enumeration of e is for.Notice that enumerator
+ * e may not be one-to-one with f in synthesis-through-unification approaches
+ * (e.g. decision tree construction for PBE synthesis).
+ *
+ * erole : the role of this enumerator (see definition of EnumeratorRole).
+ * Depending on this and the policy for actively-generated enumerators
+ * (--sygus-active-gen), the enumerator may be "actively-generated".
* For example, if --sygus-active-gen=var-agnostic, then the enumerator will
* only generate values whose variables are in canonical order (only x1-x2
* and not x2-x1 will be generated, assuming x1 and x2 are in the same
* "subclass", see getSubclassForVar).
*
- * Notice that enumerator e may not be one-to-one with f in
- * synthesis-through-unification approaches (e.g. decision tree construction
- * for PBE synthesis).
+ * useSymbolicCons : whether we want model values for e to include symbolic
+ * constructors like the "any constant" variable.
+ *
+ * An "active guard" may be allocated by this method for e based on erole
+ * and the policies for active generation.
*/
void registerEnumerator(Node e,
Node f,
SynthConjecture* conj,
- bool mkActiveGuard = false,
- bool useSymbolicCons = false,
- bool isActiveGen = false);
+ EnumeratorRole erole,
+ bool useSymbolicCons = false);
/** is e an enumerator registered with this class? */
bool isEnumerator(Node e) const;
/** return the conjecture e is associated with */
@@ -150,12 +170,13 @@ class TermDbSygus {
*
* tn : the (sygus datatype) type that lem applies to, i.e. the
* type of terms that lem blocks models for,
- * sz : the minimum size of terms that the lem blocks.
- *
- * Notice that the symmetry breaking lemma template should be relative to x,
- * where x is returned by the call to getFreeVar( tn, 0 ) in this class.
+ * sz : the minimum size of terms that the lem blocks,
+ * isTempl : if this flag is false, then lem is a (concrete) lemma.
+ * If this flag is true, then lem is a symmetry breaking lemma template
+ * over x, where x is returned by the call to getFreeVar( tn, 0 ).
*/
- void registerSymBreakLemma(Node e, Node lem, TypeNode tn, unsigned sz);
+ void registerSymBreakLemma(
+ Node e, Node lem, TypeNode tn, unsigned sz, bool isTempl = true);
/** Has symmetry breaking lemmas been added for any enumerator? */
bool hasSymBreakLemmas(std::vector<Node>& enums) const;
/** Get symmetry breaking lemmas
@@ -168,6 +189,8 @@ class TermDbSygus {
TypeNode getTypeForSymBreakLemma(Node lem) const;
/** Get the minimum size of terms symmetry breaking lemma lem applies to */
unsigned getSizeForSymBreakLemma(Node lem) const;
+ /** Returns true if lem is a lemma template, false if lem is a lemma */
+ bool isSymBreakLemmaTemplate(Node lem) const;
/** Clear information about symmetry breaking lemmas for enumerator e */
void clearSymBreakLemmas(Node e);
//------------------------------end enumerators
@@ -324,6 +347,8 @@ class TermDbSygus {
std::map<Node, TypeNode> d_sb_lemma_to_type;
/** mapping from symmetry breaking lemmas to size */
std::map<Node, unsigned> d_sb_lemma_to_size;
+ /** mapping from symmetry breaking lemmas to whether they are templates */
+ std::map<Node, bool> d_sb_lemma_to_isTempl;
/** enumerators to whether they are actively-generated */
std::map<Node, bool> d_enum_active_gen;
/** enumerators to whether they are variable agnostic */
diff --git a/src/theory/strings/theory_strings_preprocess.cpp b/src/theory/strings/theory_strings_preprocess.cpp
index fcb02d058..a1b37e6fb 100644
--- a/src/theory/strings/theory_strings_preprocess.cpp
+++ b/src/theory/strings/theory_strings_preprocess.cpp
@@ -192,7 +192,10 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
Node ud =
nm->mkSkolem("Ud", nm->mkFunctionType(argTypes, nm->stringType()));
- Node lem = n.eqNode(nm->mkNode(APPLY_UF, u, leni));
+ Node lem = nm->mkNode(GEQ, leni, d_one);
+ conc.push_back(lem);
+
+ lem = n.eqNode(nm->mkNode(APPLY_UF, u, leni));
conc.push_back(lem);
lem = d_zero.eqNode(nm->mkNode(APPLY_UF, u, d_zero));
@@ -205,23 +208,26 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
conc.push_back(lem);
Node x = nm->mkBoundVar(nm->integerType());
+ Node xPlusOne = nm->mkNode(PLUS, x, d_one);
Node xbv = nm->mkNode(BOUND_VAR_LIST, x);
Node g =
nm->mkNode(AND, nm->mkNode(GEQ, x, d_zero), nm->mkNode(LT, x, leni));
Node udx = nm->mkNode(APPLY_UF, ud, x);
Node ux = nm->mkNode(APPLY_UF, u, x);
- Node ux1 = nm->mkNode(APPLY_UF, u, nm->mkNode(PLUS, x, d_one));
+ Node ux1 = nm->mkNode(APPLY_UF, u, xPlusOne);
Node c0 = nm->mkNode(STRING_CODE, nm->mkConst(String("0")));
Node c = nm->mkNode(MINUS, nm->mkNode(STRING_CODE, udx), c0);
Node usx = nm->mkNode(APPLY_UF, us, x);
- Node usx1 = nm->mkNode(APPLY_UF, us, nm->mkNode(PLUS, x, d_one));
+ Node usx1 = nm->mkNode(APPLY_UF, us, xPlusOne);
Node ten = nm->mkConst(Rational(10));
Node eqs = usx.eqNode(nm->mkNode(STRING_CONCAT, udx, usx1));
Node eq = ux1.eqNode(nm->mkNode(PLUS, c, nm->mkNode(MULT, ten, ux)));
+ Node leadingZeroPos =
+ nm->mkNode(AND, x.eqNode(d_zero), nm->mkNode(GT, leni, d_one));
Node cb = nm->mkNode(
AND,
- nm->mkNode(GEQ, c, nm->mkNode(ITE, x.eqNode(d_zero), d_one, d_zero)),
+ nm->mkNode(GEQ, c, nm->mkNode(ITE, leadingZeroPos, d_one, d_zero)),
nm->mkNode(LT, c, ten));
lem = nm->mkNode(OR, g.negate(), nm->mkNode(AND, eqs, eq, cb));
@@ -236,12 +242,13 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
// assert:
// IF n>=0
// THEN:
+ // len( itost ) >= 1 ^
// n = U( len( itost ) ) ^ U( 0 ) = 0 ^
// "" = Us( len( itost ) ) ^ itost = Us( 0 ) ^
// forall x. (x>=0 ^ x < str.len(itost)) =>
// Us( x ) = Ud( x ) ++ Us( x+1 ) ^
// U( x+1 ) = (str.code( Ud( x ) )-48) + 10*U( x ) ^
- // ite( x=0, 49, 48 ) <= str.code( Ud( x ) ) < 58
+ // ite( x=0 AND str.len(itost)>1, 49, 48 ) <= str.code( Ud( x ) ) < 58
// ELSE
// itost = ""
// thus:
@@ -254,7 +261,8 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
// str.to.int( str.substr( int.to.str( n ), 0, x ) ). For example, for
// n=345, we have that U(1), U(2), U(3) = 3, 34, 345.
// Above, we use str.code to map characters to their integer value, where
- // note that str.code( "0" ) = 48. Further notice that ite( x=0, 49, 48 )
+ // note that str.code( "0" ) = 48. Further notice that
+ // ite( x=0 AND str.len(itost)>1, 49, 48 )
// enforces that int.to.str( n ) has no leading zeroes.
retNode = itost;
} else if( t.getKind() == kind::STRING_STOI ) {
diff --git a/src/theory/strings/theory_strings_rewriter.cpp b/src/theory/strings/theory_strings_rewriter.cpp
index c90576726..aa5b616fe 100644
--- a/src/theory/strings/theory_strings_rewriter.cpp
+++ b/src/theory/strings/theory_strings_rewriter.cpp
@@ -4962,7 +4962,7 @@ std::pair<bool, std::vector<Node> > TheoryStringsRewriter::collectEmptyEqs(
allEmptyEqs = false;
}
}
- else
+ else if (x.getKind() == kind::AND)
{
for (const Node& c : x)
{
diff --git a/test/regress/CMakeLists.txt b/test/regress/CMakeLists.txt
index 5aea954e3..5304fcab5 100644
--- a/test/regress/CMakeLists.txt
+++ b/test/regress/CMakeLists.txt
@@ -157,6 +157,8 @@ set(regress_0_tests
regress0/buggy-ite.smt2
regress0/bv/ackermann1.smt2
regress0/bv/ackermann2.smt2
+ regress0/bv/ackermann3.smt2
+ regress0/bv/ackermann4.smt2
regress0/bv/bool-to-bv.smt2
regress0/bv/bug260a.smt
regress0/bv/bug260b.smt
@@ -171,7 +173,8 @@ set(regress_0_tests
regress0/bv/bv-options2.smt2
regress0/bv/bv-options3.smt2
regress0/bv/bv-options4.smt2
- regress0/bv/bv-to-bool.smt
+ regress0/bv/bv-to-bool1.smt
+ regress0/bv/bv-to-bool2.smt2
regress0/bv/bv2nat-ground-c.smt2
regress0/bv/bv2nat-simp-range.smt2
regress0/bv/bvmul-pow2-only.smt2
@@ -836,6 +839,7 @@ set(regress_0_tests
regress0/strings/substr-rewrites.smt2
regress0/strings/type001.smt2
regress0/strings/unsound-0908.smt2
+ regress0/strings/unsound-repl-rewrite.smt2
regress0/sygus/General_plus10.sy
regress0/sygus/aig-si.sy
regress0/sygus/c100.sy
diff --git a/test/regress/README.md b/test/regress/README.md
index d43ebf337..28ccfb96b 100644
--- a/test/regress/README.md
+++ b/test/regress/README.md
@@ -3,20 +3,10 @@
## Regression Levels and Running Regression Tests
CVC4's regression tests are divided into 5 levels (level 0 to 4). Higher
-regression levels are reserved for longer running regressions. To run
-regressions up to a certain level use `make regressX` where `X` designates the
-level. `make regress` by default runs levels 0 and 1. On Travis, we only run
-regression level 0 to keep the time short. During our nightly builds, we run
-regression level 2.
+regression levels are reserved for longer running regressions.
-To only run some benchmarks, you can use the `TEST_REGEX` environment variable.
-For example:
-
-```
-TEST_REGEX=quantifiers make regress0
-```
-
-This runs regression tests from level 0 that have "quantifiers" in their name.
+For running regressions tests,
+see the [INSTALL](https://github.com/CVC4/CVC4/blob/master/INSTALL.md#testing-cvc4) file.
By default, each invocation of CVC4 is done with a 10 minute timeout. To use a
different timeout, set the `TEST_TIMEOUT` environment variable:
@@ -35,10 +25,10 @@ To add a new regression file, add the file to git, for example:
git add regress/regress0/testMyFunctionality.cvc
```
-Also add it to [Makefile.tests](Makefile.tests) in this directory.
+Also add it to [CMakeLists.txt](CMakeLists.txt) in this directory.
A number of regressions exist under test/regress that are not listed in
-[Makefile.tests](Makefile.tests). These are regressions that may someday be
+[CMakeLists.txt](CMakeLists.txt). These are regressions that may someday be
included in the standard suite of tests, but are not yet included (perhaps they
test functionality not yet supported).
diff --git a/test/regress/regress0/bug217.smt2 b/test/regress/regress0/bug217.smt2
index 4d2e828b5..30c87333e 100644
--- a/test/regress/regress0/bug217.smt2
+++ b/test/regress/regress0/bug217.smt2
@@ -1,3 +1,4 @@
+; COMMAND-LINE: --fewer-preprocessing-holes
; EXPECT: unsat
(set-logic QF_UF)
(set-info :status unsat)
diff --git a/test/regress/regress0/bv/ackermann3.smt2 b/test/regress/regress0/bv/ackermann3.smt2
new file mode 100644
index 000000000..8e47c8840
--- /dev/null
+++ b/test/regress/regress0/bv/ackermann3.smt2
@@ -0,0 +1,23 @@
+; COMMAND-LINE: --bitblast=eager --no-check-models --no-check-proofs --no-check-unsat-cores
+; EXPECT: unsat
+(set-logic QF_ABV)
+(set-info :smt-lib-version 2.0)
+(set-info :category "crafted")
+(set-info :status unsat)
+
+(define-sort bv () (_ BitVec 4))
+(define-sort abv () (Array bv bv))
+
+(declare-fun v0 () (_ BitVec 4))
+(declare-fun v1 () (_ BitVec 4))
+(declare-fun a () abv)
+(declare-fun b () abv)
+(declare-fun c () abv)
+
+(assert (not (= (select a (select b (select c v0))) (select a (select b (select c v1))))))
+
+(assert (= v0 v1))
+
+
+(check-sat)
+(exit)
diff --git a/test/regress/regress0/bv/ackermann4.smt2 b/test/regress/regress0/bv/ackermann4.smt2
new file mode 100644
index 000000000..cb8ad2e55
--- /dev/null
+++ b/test/regress/regress0/bv/ackermann4.smt2
@@ -0,0 +1,16 @@
+; COMMAND-LINE: --bitblast=eager --no-check-models --no-check-proofs --no-check-unsat-cores
+; EXPECT: sat
+(set-logic QF_UFBV)
+(set-info :smt-lib-version 2.0)
+(set-info :category "crafted")
+(set-info :status unsat)
+(declare-fun v0 () (_ BitVec 4))
+(declare-fun f ((_ BitVec 4)) (_ BitVec 4))
+(declare-fun g ((_ BitVec 4)) (_ BitVec 4))
+
+(assert (= (f v0) (g (f v0))))
+(assert (= (f (f v0)) (g (f v0))))
+(assert (= (f (f (f v0))) (g (f v0))))
+
+(check-sat)
+(exit)
diff --git a/test/regress/regress0/bv/bool-to-bv.smt2 b/test/regress/regress0/bv/bool-to-bv.smt2
index 92c7e4117..8706c51a8 100644
--- a/test/regress/regress0/bv/bool-to-bv.smt2
+++ b/test/regress/regress0/bv/bool-to-bv.smt2
@@ -6,7 +6,14 @@
(declare-fun x0 () (_ BitVec 3))
(declare-fun b1 () Bool)
(declare-fun b2 () Bool)
+(declare-fun b3 () Bool)
(assert (not (bvult (bvudiv (bvudiv (bvudiv x0 x0) x1) x2) x1)))
+(assert (not (bvslt (bvudiv (bvudiv (bvudiv x0 x0) x1) x2) x1)))
(assert (= #b000 x2))
(assert (=> b1 b2))
+(assert (and b1 b2))
+(assert (or b1 b2))
+(assert (xor b1 b3))
+(assert (not (xor b2 b2)))
+(assert (ite b2 b2 b1))
(check-sat)
diff --git a/test/regress/regress0/bv/bv-to-bool.smt b/test/regress/regress0/bv/bv-to-bool1.smt
index ef4cec257..ef4cec257 100644
--- a/test/regress/regress0/bv/bv-to-bool.smt
+++ b/test/regress/regress0/bv/bv-to-bool1.smt
diff --git a/test/regress/regress0/bv/bv-to-bool2.smt2 b/test/regress/regress0/bv/bv-to-bool2.smt2
new file mode 100644
index 000000000..fb741733d
--- /dev/null
+++ b/test/regress/regress0/bv/bv-to-bool2.smt2
@@ -0,0 +1,11 @@
+; COMMAND-LINE: --bv-to-bool
+; EXPECT: sat
+(set-logic QF_BV)
+(declare-fun v1 () (_ BitVec 1))
+(declare-fun v2 () (_ BitVec 1))
+
+(assert (= (bvxor v2 v1) v1))
+
+
+(check-sat)
+(exit)
diff --git a/test/regress/regress0/quantifiers/macros-real-arg.smt2 b/test/regress/regress0/quantifiers/macros-real-arg.smt2
index edacdbe37..52eeedae6 100644
--- a/test/regress/regress0/quantifiers/macros-real-arg.smt2
+++ b/test/regress/regress0/quantifiers/macros-real-arg.smt2
@@ -3,7 +3,8 @@
; this will fail if type rule for APPLY_UF is made strict
(set-logic UFLIRA)
(declare-fun P (Int) Bool)
-(assert (forall ((x Int)) (P x)))
+(declare-fun Q (Int) Bool)
+(assert (and (forall ((x Int)) (P x)) (forall ((x Int)) (Q x))))
(declare-fun k () Real)
(declare-fun k2 () Int)
(assert (or (not (P (to_int k))) (not (P k2))))
diff --git a/test/regress/regress0/strings/unsound-repl-rewrite.smt2 b/test/regress/regress0/strings/unsound-repl-rewrite.smt2
new file mode 100644
index 000000000..02e4cc0b2
--- /dev/null
+++ b/test/regress/regress0/strings/unsound-repl-rewrite.smt2
@@ -0,0 +1,8 @@
+; COMMAND-LINE: --strings-exp
+; EXPECT: sat
+(set-logic QF_S)
+(declare-fun x () String)
+(declare-fun y () String)
+(declare-fun z () Int)
+(assert (not (= (str.replace "B" (str.replace "" x "A") "B") (str.replace "B" x "B"))))
+(check-sat)
diff --git a/test/regress/regress1/sygus/commutative-stream.sy b/test/regress/regress1/sygus/commutative-stream.sy
index 7b96a2bf3..8203fd9cf 100644
--- a/test/regress/regress1/sygus/commutative-stream.sy
+++ b/test/regress/regress1/sygus/commutative-stream.sy
@@ -3,7 +3,7 @@
; EXPECT: (error "Maximum term size (2) for enumerative SyGuS exceeded.")
; EXIT: 1
-; COMMAND-LINE: --sygus-stream --sygus-abort-size=2 --decision=justification
+; COMMAND-LINE: --sygus-stream --sygus-abort-size=2 --sygus-active-gen=none --decision=justification
(set-logic LIA)
diff --git a/test/unit/api/CMakeLists.txt b/test/unit/api/CMakeLists.txt
index 90d34f7c6..eeab46f99 100644
--- a/test/unit/api/CMakeLists.txt
+++ b/test/unit/api/CMakeLists.txt
@@ -1,4 +1,6 @@
#-----------------------------------------------------------------------------#
# Add unit tests
-cvc4_add_unit_test_black(api_guards_black api)
+cvc4_add_unit_test_black(solver_black api)
+cvc4_add_unit_test_black(sort_black api)
+cvc4_add_unit_test_black(term_black api)
diff --git a/test/unit/api/api_guards_black.h b/test/unit/api/api_guards_black.h
deleted file mode 100644
index 777ce81f1..000000000
--- a/test/unit/api/api_guards_black.h
+++ /dev/null
@@ -1,473 +0,0 @@
-/********************* */
-/*! \file api_guards_black.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Aina Niemetz
- ** 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 Black box testing of the guards of the C++ API functions.
- **
- ** Black box testing of the guards of the C++ API functions.
- **/
-
-#include <cxxtest/TestSuite.h>
-
-#include "api/cvc4cpp.h"
-
-using namespace CVC4::api;
-
-class ApiGuardsBlack : public CxxTest::TestSuite
-{
- public:
- void setUp() override;
- void tearDown() override;
-
- void testSolverMkBitVectorSort();
- void testSolverMkFloatingPointSort();
- void testSolverMkDatatypeSort();
- void testSolverMkFunctionSort();
- void testSolverMkPredicateSort();
- void testSolverMkTupleSort();
- void testSortGetDatatype();
- void testSortInstantiate();
- void testSortGetFunctionArity();
- void testSortGetFunctionDomainSorts();
- void testSortGetFunctionCodomainSort();
- void testSortGetArrayIndexSort();
- void testSortGetArrayElementSort();
- void testSortGetSetElementSort();
- void testSortGetUninterpretedSortName();
- void testSortIsUninterpretedSortParameterized();
- void testSortGetUninterpretedSortParamSorts();
- void testSortGetUninterpretedSortConstructorName();
- void testSortGetUninterpretedSortConstructorArity();
- void testSortGetBVSize();
- void testSortGetFPExponentSize();
- void testSortGetFPSignificandSize();
- void testSortGetDatatypeParamSorts();
- void testSortGetDatatypeArity();
- void testSortGetTupleLength();
- void testSortGetTupleSorts();
- void testSolverDeclareFun();
- void testSolverDefineFun();
- void testSolverDefineFunRec();
- void testSolverDefineFunsRec();
-
- private:
- Solver d_solver;
-};
-
-void ApiGuardsBlack::setUp() {}
-
-void ApiGuardsBlack::tearDown() {}
-
-void ApiGuardsBlack::testSolverMkBitVectorSort()
-{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkBitVectorSort(32));
- TS_ASSERT_THROWS(d_solver.mkBitVectorSort(0), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSolverMkFloatingPointSort()
-{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkFloatingPointSort(4, 8));
- TS_ASSERT_THROWS(d_solver.mkFloatingPointSort(0, 8), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.mkFloatingPointSort(4, 0), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSolverMkDatatypeSort()
-{
- DatatypeDecl dtypeSpec("list");
- DatatypeConstructorDecl cons("cons");
- DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
- cons.addSelector(head);
- dtypeSpec.addConstructor(cons);
- DatatypeConstructorDecl nil("nil");
- dtypeSpec.addConstructor(nil);
- TS_ASSERT_THROWS_NOTHING(d_solver.mkDatatypeSort(dtypeSpec));
- DatatypeDecl throwsDtypeSpec("list");
- TS_ASSERT_THROWS(d_solver.mkDatatypeSort(throwsDtypeSpec), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSolverMkFunctionSort()
-{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkFunctionSort(
- d_solver.mkUninterpretedSort("u"), d_solver.getIntegerSort()));
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS(d_solver.mkFunctionSort(funSort, d_solver.getIntegerSort()),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.mkFunctionSort(d_solver.getIntegerSort(), funSort),
- CVC4ApiException&);
- TS_ASSERT_THROWS_NOTHING(d_solver.mkFunctionSort(
- {d_solver.mkUninterpretedSort("u"), d_solver.getIntegerSort()},
- d_solver.getIntegerSort()));
- Sort funSort2 = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS(
- d_solver.mkFunctionSort({funSort2, d_solver.mkUninterpretedSort("u")},
- d_solver.getIntegerSort()),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.mkFunctionSort({d_solver.getIntegerSort(),
- d_solver.mkUninterpretedSort("u")},
- funSort2),
- CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSolverMkPredicateSort()
-{
- TS_ASSERT_THROWS_NOTHING(
- d_solver.mkPredicateSort({d_solver.getIntegerSort()}));
- TS_ASSERT_THROWS(d_solver.mkPredicateSort({}), CVC4ApiException&);
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS(
- d_solver.mkPredicateSort({d_solver.getIntegerSort(), funSort}),
- CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSolverMkTupleSort()
-{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkTupleSort({d_solver.getIntegerSort()}));
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS(d_solver.mkTupleSort({d_solver.getIntegerSort(), funSort}),
- CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetDatatype()
-{
- // create datatype sort, check should not fail
- DatatypeDecl dtypeSpec("list");
- DatatypeConstructorDecl cons("cons");
- DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
- cons.addSelector(head);
- dtypeSpec.addConstructor(cons);
- DatatypeConstructorDecl nil("nil");
- dtypeSpec.addConstructor(nil);
- Sort dtypeSort = d_solver.mkDatatypeSort(dtypeSpec);
- TS_ASSERT_THROWS_NOTHING(dtypeSort.getDatatype());
- // create bv sort, check should fail
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getDatatype(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortInstantiate()
-{
- // instantiate parametric datatype, check should not fail
- Sort sort = d_solver.mkParamSort("T");
- DatatypeDecl paramDtypeSpec("paramlist", sort);
- DatatypeConstructorDecl paramCons("cons");
- DatatypeConstructorDecl paramNil("nil");
- DatatypeSelectorDecl paramHead("head", sort);
- paramCons.addSelector(paramHead);
- paramDtypeSpec.addConstructor(paramCons);
- paramDtypeSpec.addConstructor(paramNil);
- Sort paramDtypeSort = d_solver.mkDatatypeSort(paramDtypeSpec);
- TS_ASSERT_THROWS_NOTHING(
- paramDtypeSort.instantiate(std::vector<Sort>{d_solver.getIntegerSort()}));
- // instantiate non-parametric datatype sort, check should fail
- DatatypeDecl dtypeSpec("list");
- DatatypeConstructorDecl cons("cons");
- DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
- cons.addSelector(head);
- dtypeSpec.addConstructor(cons);
- DatatypeConstructorDecl nil("nil");
- dtypeSpec.addConstructor(nil);
- Sort dtypeSort = d_solver.mkDatatypeSort(dtypeSpec);
- TS_ASSERT_THROWS(
- dtypeSort.instantiate(std::vector<Sort>{d_solver.getIntegerSort()}),
- CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetFunctionArity()
-{
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS_NOTHING(funSort.getFunctionArity());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getFunctionArity(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetFunctionDomainSorts()
-{
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS_NOTHING(funSort.getFunctionDomainSorts());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getFunctionDomainSorts(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetFunctionCodomainSort()
-{
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS_NOTHING(funSort.getFunctionCodomainSort());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getFunctionCodomainSort(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetArrayIndexSort()
-{
- Sort elementSort = d_solver.mkBitVectorSort(32);
- Sort indexSort = d_solver.mkBitVectorSort(32);
- Sort arraySort = d_solver.mkArraySort(indexSort, elementSort);
- TS_ASSERT_THROWS_NOTHING(arraySort.getArrayIndexSort());
- TS_ASSERT_THROWS(indexSort.getArrayIndexSort(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetArrayElementSort()
-{
- Sort elementSort = d_solver.mkBitVectorSort(32);
- Sort indexSort = d_solver.mkBitVectorSort(32);
- Sort arraySort = d_solver.mkArraySort(indexSort, elementSort);
- TS_ASSERT_THROWS_NOTHING(arraySort.getArrayElementSort());
- TS_ASSERT_THROWS(indexSort.getArrayElementSort(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetSetElementSort()
-{
- Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort());
- TS_ASSERT_THROWS_NOTHING(setSort.getSetElementSort());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getSetElementSort(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetUninterpretedSortName()
-{
- Sort uSort = d_solver.mkUninterpretedSort("u");
- TS_ASSERT_THROWS_NOTHING(uSort.getUninterpretedSortName());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getUninterpretedSortName(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortIsUninterpretedSortParameterized()
-{
- Sort uSort = d_solver.mkUninterpretedSort("u");
- TS_ASSERT_THROWS_NOTHING(uSort.isUninterpretedSortParameterized());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.isUninterpretedSortParameterized(),
- CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetUninterpretedSortParamSorts()
-{
- Sort uSort = d_solver.mkUninterpretedSort("u");
- TS_ASSERT_THROWS_NOTHING(uSort.getUninterpretedSortParamSorts());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getUninterpretedSortParamSorts(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetUninterpretedSortConstructorName()
-{
- Sort sSort = d_solver.mkSortConstructorSort("s", 2);
- TS_ASSERT_THROWS_NOTHING(sSort.getSortConstructorName());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getSortConstructorName(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetUninterpretedSortConstructorArity()
-{
- Sort sSort = d_solver.mkSortConstructorSort("s", 2);
- TS_ASSERT_THROWS_NOTHING(sSort.getSortConstructorArity());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getSortConstructorArity(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetBVSize()
-{
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS_NOTHING(bvSort.getBVSize());
- Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort());
- TS_ASSERT_THROWS(setSort.getBVSize(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetFPExponentSize()
-{
- Sort fpSort = d_solver.mkFloatingPointSort(4, 8);
- TS_ASSERT_THROWS_NOTHING(fpSort.getFPExponentSize());
- Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort());
- TS_ASSERT_THROWS(setSort.getFPExponentSize(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetFPSignificandSize()
-{
- Sort fpSort = d_solver.mkFloatingPointSort(4, 8);
- TS_ASSERT_THROWS_NOTHING(fpSort.getFPSignificandSize());
- Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort());
- TS_ASSERT_THROWS(setSort.getFPSignificandSize(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetDatatypeParamSorts()
-{
- // create parametric datatype, check should not fail
- Sort sort = d_solver.mkParamSort("T");
- DatatypeDecl paramDtypeSpec("paramlist", sort);
- DatatypeConstructorDecl paramCons("cons");
- DatatypeConstructorDecl paramNil("nil");
- DatatypeSelectorDecl paramHead("head", sort);
- paramCons.addSelector(paramHead);
- paramDtypeSpec.addConstructor(paramCons);
- paramDtypeSpec.addConstructor(paramNil);
- Sort paramDtypeSort = d_solver.mkDatatypeSort(paramDtypeSpec);
- TS_ASSERT_THROWS_NOTHING(paramDtypeSort.getDatatypeParamSorts());
- // create non-parametric datatype sort, check should fail
- DatatypeDecl dtypeSpec("list");
- DatatypeConstructorDecl cons("cons");
- DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
- cons.addSelector(head);
- dtypeSpec.addConstructor(cons);
- DatatypeConstructorDecl nil("nil");
- dtypeSpec.addConstructor(nil);
- Sort dtypeSort = d_solver.mkDatatypeSort(dtypeSpec);
- TS_ASSERT_THROWS(dtypeSort.getDatatypeParamSorts(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetDatatypeArity()
-{
- // create datatype sort, check should not fail
- DatatypeDecl dtypeSpec("list");
- DatatypeConstructorDecl cons("cons");
- DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
- cons.addSelector(head);
- dtypeSpec.addConstructor(cons);
- DatatypeConstructorDecl nil("nil");
- dtypeSpec.addConstructor(nil);
- Sort dtypeSort = d_solver.mkDatatypeSort(dtypeSpec);
- TS_ASSERT_THROWS_NOTHING(dtypeSort.getDatatypeArity());
- // create bv sort, check should fail
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getDatatypeArity(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetTupleLength()
-{
- Sort tupleSort = d_solver.mkTupleSort(
- {d_solver.getIntegerSort(), d_solver.getIntegerSort()});
- TS_ASSERT_THROWS_NOTHING(tupleSort.getTupleLength());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getTupleLength(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSortGetTupleSorts()
-{
- Sort tupleSort = d_solver.mkTupleSort(
- {d_solver.getIntegerSort(), d_solver.getIntegerSort()});
- TS_ASSERT_THROWS_NOTHING(tupleSort.getTupleSorts());
- Sort bvSort = d_solver.mkBitVectorSort(32);
- TS_ASSERT_THROWS(bvSort.getTupleSorts(), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSolverDeclareFun()
-{
- Sort bvSort = d_solver.mkBitVectorSort(32);
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS_NOTHING(d_solver.declareFun("f1", bvSort));
- TS_ASSERT_THROWS_NOTHING(d_solver.declareFun("f2", funSort));
- TS_ASSERT_THROWS_NOTHING(
- d_solver.declareFun("f3", {bvSort, d_solver.getIntegerSort()}, bvSort));
- TS_ASSERT_THROWS(d_solver.declareFun("f4", {bvSort, funSort}, bvSort),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.declareFun("f5", {bvSort, bvSort}, funSort),
- CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSolverDefineFun()
-{
- Sort bvSort = d_solver.mkBitVectorSort(32);
- Sort funSort1 = d_solver.mkFunctionSort({bvSort, bvSort}, bvSort);
- Sort funSort2 = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- Term b1 = d_solver.mkBoundVar("b1", bvSort);
- Term b11 = d_solver.mkBoundVar("b1", bvSort);
- Term b2 = d_solver.mkBoundVar("b2", d_solver.getIntegerSort());
- Term b3 = d_solver.mkBoundVar("b3", funSort2);
- Term v1 = d_solver.mkBoundVar("v1", bvSort);
- Term v2 = d_solver.mkBoundVar("v2", d_solver.getIntegerSort());
- Term v3 = d_solver.mkVar("v3", funSort2);
- Term f1 = d_solver.declareFun("f1", funSort1);
- Term f2 = d_solver.declareFun("f2", funSort2);
- Term f3 = d_solver.declareFun("f3", bvSort);
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFun("f", {}, bvSort, v1));
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFun("ff", {b1, b2}, bvSort, v1));
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFun(f1, {b1, b11}, v1));
- TS_ASSERT_THROWS(d_solver.defineFun("fff", {b1}, bvSort, v3),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun("ffff", {b1}, funSort2, v3),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun("fffff", {b1, b3}, bvSort, v1),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun(f1, {b1}, v1), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun(f1, {b1, b11}, v2), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun(f1, {b1, b11}, v3), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun(f2, {b1}, v2), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun(f3, {b1}, v1), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSolverDefineFunRec()
-{
- Sort bvSort = d_solver.mkBitVectorSort(32);
- Sort funSort1 = d_solver.mkFunctionSort({bvSort, bvSort}, bvSort);
- Sort funSort2 = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- Term b1 = d_solver.mkBoundVar("b1", bvSort);
- Term b11 = d_solver.mkBoundVar("b1", bvSort);
- Term b2 = d_solver.mkBoundVar("b2", d_solver.getIntegerSort());
- Term b3 = d_solver.mkBoundVar("b3", funSort2);
- Term v1 = d_solver.mkBoundVar("v1", bvSort);
- Term v2 = d_solver.mkBoundVar("v2", d_solver.getIntegerSort());
- Term v3 = d_solver.mkVar("v3", funSort2);
- Term f1 = d_solver.declareFun("f1", funSort1);
- Term f2 = d_solver.declareFun("f2", funSort2);
- Term f3 = d_solver.declareFun("f3", bvSort);
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFunRec("f", {}, bvSort, v1));
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFunRec("ff", {b1, b2}, bvSort, v1));
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFunRec(f1, {b1, b11}, v1));
- TS_ASSERT_THROWS(d_solver.defineFunRec("fff", {b1}, bvSort, v3),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec("ffff", {b1}, funSort2, v3),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec("fffff", {b1, b3}, bvSort, v1),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec(f1, {b1}, v1), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec(f1, {b1, b11}, v2), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec(f1, {b1, b11}, v3), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec(f2, {b1}, v2), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec(f3, {b1}, v1), CVC4ApiException&);
-}
-
-void ApiGuardsBlack::testSolverDefineFunsRec()
-{
- Sort uSort = d_solver.mkUninterpretedSort("u");
- Sort bvSort = d_solver.mkBitVectorSort(32);
- Sort funSort1 = d_solver.mkFunctionSort({bvSort, bvSort}, bvSort);
- Sort funSort2 = d_solver.mkFunctionSort(uSort, d_solver.getIntegerSort());
- Term b1 = d_solver.mkBoundVar("b1", bvSort);
- Term b11 = d_solver.mkBoundVar("b1", bvSort);
- Term b2 = d_solver.mkBoundVar("b2", d_solver.getIntegerSort());
- Term b3 = d_solver.mkBoundVar("b3", funSort2);
- Term b4 = d_solver.mkBoundVar("b4", uSort);
- Term v1 = d_solver.mkBoundVar("v1", bvSort);
- Term v2 = d_solver.mkBoundVar("v2", d_solver.getIntegerSort());
- Term v3 = d_solver.mkVar("v3", funSort2);
- Term v4 = d_solver.mkVar("v4", uSort);
- Term f1 = d_solver.declareFun("f1", funSort1);
- Term f2 = d_solver.declareFun("f2", funSort2);
- Term f3 = d_solver.declareFun("f3", bvSort);
- TS_ASSERT_THROWS_NOTHING(
- d_solver.defineFunsRec({f1, f2}, {{b1, b11}, {b4}}, {v1, v2}));
- TS_ASSERT_THROWS(
- d_solver.defineFunsRec({f1, f3}, {{b1, b11}, {b4}}, {v1, v2}),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunsRec({f1, f2}, {{b1}, {b4}}, {v1, v2}),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunsRec({f1, f2}, {{b1, b2}, {b4}}, {v1, v2}),
- CVC4ApiException&);
- TS_ASSERT_THROWS(
- d_solver.defineFunsRec({f1, f2}, {{b1, b11}, {b4}}, {v1, v4}),
- CVC4ApiException&);
-}
diff --git a/test/unit/api/solver_black.h b/test/unit/api/solver_black.h
new file mode 100644
index 000000000..538899a0f
--- /dev/null
+++ b/test/unit/api/solver_black.h
@@ -0,0 +1,230 @@
+/********************* */
+/*! \file api_guards_black.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Aina Niemetz
+ ** 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 Black box testing of the guards of the C++ API functions.
+ **
+ ** Black box testing of the guards of the C++ API functions.
+ **/
+
+#include <cxxtest/TestSuite.h>
+
+#include "api/cvc4cpp.h"
+
+using namespace CVC4::api;
+
+class SolverBlack : public CxxTest::TestSuite
+{
+ public:
+ void setUp() override;
+ void tearDown() override;
+
+ void testMkBitVectorSort();
+ void testMkFloatingPointSort();
+ void testMkDatatypeSort();
+ void testMkFunctionSort();
+ void testMkPredicateSort();
+ void testMkTupleSort();
+ void testDeclareFun();
+ void testDefineFun();
+ void testDefineFunRec();
+ void testDefineFunsRec();
+
+ private:
+ Solver d_solver;
+};
+
+void SolverBlack::setUp() {}
+
+void SolverBlack::tearDown() {}
+
+void SolverBlack::testMkBitVectorSort()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver.mkBitVectorSort(32));
+ TS_ASSERT_THROWS(d_solver.mkBitVectorSort(0), CVC4ApiException&);
+}
+
+void SolverBlack::testMkFloatingPointSort()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver.mkFloatingPointSort(4, 8));
+ TS_ASSERT_THROWS(d_solver.mkFloatingPointSort(0, 8), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.mkFloatingPointSort(4, 0), CVC4ApiException&);
+}
+
+void SolverBlack::testMkDatatypeSort()
+{
+ DatatypeDecl dtypeSpec("list");
+ DatatypeConstructorDecl cons("cons");
+ DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
+ cons.addSelector(head);
+ dtypeSpec.addConstructor(cons);
+ DatatypeConstructorDecl nil("nil");
+ dtypeSpec.addConstructor(nil);
+ TS_ASSERT_THROWS_NOTHING(d_solver.mkDatatypeSort(dtypeSpec));
+ DatatypeDecl throwsDtypeSpec("list");
+ TS_ASSERT_THROWS(d_solver.mkDatatypeSort(throwsDtypeSpec), CVC4ApiException&);
+}
+
+void SolverBlack::testMkFunctionSort()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver.mkFunctionSort(
+ d_solver.mkUninterpretedSort("u"), d_solver.getIntegerSort()));
+ Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
+ d_solver.getIntegerSort());
+ TS_ASSERT_THROWS(d_solver.mkFunctionSort(funSort, d_solver.getIntegerSort()),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.mkFunctionSort(d_solver.getIntegerSort(), funSort),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver.mkFunctionSort(
+ {d_solver.mkUninterpretedSort("u"), d_solver.getIntegerSort()},
+ d_solver.getIntegerSort()));
+ Sort funSort2 = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
+ d_solver.getIntegerSort());
+ TS_ASSERT_THROWS(
+ d_solver.mkFunctionSort({funSort2, d_solver.mkUninterpretedSort("u")},
+ d_solver.getIntegerSort()),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.mkFunctionSort({d_solver.getIntegerSort(),
+ d_solver.mkUninterpretedSort("u")},
+ funSort2),
+ CVC4ApiException&);
+}
+
+void SolverBlack::testMkPredicateSort()
+{
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver.mkPredicateSort({d_solver.getIntegerSort()}));
+ TS_ASSERT_THROWS(d_solver.mkPredicateSort({}), CVC4ApiException&);
+ Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
+ d_solver.getIntegerSort());
+ TS_ASSERT_THROWS(
+ d_solver.mkPredicateSort({d_solver.getIntegerSort(), funSort}),
+ CVC4ApiException&);
+}
+
+void SolverBlack::testMkTupleSort()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver.mkTupleSort({d_solver.getIntegerSort()}));
+ Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
+ d_solver.getIntegerSort());
+ TS_ASSERT_THROWS(d_solver.mkTupleSort({d_solver.getIntegerSort(), funSort}),
+ CVC4ApiException&);
+}
+
+void SolverBlack::testDeclareFun()
+{
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
+ d_solver.getIntegerSort());
+ TS_ASSERT_THROWS_NOTHING(d_solver.declareFun("f1", bvSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver.declareFun("f2", funSort));
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver.declareFun("f3", {bvSort, d_solver.getIntegerSort()}, bvSort));
+ TS_ASSERT_THROWS(d_solver.declareFun("f4", {bvSort, funSort}, bvSort),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.declareFun("f5", {bvSort, bvSort}, funSort),
+ CVC4ApiException&);
+}
+
+void SolverBlack::testDefineFun()
+{
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ Sort funSort1 = d_solver.mkFunctionSort({bvSort, bvSort}, bvSort);
+ Sort funSort2 = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
+ d_solver.getIntegerSort());
+ Term b1 = d_solver.mkBoundVar("b1", bvSort);
+ Term b11 = d_solver.mkBoundVar("b1", bvSort);
+ Term b2 = d_solver.mkBoundVar("b2", d_solver.getIntegerSort());
+ Term b3 = d_solver.mkBoundVar("b3", funSort2);
+ Term v1 = d_solver.mkBoundVar("v1", bvSort);
+ Term v2 = d_solver.mkBoundVar("v2", d_solver.getIntegerSort());
+ Term v3 = d_solver.mkVar("v3", funSort2);
+ Term f1 = d_solver.declareFun("f1", funSort1);
+ Term f2 = d_solver.declareFun("f2", funSort2);
+ Term f3 = d_solver.declareFun("f3", bvSort);
+ TS_ASSERT_THROWS_NOTHING(d_solver.defineFun("f", {}, bvSort, v1));
+ TS_ASSERT_THROWS_NOTHING(d_solver.defineFun("ff", {b1, b2}, bvSort, v1));
+ TS_ASSERT_THROWS_NOTHING(d_solver.defineFun(f1, {b1, b11}, v1));
+ TS_ASSERT_THROWS(d_solver.defineFun("fff", {b1}, bvSort, v3),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFun("ffff", {b1}, funSort2, v3),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFun("fffff", {b1, b3}, bvSort, v1),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFun(f1, {b1}, v1), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFun(f1, {b1, b11}, v2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFun(f1, {b1, b11}, v3), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFun(f2, {b1}, v2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFun(f3, {b1}, v1), CVC4ApiException&);
+}
+
+void SolverBlack::testDefineFunRec()
+{
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ Sort funSort1 = d_solver.mkFunctionSort({bvSort, bvSort}, bvSort);
+ Sort funSort2 = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
+ d_solver.getIntegerSort());
+ Term b1 = d_solver.mkBoundVar("b1", bvSort);
+ Term b11 = d_solver.mkBoundVar("b1", bvSort);
+ Term b2 = d_solver.mkBoundVar("b2", d_solver.getIntegerSort());
+ Term b3 = d_solver.mkBoundVar("b3", funSort2);
+ Term v1 = d_solver.mkBoundVar("v1", bvSort);
+ Term v2 = d_solver.mkBoundVar("v2", d_solver.getIntegerSort());
+ Term v3 = d_solver.mkVar("v3", funSort2);
+ Term f1 = d_solver.declareFun("f1", funSort1);
+ Term f2 = d_solver.declareFun("f2", funSort2);
+ Term f3 = d_solver.declareFun("f3", bvSort);
+ TS_ASSERT_THROWS_NOTHING(d_solver.defineFunRec("f", {}, bvSort, v1));
+ TS_ASSERT_THROWS_NOTHING(d_solver.defineFunRec("ff", {b1, b2}, bvSort, v1));
+ TS_ASSERT_THROWS_NOTHING(d_solver.defineFunRec(f1, {b1, b11}, v1));
+ TS_ASSERT_THROWS(d_solver.defineFunRec("fff", {b1}, bvSort, v3),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFunRec("ffff", {b1}, funSort2, v3),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFunRec("fffff", {b1, b3}, bvSort, v1),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFunRec(f1, {b1}, v1), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFunRec(f1, {b1, b11}, v2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFunRec(f1, {b1, b11}, v3), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFunRec(f2, {b1}, v2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFunRec(f3, {b1}, v1), CVC4ApiException&);
+}
+
+void SolverBlack::testDefineFunsRec()
+{
+ Sort uSort = d_solver.mkUninterpretedSort("u");
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ Sort funSort1 = d_solver.mkFunctionSort({bvSort, bvSort}, bvSort);
+ Sort funSort2 = d_solver.mkFunctionSort(uSort, d_solver.getIntegerSort());
+ Term b1 = d_solver.mkBoundVar("b1", bvSort);
+ Term b11 = d_solver.mkBoundVar("b1", bvSort);
+ Term b2 = d_solver.mkBoundVar("b2", d_solver.getIntegerSort());
+ Term b3 = d_solver.mkBoundVar("b3", funSort2);
+ Term b4 = d_solver.mkBoundVar("b4", uSort);
+ Term v1 = d_solver.mkBoundVar("v1", bvSort);
+ Term v2 = d_solver.mkBoundVar("v2", d_solver.getIntegerSort());
+ Term v3 = d_solver.mkVar("v3", funSort2);
+ Term v4 = d_solver.mkVar("v4", uSort);
+ Term f1 = d_solver.declareFun("f1", funSort1);
+ Term f2 = d_solver.declareFun("f2", funSort2);
+ Term f3 = d_solver.declareFun("f3", bvSort);
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver.defineFunsRec({f1, f2}, {{b1, b11}, {b4}}, {v1, v2}));
+ TS_ASSERT_THROWS(
+ d_solver.defineFunsRec({f1, f3}, {{b1, b11}, {b4}}, {v1, v2}),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFunsRec({f1, f2}, {{b1}, {b4}}, {v1, v2}),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver.defineFunsRec({f1, f2}, {{b1, b2}, {b4}}, {v1, v2}),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(
+ d_solver.defineFunsRec({f1, f2}, {{b1, b11}, {b4}}, {v1, v4}),
+ CVC4ApiException&);
+}
diff --git a/test/unit/api/sort_black.h b/test/unit/api/sort_black.h
new file mode 100644
index 000000000..d9337e627
--- /dev/null
+++ b/test/unit/api/sort_black.h
@@ -0,0 +1,279 @@
+/********************* */
+/*! \file api_guards_black.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Aina Niemetz
+ ** 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 Black box testing of the guards of the C++ API functions.
+ **
+ ** Black box testing of the guards of the C++ API functions.
+ **/
+
+#include <cxxtest/TestSuite.h>
+
+#include "api/cvc4cpp.h"
+
+using namespace CVC4::api;
+
+class SortBlack : public CxxTest::TestSuite
+{
+ public:
+ void setUp() override;
+ void tearDown() override;
+
+ void testGetDatatype();
+ void testInstantiate();
+ void testGetFunctionArity();
+ void testGetFunctionDomainSorts();
+ void testGetFunctionCodomainSort();
+ void testGetArrayIndexSort();
+ void testGetArrayElementSort();
+ void testGetSetElementSort();
+ void testGetUninterpretedSortName();
+ void testIsUninterpretedSortParameterized();
+ void testGetUninterpretedSortParamSorts();
+ void testGetUninterpretedSortConstructorName();
+ void testGetUninterpretedSortConstructorArity();
+ void testGetBVSize();
+ void testGetFPExponentSize();
+ void testGetFPSignificandSize();
+ void testGetDatatypeParamSorts();
+ void testGetDatatypeArity();
+ void testGetTupleLength();
+ void testGetTupleSorts();
+
+ private:
+ Solver d_solver;
+};
+
+void SortBlack::setUp() {}
+
+void SortBlack::tearDown() {}
+
+void SortBlack::testGetDatatype()
+{
+ // create datatype sort, check should not fail
+ DatatypeDecl dtypeSpec("list");
+ DatatypeConstructorDecl cons("cons");
+ DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
+ cons.addSelector(head);
+ dtypeSpec.addConstructor(cons);
+ DatatypeConstructorDecl nil("nil");
+ dtypeSpec.addConstructor(nil);
+ Sort dtypeSort = d_solver.mkDatatypeSort(dtypeSpec);
+ TS_ASSERT_THROWS_NOTHING(dtypeSort.getDatatype());
+ // create bv sort, check should fail
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getDatatype(), CVC4ApiException&);
+}
+
+void SortBlack::testInstantiate()
+{
+ // instantiate parametric datatype, check should not fail
+ Sort sort = d_solver.mkParamSort("T");
+ DatatypeDecl paramDtypeSpec("paramlist", sort);
+ DatatypeConstructorDecl paramCons("cons");
+ DatatypeConstructorDecl paramNil("nil");
+ DatatypeSelectorDecl paramHead("head", sort);
+ paramCons.addSelector(paramHead);
+ paramDtypeSpec.addConstructor(paramCons);
+ paramDtypeSpec.addConstructor(paramNil);
+ Sort paramDtypeSort = d_solver.mkDatatypeSort(paramDtypeSpec);
+ TS_ASSERT_THROWS_NOTHING(
+ paramDtypeSort.instantiate(std::vector<Sort>{d_solver.getIntegerSort()}));
+ // instantiate non-parametric datatype sort, check should fail
+ DatatypeDecl dtypeSpec("list");
+ DatatypeConstructorDecl cons("cons");
+ DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
+ cons.addSelector(head);
+ dtypeSpec.addConstructor(cons);
+ DatatypeConstructorDecl nil("nil");
+ dtypeSpec.addConstructor(nil);
+ Sort dtypeSort = d_solver.mkDatatypeSort(dtypeSpec);
+ TS_ASSERT_THROWS(
+ dtypeSort.instantiate(std::vector<Sort>{d_solver.getIntegerSort()}),
+ CVC4ApiException&);
+}
+
+void SortBlack::testGetFunctionArity()
+{
+ Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
+ d_solver.getIntegerSort());
+ TS_ASSERT_THROWS_NOTHING(funSort.getFunctionArity());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getFunctionArity(), CVC4ApiException&);
+}
+
+void SortBlack::testGetFunctionDomainSorts()
+{
+ Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
+ d_solver.getIntegerSort());
+ TS_ASSERT_THROWS_NOTHING(funSort.getFunctionDomainSorts());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getFunctionDomainSorts(), CVC4ApiException&);
+}
+
+void SortBlack::testGetFunctionCodomainSort()
+{
+ Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
+ d_solver.getIntegerSort());
+ TS_ASSERT_THROWS_NOTHING(funSort.getFunctionCodomainSort());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getFunctionCodomainSort(), CVC4ApiException&);
+}
+
+void SortBlack::testGetArrayIndexSort()
+{
+ Sort elementSort = d_solver.mkBitVectorSort(32);
+ Sort indexSort = d_solver.mkBitVectorSort(32);
+ Sort arraySort = d_solver.mkArraySort(indexSort, elementSort);
+ TS_ASSERT_THROWS_NOTHING(arraySort.getArrayIndexSort());
+ TS_ASSERT_THROWS(indexSort.getArrayIndexSort(), CVC4ApiException&);
+}
+
+void SortBlack::testGetArrayElementSort()
+{
+ Sort elementSort = d_solver.mkBitVectorSort(32);
+ Sort indexSort = d_solver.mkBitVectorSort(32);
+ Sort arraySort = d_solver.mkArraySort(indexSort, elementSort);
+ TS_ASSERT_THROWS_NOTHING(arraySort.getArrayElementSort());
+ TS_ASSERT_THROWS(indexSort.getArrayElementSort(), CVC4ApiException&);
+}
+
+void SortBlack::testGetSetElementSort()
+{
+ Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort());
+ TS_ASSERT_THROWS_NOTHING(setSort.getSetElementSort());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getSetElementSort(), CVC4ApiException&);
+}
+
+void SortBlack::testGetUninterpretedSortName()
+{
+ Sort uSort = d_solver.mkUninterpretedSort("u");
+ TS_ASSERT_THROWS_NOTHING(uSort.getUninterpretedSortName());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getUninterpretedSortName(), CVC4ApiException&);
+}
+
+void SortBlack::testIsUninterpretedSortParameterized()
+{
+ Sort uSort = d_solver.mkUninterpretedSort("u");
+ TS_ASSERT_THROWS_NOTHING(uSort.isUninterpretedSortParameterized());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.isUninterpretedSortParameterized(),
+ CVC4ApiException&);
+}
+
+void SortBlack::testGetUninterpretedSortParamSorts()
+{
+ Sort uSort = d_solver.mkUninterpretedSort("u");
+ TS_ASSERT_THROWS_NOTHING(uSort.getUninterpretedSortParamSorts());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getUninterpretedSortParamSorts(), CVC4ApiException&);
+}
+
+void SortBlack::testGetUninterpretedSortConstructorName()
+{
+ Sort sSort = d_solver.mkSortConstructorSort("s", 2);
+ TS_ASSERT_THROWS_NOTHING(sSort.getSortConstructorName());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getSortConstructorName(), CVC4ApiException&);
+}
+
+void SortBlack::testGetUninterpretedSortConstructorArity()
+{
+ Sort sSort = d_solver.mkSortConstructorSort("s", 2);
+ TS_ASSERT_THROWS_NOTHING(sSort.getSortConstructorArity());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getSortConstructorArity(), CVC4ApiException&);
+}
+
+void SortBlack::testGetBVSize()
+{
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS_NOTHING(bvSort.getBVSize());
+ Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort());
+ TS_ASSERT_THROWS(setSort.getBVSize(), CVC4ApiException&);
+}
+
+void SortBlack::testGetFPExponentSize()
+{
+ Sort fpSort = d_solver.mkFloatingPointSort(4, 8);
+ TS_ASSERT_THROWS_NOTHING(fpSort.getFPExponentSize());
+ Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort());
+ TS_ASSERT_THROWS(setSort.getFPExponentSize(), CVC4ApiException&);
+}
+
+void SortBlack::testGetFPSignificandSize()
+{
+ Sort fpSort = d_solver.mkFloatingPointSort(4, 8);
+ TS_ASSERT_THROWS_NOTHING(fpSort.getFPSignificandSize());
+ Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort());
+ TS_ASSERT_THROWS(setSort.getFPSignificandSize(), CVC4ApiException&);
+}
+
+void SortBlack::testGetDatatypeParamSorts()
+{
+ // create parametric datatype, check should not fail
+ Sort sort = d_solver.mkParamSort("T");
+ DatatypeDecl paramDtypeSpec("paramlist", sort);
+ DatatypeConstructorDecl paramCons("cons");
+ DatatypeConstructorDecl paramNil("nil");
+ DatatypeSelectorDecl paramHead("head", sort);
+ paramCons.addSelector(paramHead);
+ paramDtypeSpec.addConstructor(paramCons);
+ paramDtypeSpec.addConstructor(paramNil);
+ Sort paramDtypeSort = d_solver.mkDatatypeSort(paramDtypeSpec);
+ TS_ASSERT_THROWS_NOTHING(paramDtypeSort.getDatatypeParamSorts());
+ // create non-parametric datatype sort, check should fail
+ DatatypeDecl dtypeSpec("list");
+ DatatypeConstructorDecl cons("cons");
+ DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
+ cons.addSelector(head);
+ dtypeSpec.addConstructor(cons);
+ DatatypeConstructorDecl nil("nil");
+ dtypeSpec.addConstructor(nil);
+ Sort dtypeSort = d_solver.mkDatatypeSort(dtypeSpec);
+ TS_ASSERT_THROWS(dtypeSort.getDatatypeParamSorts(), CVC4ApiException&);
+}
+
+void SortBlack::testGetDatatypeArity()
+{
+ // create datatype sort, check should not fail
+ DatatypeDecl dtypeSpec("list");
+ DatatypeConstructorDecl cons("cons");
+ DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
+ cons.addSelector(head);
+ dtypeSpec.addConstructor(cons);
+ DatatypeConstructorDecl nil("nil");
+ dtypeSpec.addConstructor(nil);
+ Sort dtypeSort = d_solver.mkDatatypeSort(dtypeSpec);
+ TS_ASSERT_THROWS_NOTHING(dtypeSort.getDatatypeArity());
+ // create bv sort, check should fail
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getDatatypeArity(), CVC4ApiException&);
+}
+
+void SortBlack::testGetTupleLength()
+{
+ Sort tupleSort = d_solver.mkTupleSort(
+ {d_solver.getIntegerSort(), d_solver.getIntegerSort()});
+ TS_ASSERT_THROWS_NOTHING(tupleSort.getTupleLength());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getTupleLength(), CVC4ApiException&);
+}
+
+void SortBlack::testGetTupleSorts()
+{
+ Sort tupleSort = d_solver.mkTupleSort(
+ {d_solver.getIntegerSort(), d_solver.getIntegerSort()});
+ TS_ASSERT_THROWS_NOTHING(tupleSort.getTupleSorts());
+ Sort bvSort = d_solver.mkBitVectorSort(32);
+ TS_ASSERT_THROWS(bvSort.getTupleSorts(), CVC4ApiException&);
+}
diff --git a/test/unit/api/term_black.h b/test/unit/api/term_black.h
new file mode 100644
index 000000000..c2ca1cb08
--- /dev/null
+++ b/test/unit/api/term_black.h
@@ -0,0 +1,37 @@
+/********************* */
+/*! \file term_black.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andres Noetzli
+ ** 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 Black box testing of the Term class
+ **/
+
+#include <cxxtest/TestSuite.h>
+
+#include "api/cvc4cpp.h"
+
+using namespace CVC4::api;
+
+class TermBlack : public CxxTest::TestSuite
+{
+ public:
+ void setUp() override {}
+ void tearDown() override {}
+
+ void testTermAssignment()
+ {
+ Term t1 = d_solver.mkReal(1);
+ Term t2 = t1;
+ t2 = d_solver.mkReal(2);
+ TS_ASSERT_EQUALS(t1, d_solver.mkReal(1));
+ }
+
+ private:
+ Solver d_solver;
+};
diff --git a/test/unit/theory/theory_strings_rewriter_white.h b/test/unit/theory/theory_strings_rewriter_white.h
index 87aef3704..42ac2cdd9 100644
--- a/test/unit/theory/theory_strings_rewriter_white.h
+++ b/test/unit/theory/theory_strings_rewriter_white.h
@@ -604,6 +604,18 @@ class TheoryStringsRewriterWhite : public CxxTest::TestSuite
b);
repl = d_nm->mkNode(kind::STRING_STRREPL, b, x, b);
sameNormalForm(repl_repl, repl);
+
+ // Different normal forms for:
+ //
+ // (str.replace "B" (str.replace "" x "A") "B")
+ //
+ // (str.replace "B" x "B")
+ repl_repl = d_nm->mkNode(kind::STRING_STRREPL,
+ b,
+ d_nm->mkNode(kind::STRING_STRREPL, empty, x, a),
+ b);
+ repl = d_nm->mkNode(kind::STRING_STRREPL, b, x, b);
+ differentNormalForms(repl_repl, repl);
}
void testRewriteContains()
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback