summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt35
-rw-r--r--src/api/cvc4cpp.cpp1037
-rw-r--r--src/api/cvc4cpp.h152
-rw-r--r--src/api/python/cvc4.pxd20
-rw-r--r--src/api/python/cvc4.pxi155
-rw-r--r--src/bindings/java/CMakeLists.txt2
-rw-r--r--src/cvc4.i1
-rw-r--r--src/expr/CMakeLists.txt6
-rw-r--r--src/expr/expr.i1
-rw-r--r--src/expr/expr_manager.i1
-rw-r--r--src/expr/expr_sequence.cpp98
-rw-r--r--src/expr/expr_sequence.h76
-rw-r--r--src/expr/expr_sequence.i18
-rw-r--r--src/expr/node_manager.cpp33
-rw-r--r--src/expr/node_manager.h19
-rw-r--r--src/expr/proof_rule.cpp61
-rw-r--r--src/expr/proof_rule.h402
-rw-r--r--src/expr/proof_step_buffer.cpp109
-rw-r--r--src/expr/proof_step_buffer.h96
-rw-r--r--src/expr/sequence.cpp12
-rw-r--r--src/expr/sequence.h4
-rw-r--r--src/expr/type.cpp16
-rw-r--r--src/expr/type.h25
-rw-r--r--src/expr/type_node.cpp12
-rw-r--r--src/expr/type_node.h10
-rw-r--r--src/options/quantifiers_options.toml3
-rw-r--r--src/options/smt_options.toml2
-rw-r--r--src/options/strings_options.toml9
-rw-r--r--src/parser/cvc/Cvc.g38
-rw-r--r--src/parser/parser.cpp55
-rw-r--r--src/parser/parser.h12
-rw-r--r--src/parser/smt2/Smt2.g33
-rw-r--r--src/parser/smt2/smt2.cpp19
-rw-r--r--src/parser/smt2/smt2.h7
-rw-r--r--src/parser/tptp/Tptp.g4
-rw-r--r--src/preprocessing/passes/unconstrained_simplifier.cpp9
-rw-r--r--src/preprocessing/passes/unconstrained_simplifier.h6
-rw-r--r--src/smt/set_defaults.cpp31
-rw-r--r--src/smt/smt_engine.cpp102
-rw-r--r--src/smt/smt_engine.h48
-rw-r--r--src/theory/arith/nl/nl_constraint.cpp (renamed from src/theory/arith/nl_constraint.cpp)4
-rw-r--r--src/theory/arith/nl/nl_constraint.h (renamed from src/theory/arith/nl_constraint.h)8
-rw-r--r--src/theory/arith/nl/nl_lemma_utils.cpp (renamed from src/theory/arith/nl_lemma_utils.cpp)6
-rw-r--r--src/theory/arith/nl/nl_lemma_utils.h (renamed from src/theory/arith/nl_lemma_utils.h)6
-rw-r--r--src/theory/arith/nl/nl_model.cpp (renamed from src/theory/arith/nl_model.cpp)14
-rw-r--r--src/theory/arith/nl/nl_model.h (renamed from src/theory/arith/nl_model.h)8
-rw-r--r--src/theory/arith/nl/nl_monomial.cpp (renamed from src/theory/arith/nl_monomial.cpp)6
-rw-r--r--src/theory/arith/nl/nl_monomial.h (renamed from src/theory/arith/nl_monomial.h)6
-rw-r--r--src/theory/arith/nl/nl_solver.cpp (renamed from src/theory/arith/nl_solver.cpp)4
-rw-r--r--src/theory/arith/nl/nl_solver.h (renamed from src/theory/arith/nl_solver.h)10
-rw-r--r--src/theory/arith/nl/nonlinear_extension.cpp (renamed from src/theory/arith/nonlinear_extension.cpp)92
-rw-r--r--src/theory/arith/nl/nonlinear_extension.h (renamed from src/theory/arith/nonlinear_extension.h)28
-rw-r--r--src/theory/arith/nl/transcendental_solver.cpp (renamed from src/theory/arith/transcendental_solver.cpp)4
-rw-r--r--src/theory/arith/nl/transcendental_solver.h (renamed from src/theory/arith/transcendental_solver.h)10
-rw-r--r--src/theory/arith/theory_arith_private.cpp26
-rw-r--r--src/theory/arith/theory_arith_private.h4
-rw-r--r--src/theory/booleans/proof_checker.cpp568
-rw-r--r--src/theory/booleans/proof_checker.h49
-rw-r--r--src/theory/builtin/proof_checker.cpp359
-rw-r--r--src/theory/builtin/proof_checker.h150
-rw-r--r--src/theory/datatypes/theory_datatypes_utils.cpp218
-rw-r--r--src/theory/datatypes/theory_datatypes_utils.h40
-rw-r--r--src/theory/quantifiers/cegqi/ceg_bv_instantiator.cpp14
-rw-r--r--src/theory/quantifiers/cegqi/ceg_bv_instantiator.h28
-rw-r--r--src/theory/quantifiers/cegqi/ceg_instantiator.cpp73
-rw-r--r--src/theory/quantifiers/cegqi/ceg_instantiator.h34
-rw-r--r--src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp17
-rw-r--r--src/theory/quantifiers/extended_rewrite.cpp5
-rw-r--r--src/theory/quantifiers/fmf/full_model_check.cpp295
-rw-r--r--src/theory/quantifiers/fmf/full_model_check.h19
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.cpp228
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.h21
-rw-r--r--src/theory/quantifiers/sygus/sygus_abduct.cpp182
-rw-r--r--src/theory/strings/kinds26
-rw-r--r--src/theory/strings/rewrites.cpp1
-rw-r--r--src/theory/strings/rewrites.h3
-rw-r--r--src/theory/strings/sequences_rewriter.cpp23
-rw-r--r--src/theory/strings/sequences_rewriter.h6
-rw-r--r--src/theory/strings/term_registry.cpp15
-rw-r--r--src/theory/strings/theory_strings_preprocess.cpp284
-rw-r--r--src/theory/strings/theory_strings_preprocess.h44
-rw-r--r--src/theory/strings/theory_strings_type_rules.h50
-rw-r--r--src/theory/strings/type_enumerator.cpp83
-rw-r--r--src/theory/strings/type_enumerator.h43
-rw-r--r--src/theory/strings/word.cpp138
-rw-r--r--src/theory/strings/word.h4
-rw-r--r--src/theory/theory_engine.cpp9
-rw-r--r--src/theory/theory_engine.h2
-rw-r--r--src/theory/uf/proof_checker.cpp172
-rw-r--r--src/theory/uf/proof_checker.h49
-rw-r--r--src/util/floatingpoint.cpp3
91 files changed, 4913 insertions, 1357 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ff11897e9..44b5dfeaf 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -300,18 +300,20 @@ libcvc4_add_sources(
theory/arith/linear_equality.h
theory/arith/matrix.cpp
theory/arith/matrix.h
- theory/arith/nl_constraint.cpp
- theory/arith/nl_constraint.h
- theory/arith/nl_lemma_utils.cpp
- theory/arith/nl_lemma_utils.h
- theory/arith/nl_model.cpp
- theory/arith/nl_model.h
- theory/arith/nl_monomial.cpp
- theory/arith/nl_monomial.h
- theory/arith/nl_solver.cpp
- theory/arith/nl_solver.h
- theory/arith/nonlinear_extension.cpp
- theory/arith/nonlinear_extension.h
+ theory/arith/nl/nl_constraint.cpp
+ theory/arith/nl/nl_constraint.h
+ theory/arith/nl/nl_lemma_utils.cpp
+ theory/arith/nl/nl_lemma_utils.h
+ theory/arith/nl/nl_model.cpp
+ theory/arith/nl/nl_model.h
+ theory/arith/nl/nl_monomial.cpp
+ theory/arith/nl/nl_monomial.h
+ theory/arith/nl/nl_solver.cpp
+ theory/arith/nl/nl_solver.h
+ theory/arith/nl/nonlinear_extension.cpp
+ theory/arith/nl/nonlinear_extension.h
+ theory/arith/nl/transcendental_solver.cpp
+ theory/arith/nl/transcendental_solver.h
theory/arith/normal_form.cpp
theory/arith/normal_form.h
theory/arith/partial_model.cpp
@@ -332,8 +334,6 @@ libcvc4_add_sources(
theory/arith/theory_arith_private.h
theory/arith/theory_arith_private_forward.h
theory/arith/theory_arith_type_rules.h
- theory/arith/transcendental_solver.cpp
- theory/arith/transcendental_solver.h
theory/arith/type_enumerator.h
theory/arrays/array_info.cpp
theory/arrays/array_info.h
@@ -355,6 +355,8 @@ libcvc4_add_sources(
theory/atom_requests.h
theory/booleans/circuit_propagator.cpp
theory/booleans/circuit_propagator.h
+ theory/booleans/proof_checker.cpp
+ theory/booleans/proof_checker.h
theory/booleans/theory_bool.cpp
theory/booleans/theory_bool.h
theory/booleans/theory_bool_rewriter.cpp
@@ -366,6 +368,8 @@ libcvc4_add_sources(
theory/builtin/theory_builtin_rewriter.cpp
theory/builtin/theory_builtin_rewriter.h
theory/builtin/theory_builtin_type_rules.h
+ theory/builtin/proof_checker.cpp
+ theory/builtin/proof_checker.h
theory/builtin/type_enumerator.cpp
theory/builtin/type_enumerator.h
theory/bv/abstraction.cpp
@@ -750,6 +754,8 @@ libcvc4_add_sources(
theory/uf/equality_engine.cpp
theory/uf/equality_engine.h
theory/uf/equality_engine_types.h
+ theory/uf/proof_checker.cpp
+ theory/uf/proof_checker.h
theory/uf/ho_extension.cpp
theory/uf/ho_extension.h
theory/uf/symmetry_breaker.cpp
@@ -923,6 +929,7 @@ install(FILES
expr/datatype.h
expr/emptyset.h
expr/expr_iomanip.h
+ expr/expr_sequence.h
expr/record.h
expr/symbol_table.h
expr/type.h
diff --git a/src/api/cvc4cpp.cpp b/src/api/cvc4cpp.cpp
index 1ea421c4b..734fcddae 100644
--- a/src/api/cvc4cpp.cpp
+++ b/src/api/cvc4cpp.cpp
@@ -724,12 +724,12 @@ class CVC4ApiExceptionStream
& CVC4ApiExceptionStream().ostream() \
<< "Invalid size of argument '" << #arg << "', expected "
-#define CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(cond, what, arg, idx) \
- CVC4_PREDICT_TRUE(cond) \
- ? (void)0 \
- : OstreamVoider() \
- & CVC4ApiExceptionStream().ostream() \
- << "Invalid " << what << " '" << arg << "' at index" << idx \
+#define CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(cond, what, arg, idx) \
+ CVC4_PREDICT_TRUE(cond) \
+ ? (void)0 \
+ : OstreamVoider() \
+ & CVC4ApiExceptionStream().ostream() \
+ << "Invalid " << what << " '" << arg << "' at index " << idx \
<< ", expected "
#define CVC4_API_SOLVER_TRY_CATCH_BEGIN \
@@ -739,6 +739,19 @@ class CVC4ApiExceptionStream
} \
catch (const CVC4::Exception& e) { throw CVC4ApiException(e.getMessage()); } \
catch (const std::invalid_argument& e) { throw CVC4ApiException(e.what()); }
+
+#define CVC4_API_SOLVER_CHECK_SORT(sort) \
+ CVC4_API_CHECK(this == sort.d_solver) \
+ << "Given sort is not associated with this solver";
+
+#define CVC4_API_SOLVER_CHECK_TERM(term) \
+ CVC4_API_CHECK(this == term.d_solver) \
+ << "Given term is not associated with this solver";
+
+#define CVC4_API_SOLVER_CHECK_OP(op) \
+ CVC4_API_CHECK(this == op.d_solver) \
+ << "Given operator is not associated with this solver";
+
} // namespace
/* -------------------------------------------------------------------------- */
@@ -823,9 +836,12 @@ std::ostream& operator<<(std::ostream& out, const Result& r)
/* Sort */
/* -------------------------------------------------------------------------- */
-Sort::Sort(const CVC4::Type& t) : d_type(new CVC4::Type(t)) {}
+Sort::Sort(const Solver* slv, const CVC4::Type& t)
+ : d_solver(slv), d_type(new CVC4::Type(t))
+{
+}
-Sort::Sort() : d_type(new CVC4::Type()) {}
+Sort::Sort() : d_solver(nullptr), d_type(new CVC4::Type()) {}
Sort::~Sort() {}
@@ -909,7 +925,7 @@ bool Sort::isComparableTo(Sort s) const
Datatype Sort::getDatatype() const
{
CVC4_API_CHECK(isDatatype()) << "Expected datatype sort.";
- return DatatypeType(*d_type).getDatatype();
+ return Datatype(d_solver, DatatypeType(*d_type).getDatatype());
}
Sort Sort::instantiate(const std::vector<Sort>& params) const
@@ -923,10 +939,10 @@ Sort Sort::instantiate(const std::vector<Sort>& params) const
}
if (d_type->isDatatype())
{
- return DatatypeType(*d_type).instantiate(tparams);
+ return Sort(d_solver, DatatypeType(*d_type).instantiate(tparams));
}
Assert(d_type->isSortConstructor());
- return SortConstructorType(*d_type).instantiate(tparams);
+ return Sort(d_solver, SortConstructorType(*d_type).instantiate(tparams));
}
std::string Sort::toString() const { return d_type->toString(); }
@@ -947,13 +963,13 @@ std::vector<Sort> Sort::getConstructorDomainSorts() const
{
CVC4_API_CHECK(isConstructor()) << "Not a function sort.";
std::vector<CVC4::Type> types = ConstructorType(*d_type).getArgTypes();
- return typeVectorToSorts(types);
+ return typeVectorToSorts(d_solver, types);
}
Sort Sort::getConstructorCodomainSort() const
{
CVC4_API_CHECK(isConstructor()) << "Not a function sort.";
- return ConstructorType(*d_type).getRangeType();
+ return Sort(d_solver, ConstructorType(*d_type).getRangeType());
}
/* Function sort ------------------------------------------------------- */
@@ -968,13 +984,13 @@ std::vector<Sort> Sort::getFunctionDomainSorts() const
{
CVC4_API_CHECK(isFunction()) << "Not a function sort.";
std::vector<CVC4::Type> types = FunctionType(*d_type).getArgTypes();
- return typeVectorToSorts(types);
+ return typeVectorToSorts(d_solver, types);
}
Sort Sort::getFunctionCodomainSort() const
{
CVC4_API_CHECK(isFunction()) << "Not a function sort.";
- return FunctionType(*d_type).getRangeType();
+ return Sort(d_solver, FunctionType(*d_type).getRangeType());
}
/* Array sort ---------------------------------------------------------- */
@@ -982,13 +998,13 @@ Sort Sort::getFunctionCodomainSort() const
Sort Sort::getArrayIndexSort() const
{
CVC4_API_CHECK(isArray()) << "Not an array sort.";
- return ArrayType(*d_type).getIndexType();
+ return Sort(d_solver, ArrayType(*d_type).getIndexType());
}
Sort Sort::getArrayElementSort() const
{
CVC4_API_CHECK(isArray()) << "Not an array sort.";
- return ArrayType(*d_type).getConstituentType();
+ return Sort(d_solver, ArrayType(*d_type).getConstituentType());
}
/* Set sort ------------------------------------------------------------ */
@@ -996,7 +1012,7 @@ Sort Sort::getArrayElementSort() const
Sort Sort::getSetElementSort() const
{
CVC4_API_CHECK(isSet()) << "Not a set sort.";
- return SetType(*d_type).getElementType();
+ return Sort(d_solver, SetType(*d_type).getElementType());
}
/* Uninterpreted sort -------------------------------------------------- */
@@ -1017,7 +1033,7 @@ std::vector<Sort> Sort::getUninterpretedSortParamSorts() const
{
CVC4_API_CHECK(isUninterpretedSort()) << "Not an uninterpreted sort.";
std::vector<CVC4::Type> types = SortType(*d_type).getParamTypes();
- return typeVectorToSorts(types);
+ return typeVectorToSorts(d_solver, types);
}
/* Sort constructor sort ----------------------------------------------- */
@@ -1062,7 +1078,7 @@ std::vector<Sort> Sort::getDatatypeParamSorts() const
{
CVC4_API_CHECK(isParametricDatatype()) << "Not a parametric datatype sort.";
std::vector<CVC4::Type> types = DatatypeType(*d_type).getParamTypes();
- return typeVectorToSorts(types);
+ return typeVectorToSorts(d_solver, types);
}
size_t Sort::getDatatypeArity() const
@@ -1083,7 +1099,7 @@ std::vector<Sort> Sort::getTupleSorts() const
{
CVC4_API_CHECK(isTuple()) << "Not a tuple sort.";
std::vector<CVC4::Type> types = DatatypeType(*d_type).getTupleTypes();
- return typeVectorToSorts(types);
+ return typeVectorToSorts(d_solver, types);
}
/* --------------------------------------------------------------------- */
@@ -1105,9 +1121,13 @@ size_t SortHashFunction::operator()(const Sort& s) const
Op::Op() : d_kind(NULL_EXPR), d_expr(new CVC4::Expr()) {}
-Op::Op(const Kind k) : d_kind(k), d_expr(new CVC4::Expr()) {}
+Op::Op(const Solver* slv, const Kind k)
+ : d_solver(slv), d_kind(k), d_expr(new CVC4::Expr())
+{
+}
-Op::Op(const Kind k, const CVC4::Expr& e) : d_kind(k), d_expr(new CVC4::Expr(e))
+Op::Op(const Solver* slv, const Kind k, const CVC4::Expr& e)
+ : d_solver(slv), d_kind(k), d_expr(new CVC4::Expr(e))
{
}
@@ -1323,19 +1343,20 @@ size_t OpHashFunction::operator()(const Op& t) const
/* Term */
/* -------------------------------------------------------------------------- */
-Term::Term() : d_expr(new CVC4::Expr()) {}
+Term::Term() : d_solver(nullptr), d_expr(new CVC4::Expr()) {}
-Term::Term(const CVC4::Expr& e) : d_expr(new CVC4::Expr(e)) {}
+Term::Term(const Solver* slv, const CVC4::Expr& e)
+ : d_solver(slv), d_expr(new CVC4::Expr(e))
+{
+}
Term::~Term() {}
-/* Helpers */
-/* -------------------------------------------------------------------------- */
-
-/* Split out to avoid nested API calls (problematic with API tracing). */
-/* .......................................................................... */
-
-bool Term::isNullHelper() const { return d_expr->isNull(); }
+bool Term::isNullHelper() const
+{
+ /* Split out to avoid nested API calls (problematic with API tracing). */
+ return d_expr->isNull();
+}
bool Term::operator==(const Term& t) const { return *d_expr == *t.d_expr; }
@@ -1371,12 +1392,12 @@ Term Term::operator[](size_t index) const
if (index == 0)
{
// return the operator
- return api::Term(d_expr->getOperator());
+ return Term(d_solver, d_expr->getOperator());
}
// otherwise we are looking up child at (index-1)
index--;
}
- return api::Term((*d_expr)[index]);
+ return Term(d_solver, (*d_expr)[index]);
}
uint64_t Term::getId() const
@@ -1394,7 +1415,7 @@ Kind Term::getKind() const
Sort Term::getSort() const
{
CVC4_API_CHECK_NOT_NULL;
- return Sort(d_expr->getType());
+ return Sort(d_solver, d_expr->getType());
}
Term Term::substitute(Term e, Term replacement) const
@@ -1406,7 +1427,7 @@ Term Term::substitute(Term e, Term replacement) const
<< "Expected non-null term as replacement in substitute";
CVC4_API_CHECK(e.getSort().isComparableTo(replacement.getSort()))
<< "Expecting terms of comparable sort in substitute";
- return api::Term(d_expr->substitute(e.getExpr(), replacement.getExpr()));
+ return Term(d_solver, d_expr->substitute(e.getExpr(), replacement.getExpr()));
}
Term Term::substitute(const std::vector<Term> es,
@@ -1424,8 +1445,9 @@ Term Term::substitute(const std::vector<Term> es,
CVC4_API_CHECK(es[i].getSort().isComparableTo(replacements[i].getSort()))
<< "Expecting terms of comparable sort in substitute";
}
- return api::Term(d_expr->substitute(termVectorToExprs(es),
- termVectorToExprs(replacements)));
+ return Term(d_solver,
+ d_expr->substitute(termVectorToExprs(es),
+ termVectorToExprs(replacements)));
}
bool Term::hasOp() const
@@ -1447,18 +1469,18 @@ Op Term::getOp() const
// is one of the APPLY_* kinds
if (isApplyKind(d_expr->getKind()))
{
- return Op(intToExtKind(d_expr->getKind()));
+ return Op(d_solver, intToExtKind(d_expr->getKind()));
}
else if (d_expr->isParameterized())
{
// it's an indexed operator
// so we should return the indexed op
CVC4::Expr op = d_expr->getOperator();
- return Op(intToExtKind(d_expr->getKind()), op);
+ return Op(d_solver, intToExtKind(d_expr->getKind()), op);
}
else
{
- return Op(intToExtKind(d_expr->getKind()));
+ return Op(d_solver, intToExtKind(d_expr->getKind()));
}
}
@@ -1475,9 +1497,9 @@ Term Term::notTerm() const
CVC4_API_CHECK_NOT_NULL;
try
{
- Term res = d_expr->notExpr();
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ Expr res = d_expr->notExpr();
+ (void)res.getType(true); /* kick off type checking */
+ return Term(d_solver, res);
}
catch (const CVC4::TypeCheckingException& e)
{
@@ -1491,9 +1513,9 @@ Term Term::andTerm(const Term& t) const
CVC4_API_ARG_CHECK_NOT_NULL(t);
try
{
- Term res = d_expr->andExpr(*t.d_expr);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ Expr res = d_expr->andExpr(*t.d_expr);
+ (void)res.getType(true); /* kick off type checking */
+ return Term(d_solver, res);
}
catch (const CVC4::TypeCheckingException& e)
{
@@ -1507,9 +1529,9 @@ Term Term::orTerm(const Term& t) const
CVC4_API_ARG_CHECK_NOT_NULL(t);
try
{
- Term res = d_expr->orExpr(*t.d_expr);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ Expr res = d_expr->orExpr(*t.d_expr);
+ (void)res.getType(true); /* kick off type checking */
+ return Term(d_solver, res);
}
catch (const CVC4::TypeCheckingException& e)
{
@@ -1523,9 +1545,9 @@ Term Term::xorTerm(const Term& t) const
CVC4_API_ARG_CHECK_NOT_NULL(t);
try
{
- Term res = d_expr->xorExpr(*t.d_expr);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ Expr res = d_expr->xorExpr(*t.d_expr);
+ (void)res.getType(true); /* kick off type checking */
+ return Term(d_solver, res);
}
catch (const CVC4::TypeCheckingException& e)
{
@@ -1539,9 +1561,9 @@ Term Term::eqTerm(const Term& t) const
CVC4_API_ARG_CHECK_NOT_NULL(t);
try
{
- Term res = d_expr->eqExpr(*t.d_expr);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ Expr res = d_expr->eqExpr(*t.d_expr);
+ (void)res.getType(true); /* kick off type checking */
+ return Term(d_solver, res);
}
catch (const CVC4::TypeCheckingException& e)
{
@@ -1555,9 +1577,9 @@ Term Term::impTerm(const Term& t) const
CVC4_API_ARG_CHECK_NOT_NULL(t);
try
{
- Term res = d_expr->impExpr(*t.d_expr);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ Expr res = d_expr->impExpr(*t.d_expr);
+ (void)res.getType(true); /* kick off type checking */
+ return Term(d_solver, res);
}
catch (const CVC4::TypeCheckingException& e)
{
@@ -1572,9 +1594,9 @@ Term Term::iteTerm(const Term& then_t, const Term& else_t) const
CVC4_API_ARG_CHECK_NOT_NULL(else_t);
try
{
- Term res = d_expr->iteExpr(*then_t.d_expr, *else_t.d_expr);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ Expr res = d_expr->iteExpr(*then_t.d_expr, *else_t.d_expr);
+ (void)res.getType(true); /* kick off type checking */
+ return Term(d_solver, res);
}
catch (const CVC4::TypeCheckingException& e)
{
@@ -1584,11 +1606,15 @@ Term Term::iteTerm(const Term& then_t, const Term& else_t) const
std::string Term::toString() const { return d_expr->toString(); }
-Term::const_iterator::const_iterator() : d_orig_expr(nullptr), d_pos(0) {}
+Term::const_iterator::const_iterator()
+ : d_solver(nullptr), d_orig_expr(nullptr), d_pos(0)
+{
+}
-Term::const_iterator::const_iterator(const std::shared_ptr<CVC4::Expr>& e,
+Term::const_iterator::const_iterator(const Solver* slv,
+ const std::shared_ptr<CVC4::Expr>& e,
uint32_t p)
- : d_orig_expr(e), d_pos(p)
+ : d_solver(slv), d_orig_expr(e), d_pos(p)
{
}
@@ -1597,6 +1623,7 @@ Term::const_iterator::const_iterator(const const_iterator& it)
{
if (it.d_orig_expr != nullptr)
{
+ d_solver = it.d_solver;
d_orig_expr = it.d_orig_expr;
d_pos = it.d_pos;
}
@@ -1604,6 +1631,7 @@ Term::const_iterator::const_iterator(const const_iterator& it)
Term::const_iterator& Term::const_iterator::operator=(const const_iterator& it)
{
+ d_solver = it.d_solver;
d_orig_expr = it.d_orig_expr;
d_pos = it.d_pos;
return *this;
@@ -1615,7 +1643,8 @@ bool Term::const_iterator::operator==(const const_iterator& it) const
{
return false;
}
- return (*d_orig_expr == *it.d_orig_expr) && (d_pos == it.d_pos);
+ return (d_solver == it.d_solver && *d_orig_expr == *it.d_orig_expr)
+ && (d_pos == it.d_pos);
}
bool Term::const_iterator::operator!=(const const_iterator& it) const
@@ -1647,7 +1676,7 @@ Term Term::const_iterator::operator*() const
if (!d_pos && extra_child)
{
- return Term(d_orig_expr->getOperator());
+ return Term(d_solver, d_orig_expr->getOperator());
}
else
{
@@ -1658,13 +1687,13 @@ Term Term::const_iterator::operator*() const
--idx;
}
Assert(idx >= 0);
- return Term((*d_orig_expr)[idx]);
+ return Term(d_solver, (*d_orig_expr)[idx]);
}
}
Term::const_iterator Term::begin() const
{
- return Term::const_iterator(d_expr, 0);
+ return Term::const_iterator(d_solver, d_expr, 0);
}
Term::const_iterator Term::end() const
@@ -1681,7 +1710,7 @@ Term::const_iterator Term::end() const
// one more child if this is a UF application (count the UF as a child)
++endpos;
}
- return Term::const_iterator(d_expr, endpos);
+ return Term::const_iterator(d_solver, d_expr, endpos);
}
// !!! This is only temporarily available until the parser is fully migrated
@@ -1741,8 +1770,14 @@ size_t TermHashFunction::operator()(const Term& t) const
/* DatatypeConstructorDecl -------------------------------------------------- */
-DatatypeConstructorDecl::DatatypeConstructorDecl(const std::string& name)
- : d_ctor(new CVC4::DatatypeConstructor(name))
+DatatypeConstructorDecl::DatatypeConstructorDecl()
+ : d_solver(nullptr), d_ctor(nullptr)
+{
+}
+
+DatatypeConstructorDecl::DatatypeConstructorDecl(const Solver* slv,
+ const std::string& name)
+ : d_solver(slv), d_ctor(new CVC4::DatatypeConstructor(name))
{
}
@@ -1789,28 +1824,33 @@ std::ostream& operator<<(std::ostream& out,
/* DatatypeDecl ------------------------------------------------------------- */
-DatatypeDecl::DatatypeDecl(const Solver* s,
+DatatypeDecl::DatatypeDecl() : d_solver(nullptr), d_dtype(nullptr) {}
+
+DatatypeDecl::DatatypeDecl(const Solver* slv,
const std::string& name,
bool isCoDatatype)
- : d_dtype(new CVC4::Datatype(s->getExprManager(), name, isCoDatatype))
+ : d_solver(slv),
+ d_dtype(new CVC4::Datatype(slv->getExprManager(), name, isCoDatatype))
{
}
-DatatypeDecl::DatatypeDecl(const Solver* s,
+DatatypeDecl::DatatypeDecl(const Solver* slv,
const std::string& name,
Sort param,
bool isCoDatatype)
- : d_dtype(new CVC4::Datatype(s->getExprManager(),
+ : d_solver(slv),
+ d_dtype(new CVC4::Datatype(slv->getExprManager(),
name,
std::vector<Type>{*param.d_type},
isCoDatatype))
{
}
-DatatypeDecl::DatatypeDecl(const Solver* s,
+DatatypeDecl::DatatypeDecl(const Solver* slv,
const std::string& name,
const std::vector<Sort>& params,
bool isCoDatatype)
+ : d_solver(slv)
{
std::vector<Type> tparams;
for (const Sort& p : params)
@@ -1818,13 +1858,11 @@ DatatypeDecl::DatatypeDecl(const Solver* s,
tparams.push_back(*p.d_type);
}
d_dtype = std::shared_ptr<CVC4::Datatype>(
- new CVC4::Datatype(s->getExprManager(), name, tparams, isCoDatatype));
+ new CVC4::Datatype(slv->getExprManager(), name, tparams, isCoDatatype));
}
bool DatatypeDecl::isNullHelper() const { return !d_dtype; }
-DatatypeDecl::DatatypeDecl() {}
-
DatatypeDecl::~DatatypeDecl() {}
void DatatypeDecl::addConstructor(const DatatypeConstructorDecl& ctor)
@@ -1875,8 +1913,9 @@ std::ostream& operator<<(std::ostream& out, const DatatypeDecl& dtdecl)
DatatypeSelector::DatatypeSelector() { d_stor = nullptr; }
-DatatypeSelector::DatatypeSelector(const CVC4::DatatypeConstructorArg& stor)
- : d_stor(new CVC4::DatatypeConstructorArg(stor))
+DatatypeSelector::DatatypeSelector(const Solver* slv,
+ const CVC4::DatatypeConstructorArg& stor)
+ : d_solver(slv), d_stor(new CVC4::DatatypeConstructorArg(stor))
{
CVC4_API_CHECK(d_stor->isResolved()) << "Expected resolved datatype selector";
}
@@ -1887,13 +1926,13 @@ std::string DatatypeSelector::getName() const { return d_stor->getName(); }
Term DatatypeSelector::getSelectorTerm() const
{
- Term sel = d_stor->getSelector();
+ Term sel = Term(d_solver, d_stor->getSelector());
return sel;
}
Sort DatatypeSelector::getRangeSort() const
{
- return Sort(d_stor->getRangeType());
+ return Sort(d_solver, d_stor->getRangeType());
}
std::string DatatypeSelector::toString() const
@@ -1919,10 +1958,13 @@ std::ostream& operator<<(std::ostream& out, const DatatypeSelector& stor)
/* DatatypeConstructor ------------------------------------------------------ */
-DatatypeConstructor::DatatypeConstructor() { d_ctor = nullptr; }
+DatatypeConstructor::DatatypeConstructor() : d_solver(nullptr), d_ctor(nullptr)
+{
+}
-DatatypeConstructor::DatatypeConstructor(const CVC4::DatatypeConstructor& ctor)
- : d_ctor(new CVC4::DatatypeConstructor(ctor))
+DatatypeConstructor::DatatypeConstructor(const Solver* slv,
+ const CVC4::DatatypeConstructor& ctor)
+ : d_solver(slv), d_ctor(new CVC4::DatatypeConstructor(ctor))
{
CVC4_API_CHECK(d_ctor->isResolved())
<< "Expected resolved datatype constructor";
@@ -1934,13 +1976,13 @@ std::string DatatypeConstructor::getName() const { return d_ctor->getName(); }
Term DatatypeConstructor::getConstructorTerm() const
{
- Term ctor = d_ctor->getConstructor();
+ Term ctor = Term(d_solver, d_ctor->getConstructor());
return ctor;
}
Term DatatypeConstructor::getTesterTerm() const
{
- Term tst = d_ctor->getTester();
+ Term tst = Term(d_solver, d_ctor->getTester());
return tst;
}
@@ -1951,7 +1993,7 @@ size_t DatatypeConstructor::getNumSelectors() const
DatatypeSelector DatatypeConstructor::operator[](size_t index) const
{
- return (*d_ctor)[index];
+ return DatatypeSelector(d_solver, (*d_ctor)[index]);
}
DatatypeSelector DatatypeConstructor::operator[](const std::string& name) const
@@ -1972,36 +2014,41 @@ Term DatatypeConstructor::getSelectorTerm(const std::string& name) const
DatatypeConstructor::const_iterator DatatypeConstructor::begin() const
{
- return DatatypeConstructor::const_iterator(*d_ctor, true);
+ return DatatypeConstructor::const_iterator(d_solver, *d_ctor, true);
}
DatatypeConstructor::const_iterator DatatypeConstructor::end() const
{
- return DatatypeConstructor::const_iterator(*d_ctor, false);
+ return DatatypeConstructor::const_iterator(d_solver, *d_ctor, false);
}
DatatypeConstructor::const_iterator::const_iterator(
- const CVC4::DatatypeConstructor& ctor, bool begin)
+ const Solver* slv, const CVC4::DatatypeConstructor& ctor, bool begin)
{
+ d_solver = slv;
d_int_stors = ctor.getArgs();
+
const std::vector<CVC4::DatatypeConstructorArg>* sels =
static_cast<const std::vector<CVC4::DatatypeConstructorArg>*>(
d_int_stors);
for (const auto& s : *sels)
{
/* Can not use emplace_back here since constructor is private. */
- d_stors.push_back(DatatypeSelector(s));
+ d_stors.push_back(DatatypeSelector(d_solver, s));
}
d_idx = begin ? 0 : sels->size();
}
-// Nullary constructor for Cython
-DatatypeConstructor::const_iterator::const_iterator() {}
+DatatypeConstructor::const_iterator::const_iterator()
+ : d_solver(nullptr), d_int_stors(nullptr), d_idx(0)
+{
+}
DatatypeConstructor::const_iterator&
DatatypeConstructor::const_iterator::operator=(
const DatatypeConstructor::const_iterator& it)
{
+ d_solver = it.d_solver;
d_int_stors = it.d_int_stors;
d_stors = it.d_stors;
d_idx = it.d_idx;
@@ -2076,7 +2123,7 @@ DatatypeSelector DatatypeConstructor::getSelectorForName(
}
CVC4_API_CHECK(foundSel) << "No selector " << name << " for constructor "
<< getName() << " exists";
- return (*d_ctor)[index];
+ return DatatypeSelector(d_solver, (*d_ctor)[index]);
}
std::ostream& operator<<(std::ostream& out, const DatatypeConstructor& ctor)
@@ -2087,21 +2134,20 @@ std::ostream& operator<<(std::ostream& out, const DatatypeConstructor& ctor)
/* Datatype ----------------------------------------------------------------- */
-Datatype::Datatype(const CVC4::Datatype& dtype)
- : d_dtype(new CVC4::Datatype(dtype))
+Datatype::Datatype(const Solver* slv, const CVC4::Datatype& dtype)
+ : d_solver(slv), d_dtype(new CVC4::Datatype(dtype))
{
CVC4_API_CHECK(d_dtype->isResolved()) << "Expected resolved datatype";
}
-// Nullary constructor for Cython
-Datatype::Datatype() {}
+Datatype::Datatype() : d_solver(nullptr), d_dtype(nullptr) {}
Datatype::~Datatype() {}
DatatypeConstructor Datatype::operator[](size_t idx) const
{
CVC4_API_CHECK(idx < getNumConstructors()) << "Index out of bounds.";
- return (*d_dtype)[idx];
+ return DatatypeConstructor(d_solver, (*d_dtype)[idx]);
}
DatatypeConstructor Datatype::operator[](const std::string& name) const
@@ -2141,12 +2187,12 @@ std::string Datatype::toString() const { return d_dtype->getName(); }
Datatype::const_iterator Datatype::begin() const
{
- return Datatype::const_iterator(*d_dtype, true);
+ return Datatype::const_iterator(d_solver, *d_dtype, true);
}
Datatype::const_iterator Datatype::end() const
{
- return Datatype::const_iterator(*d_dtype, false);
+ return Datatype::const_iterator(d_solver, *d_dtype, false);
}
// !!! This is only temporarily available until the parser is fully migrated
@@ -2169,28 +2215,33 @@ DatatypeConstructor Datatype::getConstructorForName(
}
CVC4_API_CHECK(foundCons) << "No constructor " << name << " for datatype "
<< getName() << " exists";
- return (*d_dtype)[index];
+ return DatatypeConstructor(d_solver, (*d_dtype)[index]);
}
-Datatype::const_iterator::const_iterator(const CVC4::Datatype& dtype,
+Datatype::const_iterator::const_iterator(const Solver* slv,
+ const CVC4::Datatype& dtype,
bool begin)
+ : d_solver(slv), d_int_ctors(dtype.getConstructors())
{
- d_int_ctors = dtype.getConstructors();
const std::vector<CVC4::DatatypeConstructor>* cons =
static_cast<const std::vector<CVC4::DatatypeConstructor>*>(d_int_ctors);
for (const auto& c : *cons)
{
/* Can not use emplace_back here since constructor is private. */
- d_ctors.push_back(DatatypeConstructor(c));
+ d_ctors.push_back(DatatypeConstructor(d_solver, c));
}
d_idx = begin ? 0 : cons->size();
}
-Datatype::const_iterator::const_iterator() {}
+Datatype::const_iterator::const_iterator()
+ : d_solver(nullptr), d_int_ctors(nullptr), d_idx(0)
+{
+}
Datatype::const_iterator& Datatype::const_iterator::operator=(
const Datatype::const_iterator& it)
{
+ d_solver = it.d_solver;
d_int_ctors = it.d_int_ctors;
d_ctors = it.d_ctors;
d_idx = it.d_idx;
@@ -2235,10 +2286,10 @@ bool Datatype::const_iterator::operator!=(
/* -------------------------------------------------------------------------- */
/* Grammar */
/* -------------------------------------------------------------------------- */
-Grammar::Grammar(const Solver* s,
+Grammar::Grammar(const Solver* slv,
const std::vector<Term>& sygusVars,
const std::vector<Term>& ntSymbols)
- : d_s(s),
+ : d_solver(slv),
d_sygusVars(sygusVars),
d_ntSyms(ntSymbols),
d_ntsToTerms(ntSymbols.size()),
@@ -2326,8 +2377,9 @@ Sort Grammar::resolve()
if (!d_sygusVars.empty())
{
- bvl = d_s->getExprManager()->mkExpr(CVC4::kind::BOUND_VAR_LIST,
- termVectorToExprs(d_sygusVars));
+ bvl = Term(d_solver,
+ d_solver->getExprManager()->mkExpr(
+ CVC4::kind::BOUND_VAR_LIST, termVectorToExprs(d_sygusVars)));
}
std::unordered_map<Term, Sort, TermHashFunction> ntsToUnres(d_ntSyms.size());
@@ -2336,7 +2388,8 @@ Sort Grammar::resolve()
{
// make the unresolved type, used for referencing the final version of
// the ntsymbol's datatype
- ntsToUnres[ntsymbol] = d_s->getExprManager()->mkSort(ntsymbol.toString());
+ ntsToUnres[ntsymbol] =
+ Sort(d_solver, d_solver->getExprManager()->mkSort(ntsymbol.toString()));
}
std::vector<CVC4::Datatype> datatypes;
@@ -2347,7 +2400,7 @@ Sort Grammar::resolve()
for (const Term& ntSym : d_ntSyms)
{
// make the datatype, which encodes terms generated by this non-terminal
- DatatypeDecl dtDecl(d_s, ntSym.toString());
+ DatatypeDecl dtDecl(d_solver, ntSym.toString());
for (const Term& consTerm : d_ntsToTerms[ntSym])
{
@@ -2356,7 +2409,8 @@ Sort Grammar::resolve()
if (d_allowVars.find(ntSym) != d_allowVars.cend())
{
- addSygusConstructorVariables(dtDecl, ntSym.d_expr->getType());
+ addSygusConstructorVariables(dtDecl,
+ Sort(d_solver, ntSym.d_expr->getType()));
}
bool aci = d_allowConst.find(ntSym) != d_allowConst.end();
@@ -2375,11 +2429,11 @@ Sort Grammar::resolve()
}
std::vector<DatatypeType> datatypeTypes =
- d_s->getExprManager()->mkMutualDatatypeTypes(
+ d_solver->getExprManager()->mkMutualDatatypeTypes(
datatypes, unresTypes, ExprManager::DATATYPE_FLAG_PLACEHOLDER);
// return is the first datatype
- return datatypeTypes[0];
+ return Sort(d_solver, datatypeTypes[0]);
}
void Grammar::addSygusConstructorTerm(
@@ -2406,11 +2460,13 @@ void Grammar::addSygusConstructorTerm(
*op.d_expr, termVectorToExprs(args));
if (!args.empty())
{
- Term lbvl = d_s->getExprManager()->mkExpr(CVC4::kind::BOUND_VAR_LIST,
- termVectorToExprs(args));
+ Term lbvl = Term(d_solver,
+ d_solver->getExprManager()->mkExpr(
+ CVC4::kind::BOUND_VAR_LIST, termVectorToExprs(args)));
// its operator is a lambda
- op = d_s->getExprManager()->mkExpr(CVC4::kind::LAMBDA,
- {*lbvl.d_expr, *op.d_expr});
+ op = Term(d_solver,
+ d_solver->getExprManager()->mkExpr(CVC4::kind::LAMBDA,
+ {*lbvl.d_expr, *op.d_expr}));
}
dt.d_dtype->addSygusConstructor(
*op.d_expr, ssCName.str(), sortVectorToTypes(cargs), spc);
@@ -2426,7 +2482,9 @@ Term Grammar::purifySygusGTerm(
ntsToUnres.find(term);
if (itn != ntsToUnres.cend())
{
- Term ret = d_s->getExprManager()->mkBoundVar(term.d_expr->getType());
+ Term ret =
+ Term(d_solver,
+ d_solver->getExprManager()->mkBoundVar(term.d_expr->getType()));
args.push_back(ret);
cargs.push_back(itn->second);
return ret;
@@ -2435,7 +2493,8 @@ Term Grammar::purifySygusGTerm(
bool childChanged = false;
for (unsigned i = 0, nchild = term.d_expr->getNumChildren(); i < nchild; i++)
{
- Term ptermc = purifySygusGTerm((*term.d_expr)[i], args, cargs, ntsToUnres);
+ Term ptermc = purifySygusGTerm(
+ Term(d_solver, (*term.d_expr)[i]), args, cargs, ntsToUnres);
pchildren.push_back(ptermc);
childChanged = childChanged || *ptermc.d_expr != (*term.d_expr)[i];
}
@@ -2444,22 +2503,22 @@ Term Grammar::purifySygusGTerm(
return term;
}
- Term nret;
+ Expr nret;
if (term.d_expr->isParameterized())
{
// it's an indexed operator so we should provide the op
- nret = d_s->getExprManager()->mkExpr(term.d_expr->getKind(),
- term.d_expr->getOperator(),
- termVectorToExprs(pchildren));
+ nret = d_solver->getExprManager()->mkExpr(term.d_expr->getKind(),
+ term.d_expr->getOperator(),
+ termVectorToExprs(pchildren));
}
else
{
- nret = d_s->getExprManager()->mkExpr(term.d_expr->getKind(),
- termVectorToExprs(pchildren));
+ nret = d_solver->getExprManager()->mkExpr(term.d_expr->getKind(),
+ termVectorToExprs(pchildren));
}
- return nret;
+ return Term(d_solver, nret);
}
void Grammar::addSygusConstructorVariables(DatatypeDecl& dt, Sort sort) const
@@ -2538,9 +2597,9 @@ Solver::~Solver() {}
template <typename T>
Term Solver::mkValHelper(T t) const
{
- Term res = d_exprMgr->mkConst(t);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ Expr res = d_exprMgr->mkConst(t);
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
}
Term Solver::mkRealFromStrHelper(const std::string& s) const
@@ -2623,7 +2682,7 @@ Term Solver::mkTermFromKind(Kind kind) const
kind == PI || kind == REGEXP_EMPTY || kind == REGEXP_SIGMA, kind)
<< "PI or REGEXP_EMPTY or REGEXP_SIGMA";
- Term res;
+ Expr res;
if (kind == REGEXP_EMPTY || kind == REGEXP_SIGMA)
{
CVC4::Kind k = extToIntKind(kind);
@@ -2635,8 +2694,8 @@ Term Solver::mkTermFromKind(Kind kind) const
Assert(kind == PI);
res = d_exprMgr->mkNullaryOperator(d_exprMgr->realType(), CVC4::kind::PI);
}
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2647,8 +2706,11 @@ Term Solver::mkTermHelper(Kind kind, const std::vector<Term>& children) const
for (size_t i = 0, size = children.size(); i < size; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
- !children[i].isNull(), "parameter term", children[i], i)
+ !children[i].isNull(), "child term", children[i], i)
<< "non-null term";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == children[i].d_solver, "child term", children[i], i)
+ << "a child term associated to this solver object";
}
std::vector<Expr> echildren = termVectorToExprs(children);
@@ -2656,7 +2718,7 @@ Term Solver::mkTermHelper(Kind kind, const std::vector<Term>& children) const
Assert(isDefinedIntKind(k))
<< "Not a defined internal kind : " << k << " " << kind;
- Term res;
+ Expr res;
if (echildren.size() > 2)
{
if (kind == INTS_DIVISION || kind == XOR || kind == MINUS
@@ -2701,8 +2763,8 @@ Term Solver::mkTermHelper(Kind kind, const std::vector<Term>& children) const
res = d_exprMgr->mkExpr(k, echildren);
}
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2713,20 +2775,31 @@ std::vector<Sort> Solver::mkDatatypeSortsInternal(
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
std::vector<CVC4::Datatype> datatypes;
- for (size_t i = 0, ndts = dtypedecls.size(); i < ndts; i++)
- {
- CVC4_API_ARG_CHECK_EXPECTED(dtypedecls[i].getNumConstructors() > 0,
- dtypedecls[i])
+ for (size_t i = 0, ndts = dtypedecls.size(); i < ndts; ++i)
+ {
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(this == dtypedecls[i].d_solver,
+ "datatype declaration",
+ dtypedecls[i],
+ i)
+ << "a datatype declaration associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(dtypedecls[i].getNumConstructors() > 0,
+ "datatype declaration",
+ dtypedecls[i],
+ i)
<< "a datatype declaration with at least one constructor";
datatypes.push_back(dtypedecls[i].getDatatype());
}
+ for (auto& sort : unresolvedSorts)
+ {
+ CVC4_API_SOLVER_CHECK_SORT(sort);
+ }
std::set<Type> utypes = sortSetToTypes(unresolvedSorts);
std::vector<CVC4::DatatypeType> dtypes =
d_exprMgr->mkMutualDatatypeTypes(datatypes, utypes);
std::vector<Sort> retTypes;
for (CVC4::DatatypeType t : dtypes)
{
- retTypes.push_back(Sort(t));
+ retTypes.push_back(Sort(this, t));
}
return retTypes;
@@ -2742,6 +2815,7 @@ std::vector<Type> Solver::sortVectorToTypes(
std::vector<Type> res;
for (const Sort& s : sorts)
{
+ CVC4_API_SOLVER_CHECK_SORT(s);
res.push_back(*s.d_type);
}
return res;
@@ -2753,6 +2827,7 @@ std::vector<Expr> Solver::termVectorToExprs(
std::vector<Expr> res;
for (const Term& t : terms)
{
+ CVC4_API_SOLVER_CHECK_TERM(t);
res.push_back(*t.d_expr);
}
return res;
@@ -2786,49 +2861,49 @@ void Solver::checkMkTerm(Kind kind, uint32_t nchildren) const
Sort Solver::getNullSort(void) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return Type();
+ return Sort(this, Type());
CVC4_API_SOLVER_TRY_CATCH_END;
}
Sort Solver::getBooleanSort(void) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->booleanType();
+ return Sort(this, d_exprMgr->booleanType());
CVC4_API_SOLVER_TRY_CATCH_END;
}
Sort Solver::getIntegerSort(void) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->integerType();
+ return Sort(this, d_exprMgr->integerType());
CVC4_API_SOLVER_TRY_CATCH_END;
}
Sort Solver::getRealSort(void) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->realType();
+ return Sort(this, d_exprMgr->realType());
CVC4_API_SOLVER_TRY_CATCH_END;
}
Sort Solver::getRegExpSort(void) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->regExpType();
+ return Sort(this, d_exprMgr->regExpType());
CVC4_API_SOLVER_TRY_CATCH_END;
}
Sort Solver::getStringSort(void) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->stringType();
+ return Sort(this, d_exprMgr->stringType());
CVC4_API_SOLVER_TRY_CATCH_END;
}
Sort Solver::getRoundingmodeSort(void) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->roundingModeType();
+ return Sort(this, d_exprMgr->roundingModeType());
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2841,8 +2916,11 @@ Sort Solver::mkArraySort(Sort indexSort, Sort elemSort) const
<< "non-null index sort";
CVC4_API_ARG_CHECK_EXPECTED(!elemSort.isNull(), elemSort)
<< "non-null element sort";
+ CVC4_API_SOLVER_CHECK_SORT(indexSort);
+ CVC4_API_SOLVER_CHECK_SORT(elemSort);
- return d_exprMgr->mkArrayType(*indexSort.d_type, *elemSort.d_type);
+ return Sort(this,
+ d_exprMgr->mkArrayType(*indexSort.d_type, *elemSort.d_type));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2852,7 +2930,7 @@ Sort Solver::mkBitVectorSort(uint32_t size) const
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(size > 0, size) << "size > 0";
- return d_exprMgr->mkBitVectorType(size);
+ return Sort(this, d_exprMgr->mkBitVectorType(size));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2863,7 +2941,7 @@ Sort Solver::mkFloatingPointSort(uint32_t exp, uint32_t sig) const
CVC4_API_ARG_CHECK_EXPECTED(exp > 0, exp) << "exponent size > 0";
CVC4_API_ARG_CHECK_EXPECTED(sig > 0, sig) << "significand size > 0";
- return d_exprMgr->mkFloatingPointType(exp, sig);
+ return Sort(this, d_exprMgr->mkFloatingPointType(exp, sig));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2871,10 +2949,12 @@ Sort Solver::mkFloatingPointSort(uint32_t exp, uint32_t sig) const
Sort Solver::mkDatatypeSort(DatatypeDecl dtypedecl) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_CHECK(this == dtypedecl.d_solver)
+ << "Given datatype declaration is not associated with this solver";
CVC4_API_ARG_CHECK_EXPECTED(dtypedecl.getNumConstructors() > 0, dtypedecl)
<< "a datatype declaration with at least one constructor";
- return d_exprMgr->mkDatatypeType(*dtypedecl.d_dtype);
+ return Sort(this, d_exprMgr->mkDatatypeType(*dtypedecl.d_dtype));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2897,13 +2977,16 @@ Sort Solver::mkFunctionSort(Sort domain, Sort codomain) const
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(!codomain.isNull(), codomain)
<< "non-null codomain sort";
+ CVC4_API_SOLVER_CHECK_SORT(domain);
+ CVC4_API_SOLVER_CHECK_SORT(codomain);
CVC4_API_ARG_CHECK_EXPECTED(domain.isFirstClass(), domain)
<< "first-class sort as domain sort for function sort";
CVC4_API_ARG_CHECK_EXPECTED(codomain.isFirstClass(), codomain)
<< "first-class sort as codomain sort for function sort";
Assert(!codomain.isFunction()); /* A function sort is not first-class. */
- return d_exprMgr->mkFunctionType(*domain.d_type, *codomain.d_type);
+ return Sort(this,
+ d_exprMgr->mkFunctionType(*domain.d_type, *codomain.d_type));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2919,17 +3002,21 @@ Sort Solver::mkFunctionSort(const std::vector<Sort>& sorts, Sort codomain) const
!sorts[i].isNull(), "parameter sort", sorts[i], i)
<< "non-null sort";
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == sorts[i].d_solver, "parameter sort", sorts[i], i)
+ << "sort associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
sorts[i].isFirstClass(), "parameter sort", sorts[i], i)
<< "first-class sort as parameter sort for function sort";
}
CVC4_API_ARG_CHECK_EXPECTED(!codomain.isNull(), codomain)
<< "non-null codomain sort";
+ CVC4_API_SOLVER_CHECK_SORT(codomain);
CVC4_API_ARG_CHECK_EXPECTED(codomain.isFirstClass(), codomain)
<< "first-class sort as codomain sort for function sort";
Assert(!codomain.isFunction()); /* A function sort is not first-class. */
std::vector<Type> argTypes = sortVectorToTypes(sorts);
- return d_exprMgr->mkFunctionType(argTypes, *codomain.d_type);
+ return Sort(this, d_exprMgr->mkFunctionType(argTypes, *codomain.d_type));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2937,7 +3024,8 @@ Sort Solver::mkFunctionSort(const std::vector<Sort>& sorts, Sort codomain) const
Sort Solver::mkParamSort(const std::string& symbol) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->mkSort(symbol, ExprManager::SORT_FLAG_PLACEHOLDER);
+ return Sort(this,
+ d_exprMgr->mkSort(symbol, ExprManager::SORT_FLAG_PLACEHOLDER));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2952,12 +3040,15 @@ Sort Solver::mkPredicateSort(const std::vector<Sort>& sorts) const
!sorts[i].isNull(), "parameter sort", sorts[i], i)
<< "non-null sort";
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == sorts[i].d_solver, "parameter sort", sorts[i], i)
+ << "sort associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
sorts[i].isFirstClass(), "parameter sort", sorts[i], i)
<< "first-class sort as parameter sort for predicate sort";
}
std::vector<Type> types = sortVectorToTypes(sorts);
- return d_exprMgr->mkPredicateType(types);
+ return Sort(this, d_exprMgr->mkPredicateType(types));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2973,11 +3064,14 @@ Sort Solver::mkRecordSort(
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
!p.second.isNull(), "parameter sort", p.second, i)
<< "non-null sort";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == p.second.d_solver, "parameter sort", p.second, i)
+ << "sort associated to this solver object";
i += 1;
f.emplace_back(p.first, *p.second.d_type);
}
- return d_exprMgr->mkRecordType(Record(f));
+ return Sort(this, d_exprMgr->mkRecordType(Record(f)));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2987,8 +3081,9 @@ Sort Solver::mkSetSort(Sort elemSort) const
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(!elemSort.isNull(), elemSort)
<< "non-null element sort";
+ CVC4_API_SOLVER_CHECK_SORT(elemSort);
- return d_exprMgr->mkSetType(*elemSort.d_type);
+ return Sort(this, d_exprMgr->mkSetType(*elemSort.d_type));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -2996,7 +3091,7 @@ Sort Solver::mkSetSort(Sort elemSort) const
Sort Solver::mkUninterpretedSort(const std::string& symbol) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->mkSort(symbol);
+ return Sort(this, d_exprMgr->mkSort(symbol));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3006,7 +3101,7 @@ Sort Solver::mkSortConstructorSort(const std::string& symbol,
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(arity > 0, arity) << "an arity > 0";
- return d_exprMgr->mkSortConstructor(symbol, arity);
+ return Sort(this, d_exprMgr->mkSortConstructor(symbol, arity));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3020,12 +3115,15 @@ Sort Solver::mkTupleSort(const std::vector<Sort>& sorts) const
!sorts[i].isNull(), "parameter sort", sorts[i], i)
<< "non-null sort";
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == sorts[i].d_solver, "parameter sort", sorts[i], i)
+ << "sort associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
!sorts[i].isFunctionLike(), "parameter sort", sorts[i], i)
<< "non-function-like sort as parameter sort for tuple sort";
}
std::vector<Type> types = sortVectorToTypes(sorts);
- return d_exprMgr->mkTupleType(types);
+ return Sort(this, d_exprMgr->mkTupleType(types));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3036,21 +3134,21 @@ Sort Solver::mkTupleSort(const std::vector<Sort>& sorts) const
Term Solver::mkTrue(void) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->mkConst<bool>(true);
+ return Term(this, d_exprMgr->mkConst<bool>(true));
CVC4_API_SOLVER_TRY_CATCH_END;
}
Term Solver::mkFalse(void) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->mkConst<bool>(false);
+ return Term(this, d_exprMgr->mkConst<bool>(false));
CVC4_API_SOLVER_TRY_CATCH_END;
}
Term Solver::mkBoolean(bool val) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- return d_exprMgr->mkConst<bool>(val);
+ return Term(this, d_exprMgr->mkConst<bool>(val));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3058,10 +3156,10 @@ Term Solver::mkPi() const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- Term res =
+ Expr res =
d_exprMgr->mkNullaryOperator(d_exprMgr->realType(), CVC4::kind::PI);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3143,10 +3241,10 @@ Term Solver::mkRegexpEmpty() const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- Term res =
+ Expr res =
d_exprMgr->mkExpr(CVC4::kind::REGEXP_EMPTY, std::vector<CVC4::Expr>());
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3155,10 +3253,10 @@ Term Solver::mkRegexpSigma() const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- Term res =
+ Expr res =
d_exprMgr->mkExpr(CVC4::kind::REGEXP_SIGMA, std::vector<CVC4::Expr>());
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3168,6 +3266,8 @@ Term Solver::mkEmptySet(Sort s) const
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(s.isNull() || s.isSet(), s)
<< "null sort or set sort";
+ CVC4_API_ARG_CHECK_EXPECTED(s.isNull() || this == s.d_solver, s)
+ << "set sort associated to this solver object";
return mkValHelper<CVC4::EmptySet>(CVC4::EmptySet(*s.d_type));
@@ -3178,10 +3278,11 @@ Term Solver::mkSepNil(Sort sort) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ CVC4_API_SOLVER_CHECK_SORT(sort);
- Term res = d_exprMgr->mkNullaryOperator(*sort.d_type, CVC4::kind::SEP_NIL);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ Expr res = d_exprMgr->mkNullaryOperator(*sort.d_type, CVC4::kind::SEP_NIL);
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3233,12 +3334,13 @@ Term Solver::mkUniverseSet(Sort sort) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ CVC4_API_SOLVER_CHECK_SORT(sort);
- Term res =
+ Expr res =
d_exprMgr->mkNullaryOperator(*sort.d_type, CVC4::kind::UNIVERSE_SET);
// TODO(#2771): Reenable?
- // (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ // (void)res->getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3285,7 +3387,10 @@ Term Solver::mkBitVector(uint32_t size, std::string& s, uint32_t base) const
Term Solver::mkConstArray(Sort sort, Term val) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_ARG_CHECK_NOT_NULL(sort);
CVC4_API_ARG_CHECK_NOT_NULL(val);
+ CVC4_API_SOLVER_CHECK_SORT(sort);
+ CVC4_API_SOLVER_CHECK_TERM(val);
CVC4_API_CHECK(sort.isArray()) << "Not an array sort.";
CVC4_API_CHECK(sort.getArrayElementSort().isComparableTo(val.getSort()))
<< "Value does not match element sort.";
@@ -3366,6 +3471,7 @@ Term Solver::mkUninterpretedConst(Sort sort, int32_t index) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ CVC4_API_SOLVER_CHECK_SORT(sort);
return mkValHelper<CVC4::UninterpretedConstant>(
CVC4::UninterpretedConstant(*sort.d_type, index));
@@ -3381,7 +3487,7 @@ Term Solver::mkAbstractValue(const std::string& index) const
CVC4::Integer idx(index, 10);
CVC4_API_ARG_CHECK_EXPECTED(idx > 0, index)
<< "a string representing an integer > 0";
- return d_exprMgr->mkConst(CVC4::AbstractValue(idx));
+ return Term(this, d_exprMgr->mkConst(CVC4::AbstractValue(idx)));
// do not call getType(), for abstract values, type can not be computed
// until it is substituted away
CVC4_API_SOLVER_TRY_CATCH_END;
@@ -3392,7 +3498,7 @@ Term Solver::mkAbstractValue(uint64_t index) const
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(index > 0, index) << "an integer > 0";
- return d_exprMgr->mkConst(CVC4::AbstractValue(Integer(index)));
+ return Term(this, d_exprMgr->mkConst(CVC4::AbstractValue(Integer(index))));
// do not call getType(), for abstract values, type can not be computed
// until it is substituted away
CVC4_API_SOLVER_TRY_CATCH_END;
@@ -3409,6 +3515,7 @@ Term Solver::mkFloatingPoint(uint32_t exp, uint32_t sig, Term val) const
CVC4_API_ARG_CHECK_EXPECTED(bw == val.getSort().getBVSize(), val)
<< "a bit-vector constant with bit-width '" << bw << "'";
CVC4_API_ARG_CHECK_EXPECTED(!val.isNull(), val) << "non-null term";
+ CVC4_API_SOLVER_CHECK_TERM(val);
CVC4_API_ARG_CHECK_EXPECTED(
val.getSort().isBitVector() && val.d_expr->isConst(), val)
<< "bit-vector constant";
@@ -3426,11 +3533,12 @@ Term Solver::mkConst(Sort sort, const std::string& symbol) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ CVC4_API_SOLVER_CHECK_SORT(sort);
- Term res = symbol.empty() ? d_exprMgr->mkVar(*sort.d_type)
+ Expr res = symbol.empty() ? d_exprMgr->mkVar(*sort.d_type)
: d_exprMgr->mkVar(symbol, *sort.d_type);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3442,15 +3550,25 @@ Term Solver::mkVar(Sort sort, const std::string& symbol) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ CVC4_API_SOLVER_CHECK_SORT(sort);
- Term res = symbol.empty() ? d_exprMgr->mkBoundVar(*sort.d_type)
+ Expr res = symbol.empty() ? d_exprMgr->mkBoundVar(*sort.d_type)
: d_exprMgr->mkBoundVar(symbol, *sort.d_type);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
+/* Create datatype constructor declarations */
+/* -------------------------------------------------------------------------- */
+
+DatatypeConstructorDecl Solver::mkDatatypeConstructorDecl(
+ const std::string& name)
+{
+ return DatatypeConstructorDecl(this, name);
+}
+
/* Create datatype declarations */
/* -------------------------------------------------------------------------- */
@@ -3487,11 +3605,12 @@ Term Solver::mkTerm(Kind kind, Term child) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(!child.isNull(), child) << "non-null term";
+ CVC4_API_SOLVER_CHECK_TERM(child);
checkMkTerm(kind, 1);
- Term res = d_exprMgr->mkExpr(extToIntKind(kind), *child.d_expr);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ Expr res = d_exprMgr->mkExpr(extToIntKind(kind), *child.d_expr);
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3501,12 +3620,14 @@ Term Solver::mkTerm(Kind kind, Term child1, Term child2) const
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(!child1.isNull(), child1) << "non-null term";
CVC4_API_ARG_CHECK_EXPECTED(!child2.isNull(), child2) << "non-null term";
+ CVC4_API_SOLVER_CHECK_TERM(child1);
+ CVC4_API_SOLVER_CHECK_TERM(child2);
checkMkTerm(kind, 2);
- Term res =
+ Expr res =
d_exprMgr->mkExpr(extToIntKind(kind), *child1.d_expr, *child2.d_expr);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3525,12 +3646,13 @@ Term Solver::mkTerm(Kind kind, const std::vector<Term>& children) const
Term Solver::mkTerm(Op op) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_SOLVER_CHECK_OP(op);
Term res;
if (op.isIndexedHelper())
{
const CVC4::Kind int_kind = extToIntKind(op.d_kind);
- res = d_exprMgr->mkExpr(int_kind, *op.d_expr);
+ res = Term(this, d_exprMgr->mkExpr(int_kind, *op.d_expr));
}
else
{
@@ -3546,10 +3668,12 @@ Term Solver::mkTerm(Op op) const
Term Solver::mkTerm(Op op, Term child) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_SOLVER_CHECK_OP(op);
CVC4_API_ARG_CHECK_EXPECTED(!child.isNull(), child) << "non-null term";
+ CVC4_API_SOLVER_CHECK_TERM(child);
const CVC4::Kind int_kind = extToIntKind(op.d_kind);
- Term res;
+ Expr res;
if (op.isIndexedHelper())
{
res = d_exprMgr->mkExpr(int_kind, *op.d_expr, *child.d_expr);
@@ -3559,8 +3683,8 @@ Term Solver::mkTerm(Op op, Term child) const
res = d_exprMgr->mkExpr(int_kind, *child.d_expr);
}
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3568,11 +3692,14 @@ Term Solver::mkTerm(Op op, Term child) const
Term Solver::mkTerm(Op op, Term child1, Term child2) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_SOLVER_CHECK_OP(op);
CVC4_API_ARG_CHECK_EXPECTED(!child1.isNull(), child1) << "non-null term";
CVC4_API_ARG_CHECK_EXPECTED(!child2.isNull(), child2) << "non-null term";
+ CVC4_API_SOLVER_CHECK_TERM(child1);
+ CVC4_API_SOLVER_CHECK_TERM(child2);
const CVC4::Kind int_kind = extToIntKind(op.d_kind);
- Term res;
+ Expr res;
if (op.isIndexedHelper())
{
res =
@@ -3583,20 +3710,24 @@ Term Solver::mkTerm(Op op, Term child1, Term child2) const
res = d_exprMgr->mkExpr(int_kind, *child1.d_expr, *child2.d_expr);
}
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
Term Solver::mkTerm(Op op, Term child1, Term child2, Term child3) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_SOLVER_CHECK_OP(op);
CVC4_API_ARG_CHECK_EXPECTED(!child1.isNull(), child1) << "non-null term";
CVC4_API_ARG_CHECK_EXPECTED(!child2.isNull(), child2) << "non-null term";
CVC4_API_ARG_CHECK_EXPECTED(!child3.isNull(), child3) << "non-null term";
+ CVC4_API_SOLVER_CHECK_TERM(child1);
+ CVC4_API_SOLVER_CHECK_TERM(child2);
+ CVC4_API_SOLVER_CHECK_TERM(child3);
const CVC4::Kind int_kind = extToIntKind(op.d_kind);
- Term res;
+ Expr res;
if (op.isIndexedHelper())
{
res = d_exprMgr->mkExpr(
@@ -3608,8 +3739,8 @@ Term Solver::mkTerm(Op op, Term child1, Term child2, Term child3) const
int_kind, *child1.d_expr, *child2.d_expr, *child3.d_expr);
}
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3617,16 +3748,20 @@ Term Solver::mkTerm(Op op, Term child1, Term child2, Term child3) const
Term Solver::mkTerm(Op op, const std::vector<Term>& children) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_SOLVER_CHECK_OP(op);
for (size_t i = 0, size = children.size(); i < size; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
- !children[i].isNull(), "parameter term", children[i], i)
+ !children[i].isNull(), "child term", children[i], i)
<< "non-null term";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == children[i].d_solver, "child term", children[i], i)
+ << "child term associated to this solver object";
}
const CVC4::Kind int_kind = extToIntKind(op.d_kind);
std::vector<Expr> echildren = termVectorToExprs(children);
- Term res;
+ Expr res;
if (op.isIndexedHelper())
{
res = d_exprMgr->mkExpr(int_kind, *op.d_expr, echildren);
@@ -3636,8 +3771,8 @@ Term Solver::mkTerm(Op op, const std::vector<Term>& children) const
res = d_exprMgr->mkExpr(int_kind, echildren);
}
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3651,16 +3786,22 @@ Term Solver::mkTuple(const std::vector<Sort>& sorts,
std::vector<CVC4::Expr> args;
for (size_t i = 0, size = sorts.size(); i < size; i++)
{
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == terms[i].d_solver, "child term", terms[i], i)
+ << "child term associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == sorts[i].d_solver, "child sort", sorts[i], i)
+ << "child sort associated to this solver object";
args.push_back(*(ensureTermSort(terms[i], sorts[i])).d_expr);
}
Sort s = mkTupleSort(sorts);
Datatype dt = s.getDatatype();
- Term res = d_exprMgr->mkExpr(extToIntKind(APPLY_CONSTRUCTOR),
+ Expr res = d_exprMgr->mkExpr(extToIntKind(APPLY_CONSTRUCTOR),
*dt[0].getConstructorTerm().d_expr,
args);
- (void)res.d_expr->getType(true); /* kick off type checking */
- return res;
+ (void)res.getType(true); /* kick off type checking */
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3673,7 +3814,7 @@ Op Solver::mkOp(Kind kind) const
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_CHECK(s_indexed_kinds.find(kind) == s_indexed_kinds.end())
<< "Expected a kind for a non-indexed operator.";
- return Op(kind);
+ return Op(this, kind);
CVC4_API_SOLVER_TRY_CATCH_END
}
@@ -3687,6 +3828,7 @@ Op Solver::mkOp(Kind kind, const std::string& arg) const
if (kind == RECORD_UPDATE)
{
res = Op(
+ this,
kind,
*mkValHelper<CVC4::RecordUpdate>(CVC4::RecordUpdate(arg)).d_expr.get());
}
@@ -3697,7 +3839,8 @@ Op Solver::mkOp(Kind kind, const std::string& arg) const
* as invalid. */
CVC4_API_ARG_CHECK_EXPECTED(arg != ".", arg)
<< "a string representing an integer, real or rational value.";
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::Divisible>(CVC4::Divisible(CVC4::Integer(arg)))
.d_expr.get());
}
@@ -3716,62 +3859,73 @@ Op Solver::mkOp(Kind kind, uint32_t arg) const
{
case DIVISIBLE:
res =
- Op(kind,
+ Op(this,
+ kind,
*mkValHelper<CVC4::Divisible>(CVC4::Divisible(arg)).d_expr.get());
break;
case BITVECTOR_REPEAT:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::BitVectorRepeat>(CVC4::BitVectorRepeat(arg))
.d_expr.get());
break;
case BITVECTOR_ZERO_EXTEND:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::BitVectorZeroExtend>(
CVC4::BitVectorZeroExtend(arg))
.d_expr.get());
break;
case BITVECTOR_SIGN_EXTEND:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::BitVectorSignExtend>(
CVC4::BitVectorSignExtend(arg))
.d_expr.get());
break;
case BITVECTOR_ROTATE_LEFT:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::BitVectorRotateLeft>(
CVC4::BitVectorRotateLeft(arg))
.d_expr.get());
break;
case BITVECTOR_ROTATE_RIGHT:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::BitVectorRotateRight>(
CVC4::BitVectorRotateRight(arg))
.d_expr.get());
break;
case INT_TO_BITVECTOR:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::IntToBitVector>(CVC4::IntToBitVector(arg))
.d_expr.get());
break;
case FLOATINGPOINT_TO_UBV:
res = Op(
+ this,
kind,
*mkValHelper<CVC4::FloatingPointToUBV>(CVC4::FloatingPointToUBV(arg))
.d_expr.get());
break;
case FLOATINGPOINT_TO_SBV:
res = Op(
+ this,
kind,
*mkValHelper<CVC4::FloatingPointToSBV>(CVC4::FloatingPointToSBV(arg))
.d_expr.get());
break;
case TUPLE_UPDATE:
res = Op(
+ this,
kind,
*mkValHelper<CVC4::TupleUpdate>(CVC4::TupleUpdate(arg)).d_expr.get());
break;
case REGEXP_REPEAT:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::RegExpRepeat>(CVC4::RegExpRepeat(arg))
.d_expr.get());
break;
@@ -3794,49 +3948,57 @@ Op Solver::mkOp(Kind kind, uint32_t arg1, uint32_t arg2) const
switch (kind)
{
case BITVECTOR_EXTRACT:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::BitVectorExtract>(
CVC4::BitVectorExtract(arg1, arg2))
.d_expr.get());
break;
case FLOATINGPOINT_TO_FP_IEEE_BITVECTOR:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::FloatingPointToFPIEEEBitVector>(
CVC4::FloatingPointToFPIEEEBitVector(arg1, arg2))
.d_expr.get());
break;
case FLOATINGPOINT_TO_FP_FLOATINGPOINT:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::FloatingPointToFPFloatingPoint>(
CVC4::FloatingPointToFPFloatingPoint(arg1, arg2))
.d_expr.get());
break;
case FLOATINGPOINT_TO_FP_REAL:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::FloatingPointToFPReal>(
CVC4::FloatingPointToFPReal(arg1, arg2))
.d_expr.get());
break;
case FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::FloatingPointToFPSignedBitVector>(
CVC4::FloatingPointToFPSignedBitVector(arg1, arg2))
.d_expr.get());
break;
case FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::FloatingPointToFPUnsignedBitVector>(
CVC4::FloatingPointToFPUnsignedBitVector(arg1, arg2))
.d_expr.get());
break;
case FLOATINGPOINT_TO_FP_GENERIC:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::FloatingPointToFPGeneric>(
CVC4::FloatingPointToFPGeneric(arg1, arg2))
.d_expr.get());
break;
case REGEXP_LOOP:
- res = Op(kind,
+ res = Op(this,
+ kind,
*mkValHelper<CVC4::RegExpLoop>(CVC4::RegExpLoop(arg1, arg2))
.d_expr.get());
break;
@@ -3853,12 +4015,13 @@ Op Solver::mkOp(Kind kind, uint32_t arg1, uint32_t arg2) const
/* Non-SMT-LIB commands */
/* -------------------------------------------------------------------------- */
-Term Solver::simplify(const Term& t)
+Term Solver::simplify(const Term& term)
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
- CVC4_API_ARG_CHECK_NOT_NULL(t);
+ CVC4_API_ARG_CHECK_NOT_NULL(term);
+ CVC4_API_SOLVER_CHECK_TERM(term);
- return d_smtEngine->simplify(*t.d_expr);
+ return Term(this, d_smtEngine->simplify(*term.d_expr));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3872,6 +4035,7 @@ Result Solver::checkEntailed(Term term) const
<< "Cannot make multiple queries unless incremental solving is enabled "
"(try --incremental)";
CVC4_API_ARG_CHECK_NOT_NULL(term);
+ CVC4_API_SOLVER_CHECK_TERM(term);
CVC4::Result r = d_smtEngine->checkEntailed(*term.d_expr);
return Result(r);
@@ -3889,6 +4053,7 @@ Result Solver::checkEntailed(const std::vector<Term>& terms) const
"(try --incremental)";
for (const Term& term : terms)
{
+ CVC4_API_SOLVER_CHECK_TERM(term);
CVC4_API_ARG_CHECK_NOT_NULL(term);
}
@@ -3907,10 +4072,11 @@ Result Solver::checkEntailed(const std::vector<Term>& terms) const
*/
void Solver::assertFormula(Term term) const
{
- // CHECK:
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(expr.getExprManager())
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_SOLVER_CHECK_TERM(term);
+ CVC4_API_ARG_CHECK_NOT_NULL(term);
d_smtEngine->assertFormula(*term.d_expr);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -3918,10 +4084,15 @@ void Solver::assertFormula(Term term) const
*/
Result Solver::checkSat(void) const
{
- // CHECK:
- // if d_queryMade -> incremental enabled
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+ CVC4_API_CHECK(!d_smtEngine->isQueryMade()
+ || CVC4::options::incrementalSolving())
+ << "Cannot make multiple queries unless incremental solving is enabled "
+ "(try --incremental)";
CVC4::Result r = d_smtEngine->checkSat();
return Result(r);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -3929,10 +4100,16 @@ Result Solver::checkSat(void) const
*/
Result Solver::checkSatAssuming(Term assumption) const
{
- // CHECK:
- // if assumptions.size() > 0: incremental enabled?
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+ CVC4_API_CHECK(!d_smtEngine->isQueryMade()
+ || CVC4::options::incrementalSolving())
+ << "Cannot make multiple queries unless incremental solving is enabled "
+ "(try --incremental)";
+ CVC4_API_SOLVER_CHECK_TERM(assumption);
CVC4::Result r = d_smtEngine->checkSat(*assumption.d_expr);
return Result(r);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -3940,11 +4117,21 @@ Result Solver::checkSatAssuming(Term assumption) const
*/
Result Solver::checkSatAssuming(const std::vector<Term>& assumptions) const
{
- // CHECK:
- // if assumptions.size() > 0: incremental enabled?
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+ CVC4_API_CHECK(!d_smtEngine->isQueryMade() || assumptions.size() == 0
+ || CVC4::options::incrementalSolving())
+ << "Cannot make multiple queries unless incremental solving is enabled "
+ "(try --incremental)";
+ for (const Term& term : assumptions)
+ {
+ CVC4_API_SOLVER_CHECK_TERM(term);
+ CVC4_API_ARG_CHECK_NOT_NULL(term);
+ }
std::vector<Expr> eassumptions = termVectorToExprs(assumptions);
CVC4::Result r = d_smtEngine->checkSat(eassumptions);
return Result(r);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -3954,14 +4141,21 @@ Sort Solver::declareDatatype(
const std::string& symbol,
const std::vector<DatatypeConstructorDecl>& ctors) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(ctors.size() > 0, ctors)
<< "a datatype declaration with at least one constructor";
DatatypeDecl dtdecl(this, symbol);
- for (const DatatypeConstructorDecl& ctor : ctors)
+ for (size_t i = 0, size = ctors.size(); i < size; i++)
{
- dtdecl.addConstructor(ctor);
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(this == ctors[i].d_solver,
+ "datatype constructor declaration",
+ ctors[i],
+ i)
+ << "datatype constructor declaration associated to this solver object";
+ dtdecl.addConstructor(ctors[i]);
}
- return d_exprMgr->mkDatatypeType(*dtdecl.d_dtype);
+ return Sort(this, d_exprMgr->mkDatatypeType(*dtdecl.d_dtype));
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -3971,14 +4165,19 @@ Term Solver::declareFun(const std::string& symbol,
const std::vector<Sort>& sorts,
Sort sort) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
for (size_t i = 0, size = sorts.size(); i < size; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == sorts[i].d_solver, "parameter sort", sorts[i], i)
+ << "parameter sort associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
sorts[i].isFirstClass(), "parameter sort", sorts[i], i)
<< "first-class sort as parameter sort for function sort";
}
CVC4_API_ARG_CHECK_EXPECTED(sort.isFirstClass(), sort)
<< "first-class sort as function codomain sort";
+ CVC4_API_SOLVER_CHECK_SORT(sort);
Assert(!sort.isFunction()); /* A function sort is not first-class. */
Type type = *sort.d_type;
if (!sorts.empty())
@@ -3986,7 +4185,8 @@ Term Solver::declareFun(const std::string& symbol,
std::vector<Type> types = sortVectorToTypes(sorts);
type = d_exprMgr->mkFunctionType(types, type);
}
- return d_exprMgr->mkVar(symbol, type);
+ return Term(this, d_exprMgr->mkVar(symbol, type));
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -3994,8 +4194,10 @@ Term Solver::declareFun(const std::string& symbol,
*/
Sort Solver::declareSort(const std::string& symbol, uint32_t arity) const
{
- if (arity == 0) return d_exprMgr->mkSort(symbol);
- return d_exprMgr->mkSortConstructor(symbol, arity);
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ if (arity == 0) return Sort(this, d_exprMgr->mkSort(symbol));
+ return Sort(this, d_exprMgr->mkSortConstructor(symbol, arity));
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4006,26 +4208,28 @@ Term Solver::defineFun(const std::string& symbol,
Sort sort,
Term term) const
{
- // CHECK:
- // for bv in bound_vars:
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(bv.getExprManager())
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(expr.getExprManager())
- // CHECK: not recursive
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(sort.isFirstClass(), sort)
<< "first-class sort as codomain sort for function sort";
- // CHECK:
- // for v in bound_vars: is bound var
std::vector<Type> domain_types;
for (size_t i = 0, size = bound_vars.size(); i < size; ++i)
{
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == bound_vars[i].d_solver, "bound variable", bound_vars[i], i)
+ << "bound variable associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ bound_vars[i].d_expr->getKind() == CVC4::Kind::BOUND_VARIABLE,
+ "bound variable",
+ bound_vars[i],
+ i)
+ << "a bound variable";
CVC4::Type t = bound_vars[i].d_expr->getType();
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
t.isFirstClass(), "sort of parameter", bound_vars[i], i)
<< "first-class sort of parameter of defined function";
domain_types.push_back(t);
}
+ CVC4_API_SOLVER_CHECK_SORT(sort);
CVC4_API_CHECK(sort == term.getSort())
<< "Invalid sort of function body '" << term << "', expected '" << sort
<< "'";
@@ -4037,18 +4241,15 @@ Term Solver::defineFun(const std::string& symbol,
Expr fun = d_exprMgr->mkVar(symbol, type);
std::vector<Expr> ebound_vars = termVectorToExprs(bound_vars);
d_smtEngine->defineFunction(fun, ebound_vars, *term.d_expr);
- return fun;
+ return Term(this, fun);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
Term Solver::defineFun(Term fun,
const std::vector<Term>& bound_vars,
Term term) const
{
- // CHECK:
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(bv.getExprManager())
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(expr.getExprManager())
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(fun.getSort().isFunction(), fun) << "function";
std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts();
size_t size = bound_vars.size();
@@ -4057,6 +4258,15 @@ Term Solver::defineFun(Term fun,
for (size_t i = 0; i < size; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == bound_vars[i].d_solver, "bound variable", bound_vars[i], i)
+ << "bound variable associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ bound_vars[i].d_expr->getKind() == CVC4::Kind::BOUND_VARIABLE,
+ "bound variable",
+ bound_vars[i],
+ i)
+ << "a bound variable";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
domain_sorts[i] == bound_vars[i].getSort(),
"sort of parameter",
bound_vars[i],
@@ -4064,16 +4274,15 @@ Term Solver::defineFun(Term fun,
<< "'" << domain_sorts[i] << "'";
}
Sort codomain = fun.getSort().getFunctionCodomainSort();
+ CVC4_API_SOLVER_CHECK_TERM(term);
CVC4_API_CHECK(codomain == term.getSort())
<< "Invalid sort of function body '" << term << "', expected '"
<< codomain << "'";
- // CHECK: not recursive
- // CHECK:
- // for v in bound_vars: is bound var
std::vector<Expr> ebound_vars = termVectorToExprs(bound_vars);
d_smtEngine->defineFunction(*fun.d_expr, ebound_vars, *term.d_expr);
return fun;
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4084,29 +4293,33 @@ Term Solver::defineFunRec(const std::string& symbol,
Sort sort,
Term term) const
{
- // CHECK:
- // for bv in bound_vars:
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(bv.getExprManager())
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(expr.getExprManager())
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(sort.isFirstClass(), sort)
<< "first-class sort as function codomain sort";
Assert(!sort.isFunction()); /* A function sort is not first-class. */
- // CHECK:
- // for v in bound_vars: is bound var
std::vector<Type> domain_types;
for (size_t i = 0, size = bound_vars.size(); i < size; ++i)
{
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == bound_vars[i].d_solver, "bound variable", bound_vars[i], i)
+ << "bound variable associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ bound_vars[i].d_expr->getKind() == CVC4::Kind::BOUND_VARIABLE,
+ "bound variable",
+ bound_vars[i],
+ i)
+ << "a bound variable";
CVC4::Type t = bound_vars[i].d_expr->getType();
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
t.isFirstClass(), "sort of parameter", bound_vars[i], i)
<< "first-class sort of parameter of defined function";
domain_types.push_back(t);
}
+ CVC4_API_SOLVER_CHECK_SORT(sort);
CVC4_API_CHECK(sort == term.getSort())
<< "Invalid sort of function body '" << term << "', expected '" << sort
<< "'";
+ CVC4_API_SOLVER_CHECK_TERM(term);
Type type = *sort.d_type;
if (!domain_types.empty())
{
@@ -4115,19 +4328,15 @@ Term Solver::defineFunRec(const std::string& symbol,
Expr fun = d_exprMgr->mkVar(symbol, type);
std::vector<Expr> ebound_vars = termVectorToExprs(bound_vars);
d_smtEngine->defineFunctionRec(fun, ebound_vars, *term.d_expr);
- return fun;
+ return Term(this, fun);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
Term Solver::defineFunRec(Term fun,
const std::vector<Term>& bound_vars,
Term term) const
{
- // CHECK:
- // for bv in bound_vars:
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(bv.getExprManager())
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(expr.getExprManager())
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(fun.getSort().isFunction(), fun) << "function";
std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts();
size_t size = bound_vars.size();
@@ -4136,21 +4345,30 @@ Term Solver::defineFunRec(Term fun,
for (size_t i = 0; i < size; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == bound_vars[i].d_solver, "bound variable", bound_vars[i], i)
+ << "bound variable associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ bound_vars[i].d_expr->getKind() == CVC4::Kind::BOUND_VARIABLE,
+ "bound variable",
+ bound_vars[i],
+ i)
+ << "a bound variable";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
domain_sorts[i] == bound_vars[i].getSort(),
"sort of parameter",
bound_vars[i],
i)
<< "'" << domain_sorts[i] << "'";
}
+ CVC4_API_SOLVER_CHECK_TERM(term);
Sort codomain = fun.getSort().getFunctionCodomainSort();
CVC4_API_CHECK(codomain == term.getSort())
<< "Invalid sort of function body '" << term << "', expected '"
<< codomain << "'";
- // CHECK:
- // for v in bound_vars: is bound var
std::vector<Expr> ebound_vars = termVectorToExprs(bound_vars);
d_smtEngine->defineFunctionRec(*fun.d_expr, ebound_vars, *term.d_expr);
return fun;
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4160,15 +4378,7 @@ void Solver::defineFunsRec(const std::vector<Term>& funs,
const std::vector<std::vector<Term>>& bound_vars,
const std::vector<Term>& terms) const
{
- // CHECK:
- // for f in funs:
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(f.getExprManager())
- // for bv in bound_vars:
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(bv.getExprManager())
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(expr.getExprManager())
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
size_t funs_size = funs.size();
CVC4_API_ARG_SIZE_CHECK_EXPECTED(funs_size == bound_vars.size(), bound_vars)
<< "'" << funs_size << "'";
@@ -4178,13 +4388,30 @@ void Solver::defineFunsRec(const std::vector<Term>& funs,
const std::vector<Term>& bvars = bound_vars[j];
const Term& term = terms[j];
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == fun.d_solver, "function", fun, j)
+ << "function associated to this solver object";
CVC4_API_ARG_CHECK_EXPECTED(fun.getSort().isFunction(), fun) << "function";
+ CVC4_API_SOLVER_CHECK_TERM(term);
+
std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts();
size_t size = bvars.size();
CVC4_API_ARG_SIZE_CHECK_EXPECTED(size == domain_sorts.size(), bvars)
<< "'" << domain_sorts.size() << "'";
for (size_t i = 0; i < size; ++i)
{
+ for (size_t k = 0, nbvars = bvars.size(); k < nbvars; ++k)
+ {
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == bvars[k].d_solver, "bound variable", bvars[k], k)
+ << "bound variable associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ bvars[k].d_expr->getKind() == CVC4::Kind::BOUND_VARIABLE,
+ "bound variable",
+ bvars[k],
+ k)
+ << "a bound variable";
+ }
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
domain_sorts[i] == bvars[i].getSort(),
"sort of parameter",
@@ -4197,8 +4424,6 @@ void Solver::defineFunsRec(const std::vector<Term>& funs,
codomain == term.getSort(), "sort of function body", term, j)
<< "'" << codomain << "'";
}
- // CHECK:
- // for bv in bound_vars (for v in bv): is bound var
std::vector<Expr> efuns = termVectorToExprs(funs);
std::vector<std::vector<Expr>> ebound_vars;
for (const auto& v : bound_vars)
@@ -4207,6 +4432,7 @@ void Solver::defineFunsRec(const std::vector<Term>& funs,
}
std::vector<Expr> exprs = termVectorToExprs(terms);
d_smtEngine->defineFunctionsRec(efuns, ebound_vars, exprs);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4222,6 +4448,7 @@ void Solver::echo(std::ostream& out, const std::string& str) const
*/
std::vector<Term> Solver::getAssertions(void) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
std::vector<Expr> assertions = d_smtEngine->getAssertions();
/* Can not use
* return std::vector<Term>(assertions.begin(), assertions.end());
@@ -4229,9 +4456,10 @@ std::vector<Term> Solver::getAssertions(void) const
std::vector<Term> res;
for (const Expr& e : assertions)
{
- res.push_back(Term(e));
+ res.push_back(Term(this, e));
}
return res;
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4239,15 +4467,19 @@ std::vector<Term> Solver::getAssertions(void) const
*/
std::vector<std::pair<Term, Term>> Solver::getAssignment(void) const
{
- // CHECK: produce-models set
- // CHECK: result sat
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+ CVC4_API_CHECK(CVC4::options::produceAssignments())
+ << "Cannot get assignment unless assignment generation is enabled "
+ "(try --produce-assignments)";
std::vector<std::pair<Expr, Expr>> assignment = d_smtEngine->getAssignment();
std::vector<std::pair<Term, Term>> res;
for (const auto& p : assignment)
{
- res.emplace_back(Term(p.first), Term(p.second));
+ res.emplace_back(Term(this, p.first), Term(this, p.second));
}
return res;
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4255,8 +4487,12 @@ std::vector<std::pair<Term, Term>> Solver::getAssignment(void) const
*/
std::string Solver::getInfo(const std::string& flag) const
{
- // CHECK: flag valid?
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_CHECK(d_smtEngine->isValidGetInfoFlag(flag))
+ << "Unrecognized flag for getInfo.";
+
return d_smtEngine->getInfo(flag).toString();
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4264,9 +4500,10 @@ std::string Solver::getInfo(const std::string& flag) const
*/
std::string Solver::getOption(const std::string& option) const
{
- // CHECK: option exists?
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
SExpr res = d_smtEngine->getOption(option);
return res.toString();
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4274,9 +4511,18 @@ std::string Solver::getOption(const std::string& option) const
*/
std::vector<Term> Solver::getUnsatAssumptions(void) const
{
- // CHECK: incremental?
- // CHECK: option produce-unsat-assumptions set?
- // CHECK: last check sat/valid result is unsat/invalid
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+ CVC4_API_CHECK(CVC4::options::incrementalSolving())
+ << "Cannot get unsat assumptions unless incremental solving is enabled "
+ "(try --incremental)";
+ CVC4_API_CHECK(CVC4::options::unsatAssumptions())
+ << "Cannot get unsat assumptions unless explicitly enabled "
+ "(try --produce-unsat-assumptions)";
+ CVC4_API_CHECK(d_smtEngine->getSmtMode()
+ == SmtEngine::SmtMode::SMT_MODE_UNSAT)
+ << "Cannot get unsat assumptions unless in unsat mode.";
+
std::vector<Expr> uassumptions = d_smtEngine->getUnsatAssumptions();
/* Can not use
* return std::vector<Term>(uassumptions.begin(), uassumptions.end());
@@ -4284,9 +4530,10 @@ std::vector<Term> Solver::getUnsatAssumptions(void) const
std::vector<Term> res;
for (const Expr& e : uassumptions)
{
- res.push_back(Term(e));
+ res.push_back(Term(this, e));
}
return res;
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4294,7 +4541,14 @@ std::vector<Term> Solver::getUnsatAssumptions(void) const
*/
std::vector<Term> Solver::getUnsatCore(void) const
{
- // CHECK: result unsat?
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+ CVC4_API_CHECK(CVC4::options::unsatCores())
+ << "Cannot get unsat core unless explicitly enabled "
+ "(try --produce-unsat-cores)";
+ CVC4_API_CHECK(d_smtEngine->getSmtMode()
+ == SmtEngine::SmtMode::SMT_MODE_UNSAT)
+ << "Cannot get unsat core unless in unsat mode.";
UnsatCore core = d_smtEngine->getUnsatCore();
/* Can not use
* return std::vector<Term>(core.begin(), core.end());
@@ -4302,9 +4556,10 @@ std::vector<Term> Solver::getUnsatCore(void) const
std::vector<Term> res;
for (const Expr& e : core)
{
- res.push_back(Term(e));
+ res.push_back(Term(this, e));
}
return res;
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4312,10 +4567,10 @@ std::vector<Term> Solver::getUnsatCore(void) const
*/
Term Solver::getValue(Term term) const
{
- // CHECK:
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(expr.getExprManager())
- return d_smtEngine->getValue(*term.d_expr);
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_SOLVER_CHECK_TERM(term);
+ return Term(this, d_smtEngine->getValue(*term.d_expr));
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4323,17 +4578,25 @@ Term Solver::getValue(Term term) const
*/
std::vector<Term> Solver::getValue(const std::vector<Term>& terms) const
{
- // CHECK:
- // for e in exprs:
- // NodeManager::fromExprManager(d_exprMgr)
- // == NodeManager::fromExprManager(e.getExprManager())
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+ CVC4_API_CHECK(CVC4::options::produceModels())
+ << "Cannot get value unless model generation is enabled "
+ "(try --produce-models)";
+ CVC4_API_CHECK(d_smtEngine->getSmtMode()
+ != SmtEngine::SmtMode::SMT_MODE_UNSAT)
+ << "Cannot get value when in unsat mode.";
std::vector<Term> res;
- for (const Term& t : terms)
+ for (size_t i = 0, n = terms.size(); i < n; ++i)
{
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == terms[i].d_solver, "term", terms[i], i)
+ << "term associated to this solver object";
/* Can not use emplace_back here since constructor is private. */
- res.push_back(Term(d_smtEngine->getValue(*t.d_expr)));
+ res.push_back(Term(this, d_smtEngine->getValue(*terms[i].d_expr)));
}
return res;
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4358,8 +4621,16 @@ void Solver::pop(uint32_t nscopes) const
void Solver::printModel(std::ostream& out) const
{
- // CHECK: produce-models?
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+ CVC4_API_CHECK(CVC4::options::produceModels())
+ << "Cannot get value unless model generation is enabled "
+ "(try --produce-models)";
+ CVC4_API_CHECK(d_smtEngine->getSmtMode()
+ != SmtEngine::SmtMode::SMT_MODE_UNSAT)
+ << "Cannot get value when in unsat mode.";
out << *d_smtEngine->getModel();
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4383,22 +4654,11 @@ void Solver::push(uint32_t nscopes) const
/**
* ( reset-assertions )
*/
-void Solver::resetAssertions(void) const { d_smtEngine->resetAssertions(); }
-
-// TODO: issue #2781
-void Solver::setLogicHelper(const std::string& logic) const
+void Solver::resetAssertions(void) const
{
- CVC4_API_CHECK(!d_smtEngine->isFullyInited())
- << "Invalid call to 'setLogic', solver is already fully initialized";
- try
- {
- CVC4::LogicInfo logic_info(logic);
- d_smtEngine->setLogic(logic_info);
- }
- catch (CVC4::IllegalArgumentException& e)
- {
- throw CVC4ApiException(e.getMessage());
- }
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ d_smtEngine->resetAssertions();
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4406,6 +4666,7 @@ void Solver::setLogicHelper(const std::string& logic) const
*/
void Solver::setInfo(const std::string& keyword, const std::string& value) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_EXPECTED(
keyword == "source" || keyword == "category" || keyword == "difficulty"
|| keyword == "filename" || keyword == "license" || keyword == "name"
@@ -4425,12 +4686,21 @@ void Solver::setInfo(const std::string& keyword, const std::string& value) const
<< "'sat', 'unsat' or 'unknown'";
d_smtEngine->setInfo(keyword, value);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
* ( set-logic <symbol> )
*/
-void Solver::setLogic(const std::string& logic) const { setLogicHelper(logic); }
+void Solver::setLogic(const std::string& logic) const
+{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_CHECK(!d_smtEngine->isFullyInited())
+ << "Invalid call to 'setLogic', solver is already fully initialized";
+ CVC4::LogicInfo logic_info(logic);
+ d_smtEngine->setLogic(logic_info);
+ CVC4_API_SOLVER_TRY_CATCH_END;
+}
/**
* ( set-option <option> )
@@ -4438,16 +4708,11 @@ void Solver::setLogic(const std::string& logic) const { setLogicHelper(logic); }
void Solver::setOption(const std::string& option,
const std::string& value) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_CHECK(!d_smtEngine->isFullyInited())
<< "Invalid call to 'setOption', solver is already fully initialized";
- try
- {
- d_smtEngine->setOption(option, value);
- }
- catch (CVC4::OptionException& e)
- {
- throw CVC4ApiException(e.getMessage());
- }
+ d_smtEngine->setOption(option, value);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
Term Solver::ensureTermSort(const Term& term, const Sort& sort) const
@@ -4471,7 +4736,8 @@ Term Solver::ensureTermSort(const Term& term, const Sort& sort) const
// constructors. We do this cast using division with 1. This has the
// advantage wrt using TO_REAL since (constant) division is always included
// in the theory.
- res = Term(d_exprMgr->mkExpr(extToIntKind(DIVISION),
+ res = Term(this,
+ d_exprMgr->mkExpr(extToIntKind(DIVISION),
*res.d_expr,
d_exprMgr->mkConst(CVC4::Rational(1))));
}
@@ -4483,13 +4749,14 @@ Term Solver::mkSygusVar(Sort sort, const std::string& symbol) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_NOT_NULL(sort);
+ CVC4_API_SOLVER_CHECK_SORT(sort);
Expr res = d_exprMgr->mkBoundVar(symbol, *sort.d_type);
(void)res.getType(true); /* kick off type checking */
d_smtEngine->declareSygusVar(symbol, res, *sort.d_type);
- return res;
+ return Term(this, res);
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -4497,12 +4764,22 @@ Term Solver::mkSygusVar(Sort sort, const std::string& symbol) const
Grammar Solver::mkSygusGrammar(const std::vector<Term>& boundVars,
const std::vector<Term>& ntSymbols) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_SIZE_CHECK_EXPECTED(!ntSymbols.empty(), ntSymbols)
<< "non-empty vector";
for (size_t i = 0, n = boundVars.size(); i < n; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == boundVars[i].d_solver, "bound variable", boundVars[i], i)
+ << "bound variable associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ boundVars[i].d_expr->getKind() == CVC4::Kind::BOUND_VARIABLE,
+ "bound variable",
+ boundVars[i],
+ i)
+ << "a bound variable";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
!boundVars[i].isNull(), "parameter term", boundVars[i], i)
<< "non-null term";
}
@@ -4510,11 +4787,21 @@ Grammar Solver::mkSygusGrammar(const std::vector<Term>& boundVars,
for (size_t i = 0, n = ntSymbols.size(); i < n; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == ntSymbols[i].d_solver, "term", ntSymbols[i], i)
+ << "term associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ ntSymbols[i].d_expr->getKind() == CVC4::Kind::BOUND_VARIABLE,
+ "bound variable",
+ ntSymbols[i],
+ i)
+ << "a bound variable";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
!ntSymbols[i].isNull(), "parameter term", ntSymbols[i], i)
<< "non-null term";
}
return Grammar(this, boundVars, ntSymbols);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
Term Solver::synthFun(const std::string& symbol,
@@ -4535,14 +4822,16 @@ Term Solver::synthFun(const std::string& symbol,
Term Solver::synthInv(const std::string& symbol,
const std::vector<Term>& boundVars) const
{
- return synthFunHelper(symbol, boundVars, d_exprMgr->booleanType(), true);
+ return synthFunHelper(
+ symbol, boundVars, Sort(this, d_exprMgr->booleanType()), true);
}
Term Solver::synthInv(const std::string& symbol,
const std::vector<Term>& boundVars,
Grammar& g) const
{
- return synthFunHelper(symbol, boundVars, d_exprMgr->booleanType(), true, &g);
+ return synthFunHelper(
+ symbol, boundVars, Sort(this, d_exprMgr->booleanType()), true, &g);
}
Term Solver::synthFunHelper(const std::string& symbol,
@@ -4561,10 +4850,20 @@ Term Solver::synthFunHelper(const std::string& symbol,
for (size_t i = 0, n = boundVars.size(); i < n; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == boundVars[i].d_solver, "bound variable", boundVars[i], i)
+ << "bound variable associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ boundVars[i].d_expr->getKind() == CVC4::Kind::BOUND_VARIABLE,
+ "bound variable",
+ boundVars[i],
+ i)
+ << "a bound variable";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
!boundVars[i].isNull(), "parameter term", boundVars[i], i)
<< "non-null term";
varTypes.push_back(boundVars[i].d_expr->getType());
}
+ CVC4_API_SOLVER_CHECK_SORT(sort);
if (g != nullptr)
{
@@ -4586,19 +4885,22 @@ Term Solver::synthFunHelper(const std::string& symbol,
isInv,
termVectorToExprs(boundVars));
- return fun;
+ return Term(this, fun);
CVC4_API_SOLVER_TRY_CATCH_END;
}
void Solver::addSygusConstraint(Term term) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_NOT_NULL(term);
+ CVC4_API_SOLVER_CHECK_TERM(term);
CVC4_API_ARG_CHECK_EXPECTED(
term.d_expr->getType() == d_exprMgr->booleanType(), term)
<< "boolean term";
d_smtEngine->assertSygusConstraint(*term.d_expr);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
void Solver::addSygusInvConstraint(Term inv,
@@ -4606,10 +4908,15 @@ void Solver::addSygusInvConstraint(Term inv,
Term trans,
Term post) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_NOT_NULL(inv);
+ CVC4_API_SOLVER_CHECK_TERM(inv);
CVC4_API_ARG_CHECK_NOT_NULL(pre);
+ CVC4_API_SOLVER_CHECK_TERM(pre);
CVC4_API_ARG_CHECK_NOT_NULL(trans);
+ CVC4_API_SOLVER_CHECK_TERM(trans);
CVC4_API_ARG_CHECK_NOT_NULL(post);
+ CVC4_API_SOLVER_CHECK_TERM(post);
CVC4_API_ARG_CHECK_EXPECTED(inv.d_expr->getType().isFunction(), inv)
<< "a function";
@@ -4644,13 +4951,21 @@ void Solver::addSygusInvConstraint(Term inv,
d_smtEngine->assertSygusInvConstraint(
*inv.d_expr, *pre.d_expr, *trans.d_expr, *post.d_expr);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
-Result Solver::checkSynth() const { return d_smtEngine->checkSynth(); }
+Result Solver::checkSynth() const
+{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ return d_smtEngine->checkSynth();
+ CVC4_API_SOLVER_TRY_CATCH_END;
+}
Term Solver::getSynthSolution(Term term) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_CHECK_NOT_NULL(term);
+ CVC4_API_SOLVER_CHECK_TERM(term);
std::map<CVC4::Expr, CVC4::Expr> map;
CVC4_API_CHECK(d_smtEngine->getSynthSolutions(map))
@@ -4661,17 +4976,22 @@ Term Solver::getSynthSolution(Term term) const
CVC4_API_CHECK(it != map.cend()) << "Synth solution not found for given term";
- return it->second;
+ return Term(this, it->second);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
std::vector<Term> Solver::getSynthSolutions(
const std::vector<Term>& terms) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
CVC4_API_ARG_SIZE_CHECK_EXPECTED(!terms.empty(), terms) << "non-empty vector";
for (size_t i = 0, n = terms.size(); i < n; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ this == terms[i].d_solver, "parameter term", terms[i], i)
+ << "parameter term associated to this solver object";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
!terms[i].isNull(), "parameter term", terms[i], i)
<< "non-null term";
}
@@ -4692,15 +5012,18 @@ std::vector<Term> Solver::getSynthSolutions(
CVC4_API_CHECK(it != map.cend())
<< "Synth solution not found for term at index " << i;
- synthSolution.push_back(it->second);
+ synthSolution.push_back(Term(this, it->second));
}
return synthSolution;
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
void Solver::printSynthSolution(std::ostream& out) const
{
+ CVC4_API_SOLVER_TRY_CATCH_BEGIN;
d_smtEngine->printSynthSolution(out);
+ CVC4_API_SOLVER_TRY_CATCH_END;
}
/**
@@ -4749,22 +5072,24 @@ std::set<Type> sortSetToTypes(const std::set<Sort>& sorts)
return types;
}
-std::vector<Term> exprVectorToTerms(const std::vector<Expr>& exprs)
+std::vector<Term> exprVectorToTerms(const Solver* slv,
+ const std::vector<Expr>& exprs)
{
std::vector<Term> terms;
for (size_t i = 0, esize = exprs.size(); i < esize; i++)
{
- terms.push_back(Term(exprs[i]));
+ terms.push_back(Term(slv, exprs[i]));
}
return terms;
}
-std::vector<Sort> typeVectorToSorts(const std::vector<Type>& types)
+std::vector<Sort> typeVectorToSorts(const Solver* slv,
+ const std::vector<Type>& types)
{
std::vector<Sort> sorts;
for (size_t i = 0, tsize = types.size(); i < tsize; i++)
{
- sorts.push_back(Sort(types[i]));
+ sorts.push_back(Sort(slv, types[i]));
}
return sorts;
}
diff --git a/src/api/cvc4cpp.h b/src/api/cvc4cpp.h
index 279453747..855ba4400 100644
--- a/src/api/cvc4cpp.h
+++ b/src/api/cvc4cpp.h
@@ -49,6 +49,8 @@ class Result;
namespace api {
+class Solver;
+
/* -------------------------------------------------------------------------- */
/* Exception */
/* -------------------------------------------------------------------------- */
@@ -199,10 +201,11 @@ class CVC4_PUBLIC Sort
// migrated to the new API. !!!
/**
* Constructor.
+ * @param slv the associated solver object
* @param t the internal type that is to be wrapped by this sort
* @return the Sort
*/
- Sort(const CVC4::Type& t);
+ Sort(const Solver* slv, const CVC4::Type& t);
/**
* Constructor.
@@ -589,6 +592,11 @@ class CVC4_PUBLIC Sort
bool isNullHelper() const;
/**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
+
+ /**
* The interal type wrapped by this sort.
* This is a shared_ptr rather than a unique_ptr to avoid overhead due to
* memory allocation (CVC4::Type is already ref counted, so this could be
@@ -637,19 +645,21 @@ class CVC4_PUBLIC Op
// migrated to the new API. !!!
/**
* Constructor for a single kind (non-indexed operator).
+ * @param slv the associated solver object
* @param k the kind of this Op
*/
- Op(const Kind k);
+ Op(const Solver* slv, const Kind k);
// !!! This constructor is only temporarily public until the parser is fully
// migrated to the new API. !!!
/**
* Constructor.
+ * @param slv the associated solver object
* @param k the kind of this Op
* @param e the internal expression that is to be wrapped by this term
* @return the Term
*/
- Op(const Kind k, const CVC4::Expr& e);
+ Op(const Solver* slv, const Kind k, const CVC4::Expr& e);
/**
* Destructor.
@@ -726,6 +736,11 @@ class CVC4_PUBLIC Op
*/
bool isIndexedHelper() const;
+ /**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
+
/* The kind of this operator. */
Kind d_kind;
@@ -758,10 +773,11 @@ class CVC4_PUBLIC Term
// migrated to the new API. !!!
/**
* Constructor.
+ * @param slv the associated solver object
* @param e the internal expression that is to be wrapped by this term
* @return the Term
*/
- Term(const CVC4::Expr& e);
+ Term(const Solver* slv, const CVC4::Expr& e);
/**
* Constructor.
@@ -955,10 +971,13 @@ class CVC4_PUBLIC Term
/**
* Constructor
+ * @param slv the associated solver object
* @param e a shared pointer to the expression that we're iterating over
* @param p the position of the iterator (e.g. which child it's on)
*/
- const_iterator(const std::shared_ptr<CVC4::Expr>& e, uint32_t p);
+ const_iterator(const Solver* slv,
+ const std::shared_ptr<CVC4::Expr>& e,
+ uint32_t p);
/**
* Copy constructor.
@@ -1005,6 +1024,10 @@ class CVC4_PUBLIC Term
Term operator*() const;
private:
+ /**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
/* The original expression to be iterated over */
std::shared_ptr<CVC4::Expr> d_orig_expr;
/* Keeps track of the iteration position */
@@ -1025,6 +1048,12 @@ class CVC4_PUBLIC Term
// to the new API. !!!
CVC4::Expr getExpr(void) const;
+ protected:
+ /**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
+
private:
/**
* Helper for isNull checks. This prevents calling an API function with
@@ -1138,14 +1167,13 @@ class DatatypeIterator;
class CVC4_PUBLIC DatatypeConstructorDecl
{
friend class DatatypeDecl;
+ friend class Solver;
public:
/**
- * Constructor.
- * @param name the name of the datatype constructor
- * @return the DatatypeConstructorDecl
+ * Nullary constructor for Cython.
*/
- DatatypeConstructorDecl(const std::string& name);
+ DatatypeConstructorDecl();
/**
* Add datatype selector declaration.
@@ -1170,6 +1198,19 @@ class CVC4_PUBLIC DatatypeConstructorDecl
private:
/**
+ * Constructor.
+ * @param slv the associated solver object
+ * @param name the name of the datatype constructor
+ * @return the DatatypeConstructorDecl
+ */
+ DatatypeConstructorDecl(const Solver* slv, const std::string& name);
+
+ /**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
+
+ /**
* The internal (intermediate) datatype constructor wrapped by this
* datatype constructor declaration.
* This is a shared_ptr rather than a unique_ptr since
@@ -1190,7 +1231,7 @@ class CVC4_PUBLIC DatatypeDecl
public:
/**
- * Nullary constructor for Cython
+ * Nullary constructor for Cython.
*/
DatatypeDecl();
@@ -1211,6 +1252,9 @@ class CVC4_PUBLIC DatatypeDecl
/** Is this Datatype declaration parametric? */
bool isParametric() const;
+ /**
+ * @return true if this DatatypeDecl is a null object
+ */
bool isNull() const;
/**
@@ -1228,24 +1272,24 @@ class CVC4_PUBLIC DatatypeDecl
private:
/**
* Constructor.
- * @param s the solver that created this datatype declaration
+ * @param slv the associated solver object
* @param name the name of the datatype
* @param isCoDatatype true if a codatatype is to be constructed
* @return the DatatypeDecl
*/
- DatatypeDecl(const Solver* s,
+ DatatypeDecl(const Solver* slv,
const std::string& name,
bool isCoDatatype = false);
/**
* Constructor for parameterized datatype declaration.
* Create sorts parameter with Solver::mkParamSort().
- * @param s the solver that created this datatype declaration
+ * @param slv the associated solver object
* @param name the name of the datatype
* @param param the sort parameter
* @param isCoDatatype true if a codatatype is to be constructed
*/
- DatatypeDecl(const Solver* s,
+ DatatypeDecl(const Solver* slv,
const std::string& name,
Sort param,
bool isCoDatatype = false);
@@ -1253,19 +1297,27 @@ class CVC4_PUBLIC DatatypeDecl
/**
* Constructor for parameterized datatype declaration.
* Create sorts parameter with Solver::mkParamSort().
- * @param s the solver that created this datatype declaration
+ * @param slv the associated solver object
* @param name the name of the datatype
* @param params a list of sort parameters
* @param isCoDatatype true if a codatatype is to be constructed
*/
- DatatypeDecl(const Solver* s,
+ DatatypeDecl(const Solver* slv,
const std::string& name,
const std::vector<Sort>& params,
bool isCoDatatype = false);
- // helper for isNull() to avoid calling API functions from other API functions
+ /**
+ * Helper for isNull checks. This prevents calling an API function with
+ * CVC4_API_CHECK_NOT_NULL
+ */
bool isNullHelper() const;
+ /**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
+
/* The internal (intermediate) datatype wrapped by this datatype
* declaration
* This is a shared_ptr rather than a unique_ptr since CVC4::Datatype is
@@ -1292,10 +1344,11 @@ class CVC4_PUBLIC DatatypeSelector
// migrated to the new API. !!!
/**
* Constructor.
+ * @param slv the associated solver object
* @param stor the internal datatype selector to be wrapped
* @return the DatatypeSelector
*/
- DatatypeSelector(const CVC4::DatatypeConstructorArg& stor);
+ DatatypeSelector(const Solver* slv, const CVC4::DatatypeConstructorArg& stor);
/**
* Destructor.
@@ -1325,6 +1378,11 @@ class CVC4_PUBLIC DatatypeSelector
private:
/**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
+
+ /**
* The internal datatype selector wrapped by this datatype selector.
* This is a shared_ptr rather than a unique_ptr since CVC4::Datatype is
* not ref counted.
@@ -1353,7 +1411,7 @@ class CVC4_PUBLIC DatatypeConstructor
* @param ctor the internal datatype constructor to be wrapped
* @return the DatatypeConstructor
*/
- DatatypeConstructor(const CVC4::DatatypeConstructor& ctor);
+ DatatypeConstructor(const Solver* slv, const CVC4::DatatypeConstructor& ctor);
/**
* Destructor.
@@ -1466,16 +1524,27 @@ class CVC4_PUBLIC DatatypeConstructor
private:
/**
* Constructor.
+ * @param slv the associated Solver object
* @param ctor the internal datatype constructor to iterate over
* @param true if this is a begin() iterator
*/
- const_iterator(const CVC4::DatatypeConstructor& ctor, bool begin);
+ const_iterator(const Solver* slv,
+ const CVC4::DatatypeConstructor& ctor,
+ bool begin);
+
+ /**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
+
/* A pointer to the list of selectors of the internal datatype
* constructor to iterate over.
* This pointer is maintained for operators == and != only. */
const void* d_int_stors;
+
/* The list of datatype selector (wrappers) to iterate over. */
std::vector<DatatypeSelector> d_stors;
+
/* The current index of the iterator. */
size_t d_idx;
};
@@ -1501,6 +1570,12 @@ class CVC4_PUBLIC DatatypeConstructor
* @return the selector object for the name
*/
DatatypeSelector getSelectorForName(const std::string& name) const;
+
+ /**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
+
/**
* The internal datatype constructor wrapped by this datatype constructor.
* This is a shared_ptr rather than a unique_ptr since CVC4::Datatype is
@@ -1525,7 +1600,7 @@ class CVC4_PUBLIC Datatype
* @param dtype the internal datatype to be wrapped
* @return the Datatype
*/
- Datatype(const CVC4::Datatype& dtype);
+ Datatype(const Solver* slv, const CVC4::Datatype& dtype);
// Nullary constructor for Cython
Datatype();
@@ -1654,16 +1729,25 @@ class CVC4_PUBLIC Datatype
private:
/**
* Constructor.
+ * @param slv the associated Solver object
* @param dtype the internal datatype to iterate over
* @param true if this is a begin() iterator
*/
- const_iterator(const CVC4::Datatype& dtype, bool begin);
+ const_iterator(const Solver* slv, const CVC4::Datatype& dtype, bool begin);
+
+ /**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
+
/* A pointer to the list of constructors of the internal datatype
* to iterate over.
* This pointer is maintained for operators == and != only. */
const void* d_int_ctors;
+
/* The list of datatype constructor (wrappers) to iterate over. */
std::vector<DatatypeConstructor> d_ctors;
+
/* The current index of the iterator. */
size_t d_idx;
};
@@ -1689,6 +1773,12 @@ class CVC4_PUBLIC Datatype
* @return the constructor object for the name
*/
DatatypeConstructor getConstructorForName(const std::string& name) const;
+
+ /**
+ * The associated solver object.
+ */
+ const Solver* d_solver;
+
/**
* The internal datatype wrapped by this datatype.
* This is a shared_ptr rather than a unique_ptr since CVC4::Datatype is
@@ -1793,11 +1883,11 @@ class CVC4_PUBLIC Grammar
private:
/**
* Constructor.
- * @param s the solver that created this grammar
+ * @param slv the solver that created this grammar
* @param sygusVars the input variables to synth-fun/synth-var
* @param ntSymbols the non-terminals of this grammar
*/
- Grammar(const Solver* s,
+ Grammar(const Solver* slv,
const std::vector<Term>& sygusVars,
const std::vector<Term>& ntSymbols);
@@ -1863,7 +1953,7 @@ class CVC4_PUBLIC Grammar
void addSygusConstructorVariables(DatatypeDecl& dt, Sort sort) const;
/** The solver that created this grammar. */
- const Solver* d_s;
+ const Solver* d_solver;
/** Input variables to the corresponding function/invariant to synthesize.*/
std::vector<Term> d_sygusVars;
/** The non-terminal symbols of this grammar. */
@@ -2613,6 +2703,12 @@ class CVC4_PUBLIC Solver
Term mkVar(Sort sort, const std::string& symbol = std::string()) const;
/* .................................................................... */
+ /* Create datatype constructor declarations */
+ /* .................................................................... */
+
+ DatatypeConstructorDecl mkDatatypeConstructorDecl(const std::string& name);
+
+ /* .................................................................... */
/* Create datatype declarations */
/* .................................................................... */
@@ -3142,9 +3238,11 @@ class CVC4_PUBLIC Solver
// new API. !!!
std::vector<Expr> termVectorToExprs(const std::vector<Term>& terms);
std::vector<Type> sortVectorToTypes(const std::vector<Sort>& sorts);
-std::vector<Term> exprVectorToTerms(const std::vector<Expr>& terms);
-std::vector<Sort> typeVectorToSorts(const std::vector<Type>& sorts);
std::set<Type> sortSetToTypes(const std::set<Sort>& sorts);
+std::vector<Term> exprVectorToTerms(const Solver* slv,
+ const std::vector<Expr>& terms);
+std::vector<Sort> typeVectorToSorts(const Solver* slv,
+ const std::vector<Type>& sorts);
} // namespace api
diff --git a/src/api/python/cvc4.pxd b/src/api/python/cvc4.pxd
index d81d0c0bf..1e0b9893b 100644
--- a/src/api/python/cvc4.pxd
+++ b/src/api/python/cvc4.pxd
@@ -54,7 +54,6 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api":
cdef cppclass DatatypeConstructorDecl:
- DatatypeConstructorDecl(const string& name) except +
void addSelector(const string& name, Sort sort) except +
void addSelectorSelf(const string& name) except +
string toString() except +
@@ -81,15 +80,22 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api":
T getIndices[T]() except +
string toString() except +
+ cdef cppclass OpHashFunction:
+ OpHashFunction() except +
+ size_t operator()(const Op & o) except +
+
cdef cppclass Result:
- # Note: don't even need constructor
+ Result() except+
+ bint isNull() except +
bint isSat() except +
bint isUnsat() except +
bint isSatUnknown() except +
bint isEntailed() except +
bint isNotEntailed() except +
bint isEntailmentUnknown() except +
+ bint operator==(const Result& r) except +
+ bint operator!=(const Result& r) except +
string getUnknownExplanation() except +
string toString() except +
@@ -156,6 +162,7 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api":
# default value for symbol defined in cvc4cpp.h
Term mkConst(Sort sort) except +
Term mkVar(Sort sort, const string& symbol) except +
+ DatatypeConstructorDecl mkDatatypeConstructorDecl(const string& name) except +
DatatypeDecl mkDatatypeDecl(const string& name) except +
DatatypeDecl mkDatatypeDecl(const string& name, bint isCoDatatype) except +
DatatypeDecl mkDatatypeDecl(const string& name, Sort param) except +
@@ -229,12 +236,17 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api":
bint isUninterpretedSortParameterized() except +
string toString() except +
+ cdef cppclass SortHashFunction:
+ SortHashFunction() except +
+ size_t operator()(const Sort & s) except +
+
cdef cppclass Term:
Term()
bint operator==(const Term&) except +
bint operator!=(const Term&) except +
Kind getKind() except +
Sort getSort() except +
+ Term substitute(const vector[Term] es, const vector[Term] & reps) except +
bint hasOp() except +
Op getOp() except +
bint isNull() except +
@@ -255,6 +267,10 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api":
const_iterator begin() except +
const_iterator end() except +
+ cdef cppclass TermHashFunction:
+ TermHashFunction() except +
+ size_t operator()(const Term & t) except +
+
cdef extern from "api/cvc4cpp.h" namespace "CVC4::api::RoundingMode":
cdef RoundingMode ROUND_NEAREST_TIES_TO_EVEN,
diff --git a/src/api/python/cvc4.pxi b/src/api/python/cvc4.pxi
index 1489b34a6..827c53ef4 100644
--- a/src/api/python/cvc4.pxi
+++ b/src/api/python/cvc4.pxi
@@ -15,11 +15,14 @@ from cvc4 cimport DatatypeSelector as c_DatatypeSelector
from cvc4 cimport Result as c_Result
from cvc4 cimport RoundingMode as c_RoundingMode
from cvc4 cimport Op as c_Op
+from cvc4 cimport OpHashFunction as c_OpHashFunction
from cvc4 cimport Solver as c_Solver
from cvc4 cimport Sort as c_Sort
+from cvc4 cimport SortHashFunction as c_SortHashFunction
from cvc4 cimport ROUND_NEAREST_TIES_TO_EVEN, ROUND_TOWARD_POSITIVE
from cvc4 cimport ROUND_TOWARD_ZERO, ROUND_NEAREST_TIES_TO_AWAY
from cvc4 cimport Term as c_Term
+from cvc4 cimport TermHashFunction as c_TermHashFunction
from cvc4kinds cimport Kind as c_Kind
@@ -49,7 +52,12 @@ def expand_list_arg(num_req_args=0):
### can omit spaces between unrelated oneliners
### always use c++ default arguments
#### only use default args of None at python level
-#### Result class can have default because it's pure python
+
+
+## Objects for hashing
+cdef c_OpHashFunction cophash = c_OpHashFunction()
+cdef c_SortHashFunction csorthash = c_SortHashFunction()
+cdef c_TermHashFunction ctermhash = c_TermHashFunction()
cdef class Datatype:
@@ -125,12 +133,14 @@ cdef class DatatypeConstructor:
cdef class DatatypeConstructorDecl:
- cdef c_DatatypeConstructorDecl* cddc
- def __cinit__(self, str name):
- self.cddc = new c_DatatypeConstructorDecl(name.encode())
+ cdef c_DatatypeConstructorDecl cddc
+
+ def __cinit__(self):
+ pass
def addSelector(self, str name, Sort sort):
self.cddc.addSelector(name.encode(), sort.csort)
+
def addSelectorSelf(self, str name):
self.cddc.addSelectorSelf(name.encode())
@@ -147,7 +157,7 @@ cdef class DatatypeDecl:
pass
def addConstructor(self, DatatypeConstructorDecl ctor):
- self.cdd.addConstructor(ctor.cddc[0])
+ self.cdd.addConstructor(ctor.cddc)
def isParametric(self):
return self.cdd.isParametric()
@@ -188,6 +198,9 @@ cdef class Op:
def __repr__(self):
return self.cop.toString().decode()
+ def __hash__(self):
+ return cophash(self.cop)
+
def getKind(self):
return kind(<int> self.cop.getKind())
@@ -217,54 +230,47 @@ cdef class Op:
return indices
-class Result:
- def __init__(self, name, explanation=""):
- name = name.lower()
- incomplete = False
- if "(incomplete)" in name:
- incomplete = True
- name = name.replace("(incomplete)", "").strip()
- assert name in {"sat", "unsat", "valid", "invalid", "unknown"}, \
- "can't interpret result = {}".format(name)
-
- self._name = name
- self._explanation = explanation
- self._incomplete = incomplete
-
- def __bool__(self):
- if self._name in {"sat", "valid"}:
- return True
- elif self._name in {"unsat", "invalid"}:
- return False
- elif self._name == "unknown":
- raise RuntimeError("Cannot interpret 'unknown' result as a Boolean")
- else:
- assert False, "Unhandled result=%s"%self._name
+cdef class Result:
+ cdef c_Result cr
+ def __cinit__(self):
+ # gets populated by solver
+ self.cr = c_Result()
- def __eq__(self, other):
- if not isinstance(other, Result):
- return False
+ def isNull(self):
+ return self.cr.isNull()
- return self._name == other._name
+ def isSat(self):
+ return self.cr.isSat()
- def __ne__(self, other):
- return not self.__eq__(other)
+ def isUnsat(self):
+ return self.cr.isUnsat()
- def __str__(self):
- return self._name
+ def isSatUnknown(self):
+ return self.cr.isSatUnknown()
- def __repr__(self):
- return self._name
+ def isEntailed(self):
+ return self.cr.isEntailed()
+
+ def isNotEntailed(self):
+ return self.cr.isNotEntailed()
+
+ def isEntailmentUnknown(self):
+ return self.cr.isEntailmentUnknown()
- def isUnknown(self):
- return self._name == "unknown"
+ def __eq__(self, Result other):
+ return self.cr == other.cr
- def isIncomplete(self):
- return self._incomplete
+ def __ne__(self, Result other):
+ return self.cr != other.cr
- @property
- def explanation(self):
- return self._explanation
+ def getUnknownExplanation(self):
+ return self.cr.getUnknownExplanation().decode()
+
+ def __str__(self):
+ return self.cr.toString().decode()
+
+ def __repr__(self):
+ return self.cr.toString().decode()
cdef class RoundingMode:
@@ -663,6 +669,11 @@ cdef class Solver:
(<str?> symbol).encode())
return term
+ def mkDatatypeConstructorDecl(self, str name):
+ cdef DatatypeConstructorDecl ddc = DatatypeConstructorDecl()
+ ddc.cddc = self.csolver.mkDatatypeConstructorDecl(name.encode())
+ return ddc
+
def mkDatatypeDecl(self, str name, sorts_or_bool=None, isCoDatatype=None):
cdef DatatypeDecl dd = DatatypeDecl()
cdef vector[c_Sort] v
@@ -716,12 +727,9 @@ cdef class Solver:
self.csolver.assertFormula(term.cterm)
def checkSat(self):
- cdef c_Result r = self.csolver.checkSat()
- name = r.toString().decode()
- explanation = ""
- if r.isSatUnknown():
- explanation = r.getUnknownExplanation().decode()
- return Result(name, explanation)
+ cdef Result r = Result()
+ r.cr = self.csolver.checkSat()
+ return r
@expand_list_arg(num_req_args=0)
def checkSatAssuming(self, *assumptions):
@@ -732,17 +740,13 @@ cdef class Solver:
where assumptions can also be comma-separated arguments of
type (boolean) Term
'''
- cdef c_Result r
+ cdef Result r = Result()
# used if assumptions is a list of terms
cdef vector[c_Term] v
for a in assumptions:
v.push_back((<Term?> a).cterm)
- r = self.csolver.checkSatAssuming(<const vector[c_Term]&> v)
- name = r.toString().decode()
- explanation = ""
- if r.isSatUnknown():
- explanation = r.getUnknownExplanation().decode()
- return Result(name, explanation)
+ r.cr = self.csolver.checkSatAssuming(<const vector[c_Term]&> v)
+ return r
@expand_list_arg(num_req_args=0)
def checkEntailed(self, *assumptions):
@@ -753,17 +757,13 @@ cdef class Solver:
where assumptions can also be comma-separated arguments of
type (boolean) Term
'''
- cdef c_Result r
+ cdef Result r = Result()
# used if assumptions is a list of terms
cdef vector[c_Term] v
for a in assumptions:
v.push_back((<Term?> a).cterm)
- r = self.csolver.checkEntailed(<const vector[c_Term]&> v)
- name = r.toString().decode()
- explanation = ""
- if r.isEntailmentUnknown():
- explanation = r.getUnknownExplanation().decode()
- return Result(name, explanation)
+ r.cr = self.csolver.checkEntailed(<const vector[c_Term]&> v)
+ return r
@expand_list_arg(num_req_args=1)
def declareDatatype(self, str symbol, *ctors):
@@ -778,7 +778,7 @@ cdef class Solver:
cdef vector[c_DatatypeConstructorDecl] v
for c in ctors:
- v.push_back((<DatatypeConstructorDecl?> c).cddc[0])
+ v.push_back((<DatatypeConstructorDecl?> c).cddc)
sort.csort = self.csolver.declareDatatype(symbol.encode(), v)
return sort
@@ -953,6 +953,9 @@ cdef class Sort:
def __repr__(self):
return self.csort.toString().decode()
+ def __hash__(self):
+ return csorthash(self.csort)
+
def isBoolean(self):
return self.csort.isBoolean()
@@ -1054,6 +1057,9 @@ cdef class Term:
term.cterm = ci
yield term
+ def __hash__(self):
+ return ctermhash(self.cterm)
+
def getKind(self):
return kind(<int> self.cterm.getKind())
@@ -1062,6 +1068,23 @@ cdef class Term:
sort.csort = self.cterm.getSort()
return sort
+ def substitute(self, list es, list replacements):
+ cdef vector[c_Term] ces
+ cdef vector[c_Term] creplacements
+ cdef Term term = Term()
+
+ if len(es) != len(replacements):
+ raise RuntimeError("Expecting list inputs to substitute to "
+ "have the same length but got: "
+ "{} and {}".format(len(es), len(replacements)))
+
+ for e, r in zip(es, replacements):
+ ces.push_back((<Term?> e).cterm)
+ creplacements.push_back((<Term?> r).cterm)
+
+ term.cterm = self.cterm.substitute(ces, creplacements)
+ return term
+
def hasOp(self):
return self.cterm.hasOp()
diff --git a/src/bindings/java/CMakeLists.txt b/src/bindings/java/CMakeLists.txt
index c5abf9b27..4e1b96af9 100644
--- a/src/bindings/java/CMakeLists.txt
+++ b/src/bindings/java/CMakeLists.txt
@@ -65,6 +65,7 @@ set(gen_java_files
${CMAKE_CURRENT_BINARY_DIR}/ExprHashFunction.java
${CMAKE_CURRENT_BINARY_DIR}/ExprManager.java
${CMAKE_CURRENT_BINARY_DIR}/ExprManagerMapCollection.java
+ ${CMAKE_CURRENT_BINARY_DIR}/ExprSequence.java
${CMAKE_CURRENT_BINARY_DIR}/FloatingPoint.java
${CMAKE_CURRENT_BINARY_DIR}/FloatingPointConvertSort.java
${CMAKE_CURRENT_BINARY_DIR}/FloatingPointSize.java
@@ -137,6 +138,7 @@ set(gen_java_files
${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_std__vectorT_std__pairT_CVC4__Expr_CVC4__Expr_t_t.java
${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_std__vectorT_std__vectorT_std__string_t_t.java
${CMAKE_CURRENT_BINARY_DIR}/SelectorType.java
+ ${CMAKE_CURRENT_BINARY_DIR}/SequenceType.java
${CMAKE_CURRENT_BINARY_DIR}/SetType.java
${CMAKE_CURRENT_BINARY_DIR}/SmtEngine.java
${CMAKE_CURRENT_BINARY_DIR}/SortConstructorType.java
diff --git a/src/cvc4.i b/src/cvc4.i
index 01fd088a8..6b3598a2f 100644
--- a/src/cvc4.i
+++ b/src/cvc4.i
@@ -286,6 +286,7 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters;
%include "expr/array_store_all.i"
%include "expr/ascription_type.i"
%include "expr/emptyset.i"
+%include "expr/expr_sequence.i"
%include "expr/datatype.i"
%include "expr/record.i"
%include "proof/unsat_core.i"
diff --git a/src/expr/CMakeLists.txt b/src/expr/CMakeLists.txt
index f2a4377d0..3d41b7a72 100644
--- a/src/expr/CMakeLists.txt
+++ b/src/expr/CMakeLists.txt
@@ -12,6 +12,8 @@ libcvc4_add_sources(
expr_iomanip.cpp
expr_iomanip.h
expr_manager_scope.h
+ expr_sequence.cpp
+ expr_sequence.h
kind_map.h
match_trie.cpp
match_trie.h
@@ -32,6 +34,8 @@ libcvc4_add_sources(
node_traversal.h
node_value.cpp
node_value.h
+ sequence.cpp
+ sequence.h
node_visitor.h
proof.cpp
proof.h
@@ -47,6 +51,8 @@ libcvc4_add_sources(
proof_rule.h
proof_skolem_cache.cpp
proof_skolem_cache.h
+ proof_step_buffer.cpp
+ proof_step_buffer.h
symbol_table.cpp
symbol_table.h
term_canonize.cpp
diff --git a/src/expr/expr.i b/src/expr/expr.i
index 14ccf213c..14228d7c5 100644
--- a/src/expr/expr.i
+++ b/src/expr/expr.i
@@ -146,6 +146,7 @@ namespace CVC4 {
%template(getConstBoolean) CVC4::Expr::getConst<bool>;
%template(getConstDatatypeIndexConstant) CVC4::Expr::getConst<CVC4::DatatypeIndexConstant>;
%template(getConstEmptySet) CVC4::Expr::getConst<CVC4::EmptySet>;
+%template(getConstExprSequence) CVC4::Expr::getConst<CVC4::ExprSequence>;
%template(getConstFloatingPoint) CVC4::Expr::getConst<CVC4::FloatingPoint>;
%template(getConstKind) CVC4::Expr::getConst<CVC4::kind::Kind_t>;
%template(getConstRational) CVC4::Expr::getConst<CVC4::Rational>;
diff --git a/src/expr/expr_manager.i b/src/expr/expr_manager.i
index f8251e752..5a5e7a9d4 100644
--- a/src/expr/expr_manager.i
+++ b/src/expr/expr_manager.i
@@ -57,6 +57,7 @@
%template(mkConst) CVC4::ExprManager::mkConst<CVC4::Rational>;
%template(mkConst) CVC4::ExprManager::mkConst<CVC4::BitVector>;
%template(mkConst) CVC4::ExprManager::mkConst<CVC4::EmptySet>;
+%template(mkConst) CVC4::ExprManager::mkConst<CVC4::ExprSequence>;
%template(mkConst) CVC4::ExprManager::mkConst<CVC4::String>;
#ifdef SWIGPYTHON
/* The python bindings cannot differentiate between bool and other basic
diff --git a/src/expr/expr_sequence.cpp b/src/expr/expr_sequence.cpp
new file mode 100644
index 000000000..4f761c8f7
--- /dev/null
+++ b/src/expr/expr_sequence.cpp
@@ -0,0 +1,98 @@
+/********************* */
+/*! \file expr_sequence.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of the sequence data type.
+ **/
+
+#include "expr/expr_sequence.h"
+
+#include "expr/expr.h"
+#include "expr/node.h"
+#include "expr/sequence.h"
+#include "expr/type.h"
+#include "expr/type_node.h"
+
+namespace CVC4 {
+
+ExprSequence::ExprSequence(const Type& t, const std::vector<Expr>& seq)
+{
+ d_type.reset(new Type(t));
+ std::vector<Node> nseq;
+ for (const Expr& e : seq)
+ {
+ nseq.push_back(Node::fromExpr(e));
+ }
+ d_sequence.reset(new Sequence(TypeNode::fromType(t), nseq));
+}
+ExprSequence::~ExprSequence() {}
+
+ExprSequence::ExprSequence(const ExprSequence& other)
+ : d_type(new Type(other.getType())),
+ d_sequence(new Sequence(other.getSequence()))
+{
+}
+
+ExprSequence& ExprSequence::operator=(const ExprSequence& other)
+{
+ (*d_type) = other.getType();
+ (*d_sequence) = other.getSequence();
+ return *this;
+}
+
+const Type& ExprSequence::getType() const { return *d_type; }
+
+const Sequence& ExprSequence::getSequence() const { return *d_sequence; }
+
+bool ExprSequence::operator==(const ExprSequence& es) const
+{
+ return getType() == es.getType() && getSequence() == es.getSequence();
+}
+
+bool ExprSequence::operator!=(const ExprSequence& es) const
+{
+ return !(*this == es);
+}
+
+bool ExprSequence::operator<(const ExprSequence& es) const
+{
+ return (getType() < es.getType())
+ || (getType() == es.getType() && getSequence() < es.getSequence());
+}
+
+bool ExprSequence::operator<=(const ExprSequence& es) const
+{
+ return (getType() < es.getType())
+ || (getType() == es.getType() && getSequence() <= es.getSequence());
+}
+
+bool ExprSequence::operator>(const ExprSequence& es) const
+{
+ return !(*this <= es);
+}
+
+bool ExprSequence::operator>=(const ExprSequence& es) const
+{
+ return !(*this < es);
+}
+
+std::ostream& operator<<(std::ostream& os, const ExprSequence& s)
+{
+ return os << "__expr_sequence__(" << s.getType() << ", " << s.getSequence()
+ << ")";
+}
+
+size_t ExprSequenceHashFunction::operator()(const ExprSequence& es) const
+{
+ uint64_t hash = fnv1a::fnv1a_64(TypeHashFunction()(es.getType()));
+ return static_cast<size_t>(SequenceHashFunction()(es.getSequence()), hash);
+}
+
+} // namespace CVC4
diff --git a/src/expr/expr_sequence.h b/src/expr/expr_sequence.h
new file mode 100644
index 000000000..9515a9244
--- /dev/null
+++ b/src/expr/expr_sequence.h
@@ -0,0 +1,76 @@
+/********************* */
+/*! \file expr_sequence.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 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 The sequence data type.
+ **/
+
+#include "cvc4_public.h"
+
+#ifndef CVC4__EXPR__EXPR_SEQUENCE_H
+#define CVC4__EXPR__EXPR_SEQUENCE_H
+
+#include <iosfwd>
+#include <memory>
+#include <vector>
+
+namespace CVC4 {
+
+// messy; Expr needs ExprSequence (because it's the payload of a
+// CONSTANT-kinded expression), and ExprSequence needs Expr.
+class Type;
+class Expr;
+class Sequence;
+
+/** The CVC4 sequence class
+ *
+ * This data structure is the domain of values for the sequence type.
+ */
+class CVC4_PUBLIC ExprSequence
+{
+ public:
+ /** constructors for ExprSequence
+ *
+ * Internally, a CVC4::ExprSequence is represented by a vector of Nodes
+ * (d_seq), where each Node in this vector must be a constant.
+ */
+ ExprSequence(const Type& type, const std::vector<Expr>& seq);
+ ~ExprSequence();
+
+ ExprSequence(const ExprSequence& other);
+ ExprSequence& operator=(const ExprSequence& other);
+
+ bool operator==(const ExprSequence& es) const;
+ bool operator!=(const ExprSequence& es) const;
+ bool operator<(const ExprSequence& es) const;
+ bool operator<=(const ExprSequence& es) const;
+ bool operator>(const ExprSequence& es) const;
+ bool operator>=(const ExprSequence& es) const;
+
+ const Type& getType() const;
+ const Sequence& getSequence() const;
+
+ private:
+ /** The element type of the sequence */
+ std::unique_ptr<Type> d_type;
+ /** The data of the sequence */
+ std::unique_ptr<Sequence> d_sequence;
+}; /* class ExprSequence */
+
+struct CVC4_PUBLIC ExprSequenceHashFunction
+{
+ size_t operator()(const ::CVC4::ExprSequence& s) const;
+}; /* struct ExprSequenceHashFunction */
+
+std::ostream& operator<<(std::ostream& os, const ExprSequence& s) CVC4_PUBLIC;
+
+} // namespace CVC4
+
+#endif /* CVC4__EXPR__SEQUENCE_H */
diff --git a/src/expr/expr_sequence.i b/src/expr/expr_sequence.i
new file mode 100644
index 000000000..42e130466
--- /dev/null
+++ b/src/expr/expr_sequence.i
@@ -0,0 +1,18 @@
+%{
+#include "expr/expr_sequence.h"
+%}
+
+%rename(equals) CVC4::ExprSequence::operator==(const ExprSequence&) const;
+%ignore CVC4::ExprSequence::operator!=(const ExprSequence&) const;
+%ignore CVC4::ExprSequence::getSequence() const;
+
+%rename(less) CVC4::ExprSequence::operator<(const ExprSequence&) const;
+%rename(lessEqual) CVC4::ExprSequence::operator<=(const ExprSequence&) const;
+%rename(greater) CVC4::ExprSequence::operator>(const ExprSequence&) const;
+%rename(greaterEqual) CVC4::ExprSequence::operator>=(const ExprSequence&) const;
+
+%rename(apply) CVC4::ExprSequenceHashFunction::operator()(const ExprSequence&) const;
+
+%ignore CVC4::operator<<(std::ostream& out, const ExprSequence& es);
+
+%include "expr/expr_sequence.h"
diff --git a/src/expr/node_manager.cpp b/src/expr/node_manager.cpp
index feec9b782..427afd5af 100644
--- a/src/expr/node_manager.cpp
+++ b/src/expr/node_manager.cpp
@@ -495,6 +495,17 @@ Node NodeManager::mkSkolem(const std::string& prefix, const TypeNode& type, cons
return n;
}
+TypeNode NodeManager::mkSequenceType(TypeNode elementType)
+{
+ CheckArgument(
+ !elementType.isNull(), elementType, "unexpected NULL element type");
+ CheckArgument(elementType.isFirstClass(),
+ elementType,
+ "cannot store types that are not first-class in sequences. Try "
+ "option --uf-ho.");
+ return mkTypeNode(kind::SEQUENCE_TYPE, elementType);
+}
+
TypeNode NodeManager::mkConstructorType(const DatatypeConstructor& constructor,
TypeNode range) {
vector<TypeNode> sorts;
@@ -854,4 +865,26 @@ void NodeManager::debugHook(int debugFlag){
// For debugging purposes only, DO NOT CHECK IN ANY CODE!
}
+Kind NodeManager::getKindForFunction(TNode fun)
+{
+ TypeNode tn = fun.getType();
+ if (tn.isFunction())
+ {
+ return kind::APPLY_UF;
+ }
+ else if (tn.isConstructor())
+ {
+ return kind::APPLY_CONSTRUCTOR;
+ }
+ else if (tn.isSelector())
+ {
+ return kind::APPLY_SELECTOR;
+ }
+ else if (tn.isTester())
+ {
+ return kind::APPLY_TESTER;
+ }
+ return kind::UNDEFINED_KIND;
+}
+
}/* CVC4 namespace */
diff --git a/src/expr/node_manager.h b/src/expr/node_manager.h
index aea49d979..1fab328e9 100644
--- a/src/expr/node_manager.h
+++ b/src/expr/node_manager.h
@@ -444,6 +444,20 @@ public:
/** Get a Kind from an operator expression */
static inline Kind operatorToKind(TNode n);
+ /** Get corresponding application kind for function
+ *
+ * Different functional nodes are applied differently, according to their
+ * type. For example, uninterpreted functions (of FUNCTION_TYPE) are applied
+ * via APPLY_UF, while constructors (of CONSTRUCTOR_TYPE) via
+ * APPLY_CONSTRUCTOR. This method provides the correct application according
+ * to which functional type fun has.
+ *
+ * @param fun The functional node
+ * @return the correct application kind for fun. If fun's type is not function
+ * like (see TypeNode::isFunctionLike), then UNDEFINED_KIND is returned.
+ */
+ static Kind getKindForFunction(TNode fun);
+
// general expression-builders
/** Create a node with one child. */
@@ -875,9 +889,12 @@ public:
/** Make the type of arrays with the given parameterization */
inline TypeNode mkArrayType(TypeNode indexType, TypeNode constituentType);
- /** Make the type of arrays with the given parameterization */
+ /** Make the type of set with the given parameterization */
inline TypeNode mkSetType(TypeNode elementType);
+ /** Make the type of sequences with the given parameterization */
+ TypeNode mkSequenceType(TypeNode elementType);
+
/** Make a type representing a constructor with the given parameterization */
TypeNode mkConstructorType(const DatatypeConstructor& constructor, TypeNode range);
/**
diff --git a/src/expr/proof_rule.cpp b/src/expr/proof_rule.cpp
index e555f5691..595e1d5f7 100644
--- a/src/expr/proof_rule.cpp
+++ b/src/expr/proof_rule.cpp
@@ -25,7 +25,66 @@ const char* toString(PfRule id)
//================================================= Core rules
case PfRule::ASSUME: return "ASSUME";
case PfRule::SCOPE: return "SCOPE";
-
+ case PfRule::SUBS: return "SUBS";
+ case PfRule::REWRITE: return "REWRITE";
+ case PfRule::MACRO_SR_EQ_INTRO: return "MACRO_SR_EQ_INTRO";
+ case PfRule::MACRO_SR_PRED_INTRO: return "MACRO_SR_PRED_INTRO";
+ case PfRule::MACRO_SR_PRED_ELIM: return "MACRO_SR_PRED_ELIM";
+ case PfRule::MACRO_SR_PRED_TRANSFORM: return "MACRO_SR_PRED_TRANSFORM";
+ //================================================= Equality rules
+ case PfRule::REFL: return "REFL";
+ case PfRule::SYMM: return "SYMM";
+ case PfRule::TRANS: return "TRANS";
+ case PfRule::CONG: return "CONG";
+ case PfRule::TRUE_INTRO: return "TRUE_INTRO";
+ case PfRule::TRUE_ELIM: return "TRUE_ELIM";
+ case PfRule::FALSE_INTRO: return "FALSE_INTRO";
+ case PfRule::FALSE_ELIM: return "FALSE_ELIM";
+ //================================================= Boolean rules
+ case PfRule::SPLIT: return "SPLIT";
+ case PfRule::AND_ELIM: return "AND_ELIM";
+ case PfRule::AND_INTRO: return "AND_INTRO";
+ case PfRule::NOT_OR_ELIM: return "NOT_OR_ELIM";
+ case PfRule::IMPLIES_ELIM: return "IMPLIES_ELIM";
+ case PfRule::NOT_IMPLIES_ELIM1: return "NOT_IMPLIES_ELIM1";
+ case PfRule::NOT_IMPLIES_ELIM2: return "NOT_IMPLIES_ELIM2";
+ case PfRule::EQUIV_ELIM1: return "EQUIV_ELIM1";
+ case PfRule::EQUIV_ELIM2: return "EQUIV_ELIM2";
+ case PfRule::NOT_EQUIV_ELIM1: return "NOT_EQUIV_ELIM1";
+ case PfRule::NOT_EQUIV_ELIM2: return "NOT_EQUIV_ELIM2";
+ case PfRule::XOR_ELIM1: return "XOR_ELIM1";
+ case PfRule::XOR_ELIM2: return "XOR_ELIM2";
+ case PfRule::NOT_XOR_ELIM1: return "NOT_XOR_ELIM1";
+ case PfRule::NOT_XOR_ELIM2: return "NOT_XOR_ELIM2";
+ case PfRule::ITE_ELIM1: return "ITE_ELIM1";
+ case PfRule::ITE_ELIM2: return "ITE_ELIM2";
+ case PfRule::NOT_ITE_ELIM1: return "NOT_ITE_ELIM1";
+ case PfRule::NOT_ITE_ELIM2: return "NOT_ITE_ELIM2";
+ case PfRule::CONTRA: return "CONTRA";
+ //================================================= De Morgan rules
+ case PfRule::NOT_AND: return "NOT_AND";
+ //================================================= CNF rules
+ case PfRule::CNF_AND_POS: return "CNF_AND_POS";
+ case PfRule::CNF_AND_NEG: return "CNF_AND_NEG";
+ case PfRule::CNF_OR_POS: return "CNF_OR_POS";
+ case PfRule::CNF_OR_NEG: return "CNF_OR_NEG";
+ case PfRule::CNF_IMPLIES_POS: return "CNF_IMPLIES_POS";
+ case PfRule::CNF_IMPLIES_NEG1: return "CNF_IMPLIES_NEG1";
+ case PfRule::CNF_IMPLIES_NEG2: return "CNF_IMPLIES_NEG2";
+ case PfRule::CNF_EQUIV_POS1: return "CNF_EQUIV_POS1";
+ case PfRule::CNF_EQUIV_POS2: return "CNF_EQUIV_POS2";
+ case PfRule::CNF_EQUIV_NEG1: return "CNF_EQUIV_NEG1";
+ case PfRule::CNF_EQUIV_NEG2: return "CNF_EQUIV_NEG2";
+ case PfRule::CNF_XOR_POS1: return "CNF_XOR_POS1";
+ case PfRule::CNF_XOR_POS2: return "CNF_XOR_POS2";
+ case PfRule::CNF_XOR_NEG1: return "CNF_XOR_NEG1";
+ case PfRule::CNF_XOR_NEG2: return "CNF_XOR_NEG2";
+ case PfRule::CNF_ITE_POS1: return "CNF_ITE_POS1";
+ case PfRule::CNF_ITE_POS2: return "CNF_ITE_POS2";
+ case PfRule::CNF_ITE_POS3: return "CNF_ITE_POS3";
+ case PfRule::CNF_ITE_NEG1: return "CNF_ITE_NEG1";
+ case PfRule::CNF_ITE_NEG2: return "CNF_ITE_NEG2";
+ case PfRule::CNF_ITE_NEG3: return "CNF_ITE_NEG3";
//================================================= Unknown rule
case PfRule::UNKNOWN: return "UNKNOWN";
default: return "?";
diff --git a/src/expr/proof_rule.h b/src/expr/proof_rule.h
index 0d03bb347..6acccfffd 100644
--- a/src/expr/proof_rule.h
+++ b/src/expr/proof_rule.h
@@ -71,6 +71,408 @@ enum class PfRule : uint32_t
// has the conclusion (=> F F) and has no free assumptions. More generally, a
// proof with no free assumptions always concludes a valid formula.
SCOPE,
+ //================================================= Equality rules
+ // ======== Reflexive
+ // Children: none
+ // Arguments: (t)
+ // ---------------------
+ // Conclusion: (= t t)
+ REFL,
+ // ======== Symmetric
+ // Children: (P:(= t1 t2)) or (P:(not (= t1 t2)))
+ // Arguments: none
+ // -----------------------
+ // Conclusion: (= t2 t1) or (not (= t2 t1))
+ SYMM,
+ // ======== Transitivity
+ // Children: (P1:(= t1 t2), ..., Pn:(= t{n-1} tn))
+ // Arguments: none
+ // -----------------------
+ // Conclusion: (= t1 tn)
+ TRANS,
+ // ======== Congruence (subsumed by Substitute?)
+ // Children: (P1:(= t1 s1), ..., Pn:(= tn sn))
+ // Arguments: (f)
+ // ---------------------------------------------
+ // Conclusion: (= (f t1 ... tn) (f s1 ... sn))
+ CONG,
+ // ======== True intro
+ // Children: (P:F)
+ // Arguments: none
+ // ----------------------------------------
+ // Conclusion: (= F true)
+ TRUE_INTRO,
+ // ======== True elim
+ // Children: (P:(= F true)
+ // Arguments: none
+ // ----------------------------------------
+ // Conclusion: F
+ TRUE_ELIM,
+ // ======== False intro
+ // Children: (P:(not F))
+ // Arguments: none
+ // ----------------------------------------
+ // Conclusion: (= F false)
+ FALSE_INTRO,
+ // ======== False elim
+ // Children: (P:(= F false)
+ // Arguments: none
+ // ----------------------------------------
+ // Conclusion: (not F)
+ FALSE_ELIM,
+
+ //================================================= Boolean rules
+ // ======== Split
+ // Children: none
+ // Arguments: (F)
+ // ---------------------
+ // Conclusion: (or F (not F))
+ SPLIT,
+ // ======== And elimination
+ // Children: (P:(and F1 ... Fn))
+ // Arguments: (i)
+ // ---------------------
+ // Conclusion: (Fi)
+ AND_ELIM,
+ // ======== And introduction
+ // Children: (P1:F1 ... Pn:Fn))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (and P1 ... Pn)
+ AND_INTRO,
+ // ======== Not Or elimination
+ // Children: (P:(not (or F1 ... Fn)))
+ // Arguments: (i)
+ // ---------------------
+ // Conclusion: (not Fi)
+ NOT_OR_ELIM,
+ // ======== Implication elimination
+ // Children: (P:(=> F1 F2))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or (not F1) F2)
+ IMPLIES_ELIM,
+ // ======== Not Implication elimination version 1
+ // Children: (P:(not (=> F1 F2)))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (F1)
+ NOT_IMPLIES_ELIM1,
+ // ======== Not Implication elimination version 2
+ // Children: (P:(not (=> F1 F2)))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (not F2)
+ NOT_IMPLIES_ELIM2,
+ // ======== Equivalence elimination version 1
+ // Children: (P:(= F1 F2))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or (not F1) F2)
+ EQUIV_ELIM1,
+ // ======== Equivalence elimination version 2
+ // Children: (P:(= F1 F2))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or F1 (not F2))
+ EQUIV_ELIM2,
+ // ======== Not Equivalence elimination version 1
+ // Children: (P:(not (= F1 F2)))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or F1 F2)
+ NOT_EQUIV_ELIM1,
+ // ======== Not Equivalence elimination version 2
+ // Children: (P:(not (= F1 F2)))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or (not F1) (not F2))
+ NOT_EQUIV_ELIM2,
+ // ======== XOR elimination version 1
+ // Children: (P:(xor F1 F2)))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or F1 F2)
+ XOR_ELIM1,
+ // ======== XOR elimination version 2
+ // Children: (P:(xor F1 F2)))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or (not F1) (not F2))
+ XOR_ELIM2,
+ // ======== Not XOR elimination version 1
+ // Children: (P:(not (xor F1 F2)))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or F1 (not F2))
+ NOT_XOR_ELIM1,
+ // ======== Not XOR elimination version 2
+ // Children: (P:(not (xor F1 F2)))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or (not F1) F2)
+ NOT_XOR_ELIM2,
+ // ======== ITE elimination version 1
+ // Children: (P:(ite C F1 F2))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or (not C) F1)
+ ITE_ELIM1,
+ // ======== ITE elimination version 2
+ // Children: (P:(ite C F1 F2))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or C F2)
+ ITE_ELIM2,
+ // ======== Not ITE elimination version 1
+ // Children: (P:(not (ite C F1 F2)))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or (not C) (not F1))
+ NOT_ITE_ELIM1,
+ // ======== Not ITE elimination version 1
+ // Children: (P:(not (ite C F1 F2)))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or C (not F2))
+ NOT_ITE_ELIM2,
+ // ======== Not ITE elimination version 1
+ // Children: (P1:P P2:(not P))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (false)
+ CONTRA,
+
+ //================================================= De Morgan rules
+ // ======== Not And
+ // Children: (P:(not (and F1 ... Fn))
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: (or (not F1) ... (not Fn))
+ NOT_AND,
+ //================================================= CNF rules
+ // ======== CNF And Pos
+ // Children: ()
+ // Arguments: ((and F1 ... Fn), i)
+ // ---------------------
+ // Conclusion: (or (not (and F1 ... Fn)) Fi)
+ CNF_AND_POS,
+ // ======== CNF And Neg
+ // Children: ()
+ // Arguments: ((and F1 ... Fn))
+ // ---------------------
+ // Conclusion: (or (and F1 ... Fn) (not F1) ... (not Fn))
+ CNF_AND_NEG,
+ // ======== CNF Or Pos
+ // Children: ()
+ // Arguments: ((or F1 ... Fn))
+ // ---------------------
+ // Conclusion: (or (not (or F1 ... Fn)) F1 ... Fn)
+ CNF_OR_POS,
+ // ======== CNF Or Neg
+ // Children: ()
+ // Arguments: ((or F1 ... Fn), i)
+ // ---------------------
+ // Conclusion: (or (or F1 ... Fn) (not Fi))
+ CNF_OR_NEG,
+ // ======== CNF Implies Pos
+ // Children: ()
+ // Arguments: ((implies F1 F2))
+ // ---------------------
+ // Conclusion: (or (not (implies F1 F2)) (not F1) F2)
+ CNF_IMPLIES_POS,
+ // ======== CNF Implies Neg version 1
+ // Children: ()
+ // Arguments: ((implies F1 F2))
+ // ---------------------
+ // Conclusion: (or (implies F1 F2) F1)
+ CNF_IMPLIES_NEG1,
+ // ======== CNF Implies Neg version 2
+ // Children: ()
+ // Arguments: ((implies F1 F2))
+ // ---------------------
+ // Conclusion: (or (implies F1 F2) (not F2))
+ CNF_IMPLIES_NEG2,
+ // ======== CNF Equiv Pos version 1
+ // Children: ()
+ // Arguments: ((= F1 F2))
+ // ---------------------
+ // Conclusion: (or (not (= F1 F2)) (not F1) F2)
+ CNF_EQUIV_POS1,
+ // ======== CNF Equiv Pos version 2
+ // Children: ()
+ // Arguments: ((= F1 F2))
+ // ---------------------
+ // Conclusion: (or (not (= F1 F2)) F1 (not F2))
+ CNF_EQUIV_POS2,
+ // ======== CNF Equiv Neg version 1
+ // Children: ()
+ // Arguments: ((= F1 F2))
+ // ---------------------
+ // Conclusion: (or (= F1 F2) F1 F2)
+ CNF_EQUIV_NEG1,
+ // ======== CNF Equiv Neg version 2
+ // Children: ()
+ // Arguments: ((= F1 F2))
+ // ---------------------
+ // Conclusion: (or (= F1 F2) (not F1) (not F2))
+ CNF_EQUIV_NEG2,
+ // ======== CNF Xor Pos version 1
+ // Children: ()
+ // Arguments: ((xor F1 F2))
+ // ---------------------
+ // Conclusion: (or (not (xor F1 F2)) F1 F2)
+ CNF_XOR_POS1,
+ // ======== CNF Xor Pos version 2
+ // Children: ()
+ // Arguments: ((xor F1 F2))
+ // ---------------------
+ // Conclusion: (or (not (xor F1 F2)) (not F1) (not F2))
+ CNF_XOR_POS2,
+ // ======== CNF Xor Neg version 1
+ // Children: ()
+ // Arguments: ((xor F1 F2))
+ // ---------------------
+ // Conclusion: (or (xor F1 F2) (not F1) F2)
+ CNF_XOR_NEG1,
+ // ======== CNF Xor Neg version 2
+ // Children: ()
+ // Arguments: ((xor F1 F2))
+ // ---------------------
+ // Conclusion: (or (xor F1 F2) F1 (not F2))
+ CNF_XOR_NEG2,
+ // ======== CNF ITE Pos version 1
+ // Children: ()
+ // Arguments: ((ite C F1 F2))
+ // ---------------------
+ // Conclusion: (or (not (ite C F1 F2)) (not C) F1)
+ CNF_ITE_POS1,
+ // ======== CNF ITE Pos version 2
+ // Children: ()
+ // Arguments: ((ite C F1 F2))
+ // ---------------------
+ // Conclusion: (or (not (ite C F1 F2)) C F2)
+ CNF_ITE_POS2,
+ // ======== CNF ITE Pos version 3
+ // Children: ()
+ // Arguments: ((ite C F1 F2))
+ // ---------------------
+ // Conclusion: (or (not (ite C F1 F2)) F1 F2)
+ CNF_ITE_POS3,
+ // ======== CNF ITE Neg version 1
+ // Children: ()
+ // Arguments: ((ite C F1 F2))
+ // ---------------------
+ // Conclusion: (or (ite C F1 F2) (not C) (not F1))
+ CNF_ITE_NEG1,
+ // ======== CNF ITE Neg version 2
+ // Children: ()
+ // Arguments: ((ite C F1 F2))
+ // ---------------------
+ // Conclusion: (or (ite C F1 F2) C (not F2))
+ CNF_ITE_NEG2,
+ // ======== CNF ITE Neg version 3
+ // Children: ()
+ // Arguments: ((ite C F1 F2))
+ // ---------------------
+ // Conclusion: (or (ite C F1 F2) (not F1) (not F2))
+ CNF_ITE_NEG3,
+
+ //======================== Builtin theory (common node operations)
+ // ======== Substitution
+ // Children: (P1:F1, ..., Pn:Fn)
+ // Arguments: (t, (ids)?)
+ // ---------------------------------------------------------------
+ // Conclusion: (= t t*sigma{ids}(Fn)*...*sigma{ids}(F1))
+ // where sigma{ids}(Fi) are substitutions, which notice are applied in
+ // reverse order.
+ // Notice that ids is a MethodId identifier, which determines how to convert
+ // the formulas F1, ..., Fn into substitutions.
+ SUBS,
+ // ======== Rewrite
+ // Children: none
+ // Arguments: (t, (idr)?)
+ // ----------------------------------------
+ // Conclusion: (= t Rewriter{idr}(t))
+ // where idr is a MethodId identifier, which determines the kind of rewriter
+ // to apply, e.g. Rewriter::rewrite.
+ REWRITE,
+ // ======== Substitution + Rewriting equality introduction
+ //
+ // In this rule, we provide a term t and conclude that it is equal to its
+ // rewritten form under a (proven) substitution.
+ //
+ // Children: (P1:F1, ..., Pn:Fn)
+ // Arguments: (t, (ids (idr)?)?)
+ // ---------------------------------------------------------------
+ // Conclusion: (= t t')
+ // where
+ // t' is
+ // toWitness(Rewriter{idr}(toSkolem(t)*sigma{ids}(Fn)*...*sigma{ids}(F1)))
+ // toSkolem(...) converts terms from witness form to Skolem form,
+ // toWitness(...) converts terms from Skolem form to witness form.
+ //
+ // Notice that:
+ // toSkolem(t')=Rewriter{idr}(toSkolem(t)*sigma{ids}(Fn)*...*sigma{ids}(F1))
+ // In other words, from the point of view of Skolem forms, this rule
+ // transforms t to t' by standard substitution + rewriting.
+ //
+ // The argument ids and idr is optional and specify the identifier of the
+ // substitution and rewriter respectively to be used. For details, see
+ // theory/builtin/proof_checker.h.
+ MACRO_SR_EQ_INTRO,
+ // ======== Substitution + Rewriting predicate introduction
+ //
+ // In this rule, we provide a formula F and conclude it, under the condition
+ // that it rewrites to true under a proven substitution.
+ //
+ // Children: (P1:F1, ..., Pn:Fn)
+ // Arguments: (F, (ids (idr)?)?)
+ // ---------------------------------------------------------------
+ // Conclusion: F
+ // where
+ // Rewriter{idr}(F*sigma{ids}(Fn)*...*sigma{ids}(F1)) == true
+ // where ids and idr are method identifiers.
+ //
+ // Notice that we apply rewriting on the witness form of F, meaning that this
+ // rule may conclude an F whose Skolem form is justified by the definition of
+ // its (fresh) Skolem variables. Furthermore, notice that the rewriting and
+ // substitution is applied only within the side condition, meaning the
+ // rewritten form of the witness form of F does not escape this rule.
+ MACRO_SR_PRED_INTRO,
+ // ======== Substitution + Rewriting predicate elimination
+ //
+ // In this rule, if we have proven a formula F, then we may conclude its
+ // rewritten form under a proven substitution.
+ //
+ // Children: (P1:F, P2:F1, ..., P_{n+1}:Fn)
+ // Arguments: ((ids (idr)?)?)
+ // ----------------------------------------
+ // Conclusion: F'
+ // where
+ // F' is
+ // toWitness(Rewriter{idr}(toSkolem(F)*sigma{ids}(Fn)*...*sigma{ids}(F1)).
+ // where ids and idr are method identifiers.
+ //
+ // We rewrite only on the Skolem form of F, similar to MACRO_SR_EQ_INTRO.
+ MACRO_SR_PRED_ELIM,
+ // ======== Substitution + Rewriting predicate transform
+ //
+ // In this rule, if we have proven a formula F, then we may provide a formula
+ // G and conclude it if F and G are equivalent after rewriting under a proven
+ // substitution.
+ //
+ // Children: (P1:F, P2:F1, ..., P_{n+1}:Fn)
+ // Arguments: (G, (ids (idr)?)?)
+ // ----------------------------------------
+ // Conclusion: G
+ // where
+ // Rewriter{idr}(F*sigma{ids}(Fn)*...*sigma{ids}(F1)) ==
+ // Rewriter{idr}(G*sigma{ids}(Fn)*...*sigma{ids}(F1))
+ //
+ // Notice that we apply rewriting on the witness form of F and G, similar to
+ // MACRO_SR_PRED_INTRO.
+ MACRO_SR_PRED_TRANSFORM,
//================================================= Unknown rule
UNKNOWN,
diff --git a/src/expr/proof_step_buffer.cpp b/src/expr/proof_step_buffer.cpp
new file mode 100644
index 000000000..800efa2c0
--- /dev/null
+++ b/src/expr/proof_step_buffer.cpp
@@ -0,0 +1,109 @@
+/********************* */
+/*! \file proof_step_buffer.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of proof step and proof step buffer utilities.
+ **/
+
+#include "expr/proof_step_buffer.h"
+
+using namespace CVC4::kind;
+
+namespace CVC4 {
+
+ProofStep::ProofStep() : d_rule(PfRule::UNKNOWN) {}
+ProofStep::ProofStep(PfRule r,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args)
+ : d_rule(r), d_children(children), d_args(args)
+{
+}
+std::ostream& operator<<(std::ostream& out, ProofStep step)
+{
+ out << "(step " << step.d_rule;
+ for (const Node& c : step.d_children)
+ {
+ out << " " << c;
+ }
+ if (!step.d_args.empty())
+ {
+ out << " :args";
+ for (const Node& a : step.d_args)
+ {
+ out << " " << a;
+ }
+ }
+ out << ")";
+ return out;
+}
+
+ProofStepBuffer::ProofStepBuffer(ProofChecker* pc) : d_checker(pc) {}
+
+Node ProofStepBuffer::tryStep(PfRule id,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args,
+ Node expected)
+{
+ if (d_checker == nullptr)
+ {
+ Assert(false) << "ProofStepBuffer::ProofStepBuffer: no proof checker.";
+ return Node::null();
+ }
+ Node res =
+ d_checker->checkDebug(id, children, args, expected, "pf-step-buffer");
+ if (!res.isNull())
+ {
+ // add proof step
+ d_steps.push_back(
+ std::pair<Node, ProofStep>(res, ProofStep(id, children, args)));
+ }
+ return res;
+}
+
+void ProofStepBuffer::addStep(PfRule id,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args,
+ Node expected)
+{
+ d_steps.push_back(
+ std::pair<Node, ProofStep>(expected, ProofStep(id, children, args)));
+}
+
+void ProofStepBuffer::addSteps(ProofStepBuffer& psb)
+{
+ const std::vector<std::pair<Node, ProofStep>>& steps = psb.getSteps();
+ for (const std::pair<Node, ProofStep>& step : steps)
+ {
+ addStep(step.second.d_rule,
+ step.second.d_children,
+ step.second.d_args,
+ step.first);
+ }
+}
+
+void ProofStepBuffer::popStep()
+{
+ Assert(!d_steps.empty());
+ if (!d_steps.empty())
+ {
+ d_steps.pop_back();
+ }
+}
+
+size_t ProofStepBuffer::getNumSteps() const { return d_steps.size(); }
+
+const std::vector<std::pair<Node, ProofStep>>& ProofStepBuffer::getSteps() const
+{
+ return d_steps;
+}
+
+void ProofStepBuffer::clear() { d_steps.clear(); }
+
+} // namespace CVC4
diff --git a/src/expr/proof_step_buffer.h b/src/expr/proof_step_buffer.h
new file mode 100644
index 000000000..005aee399
--- /dev/null
+++ b/src/expr/proof_step_buffer.h
@@ -0,0 +1,96 @@
+/********************* */
+/*! \file proof_step_buffer.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 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 Proof step and proof step buffer utilities.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__EXPR__PROOF_STEP_BUFFER_H
+#define CVC4__EXPR__PROOF_STEP_BUFFER_H
+
+#include <vector>
+
+#include "expr/node.h"
+#include "expr/proof_checker.h"
+#include "expr/proof_rule.h"
+
+namespace CVC4 {
+
+/**
+ * Information for constructing a step in a CDProof. Notice that the conclusion
+ * of the proof step is intentionally not included in this data structure.
+ * Instead, it is intended that conclusions may be associated with proof steps
+ * based on e.g. the result of proof checking.
+ */
+class ProofStep
+{
+ public:
+ ProofStep();
+ ProofStep(PfRule r,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args);
+ /** The proof rule */
+ PfRule d_rule;
+ /** The proof children */
+ std::vector<Node> d_children;
+ /** The proof arguments */
+ std::vector<Node> d_args;
+};
+std::ostream& operator<<(std::ostream& out, ProofStep step);
+
+/**
+ * Class used to speculatively try and buffer a set of proof steps before
+ * sending them to a proof object.
+ */
+class ProofStepBuffer
+{
+ public:
+ ProofStepBuffer(ProofChecker* pc = nullptr);
+ ~ProofStepBuffer() {}
+ /**
+ * Returns the conclusion of the proof step, as determined by the proof
+ * checker of the given proof. If this is non-null, then the given step
+ * is added to the buffer maintained by this class.
+ *
+ * If expected is non-null, then this method returns null if the result of
+ * checking is not equal to expected.
+ */
+ Node tryStep(PfRule id,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args,
+ Node expected = Node::null());
+ /** Same as above, without checking */
+ void addStep(PfRule id,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args,
+ Node expected);
+ /** Multi-step version */
+ void addSteps(ProofStepBuffer& psb);
+ /** pop step */
+ void popStep();
+ /** Get num steps */
+ size_t getNumSteps() const;
+ /** Get steps */
+ const std::vector<std::pair<Node, ProofStep>>& getSteps() const;
+ /** Clear */
+ void clear();
+
+ private:
+ /** The proof checker*/
+ ProofChecker* d_checker;
+ /** the queued proof steps */
+ std::vector<std::pair<Node, ProofStep>> d_steps;
+};
+
+} // namespace CVC4
+
+#endif /* CVC4__EXPR__PROOF_STEP_BUFFER_H */
diff --git a/src/expr/sequence.cpp b/src/expr/sequence.cpp
index e42a67bbe..f70a70027 100644
--- a/src/expr/sequence.cpp
+++ b/src/expr/sequence.cpp
@@ -14,6 +14,8 @@
#include "expr/sequence.h"
+#include "expr/expr_sequence.h"
+
using namespace std;
namespace CVC4 {
@@ -297,6 +299,16 @@ bool Sequence::noOverlapWith(const Sequence& y) const
size_t Sequence::maxSize() { return std::numeric_limits<uint32_t>::max(); }
+ExprSequence Sequence::toExprSequence()
+{
+ std::vector<Expr> seq;
+ for (const Node& n : d_seq)
+ {
+ seq.push_back(n.toExpr());
+ }
+ return ExprSequence(d_type.toType(), seq);
+}
+
std::ostream& operator<<(std::ostream& os, const Sequence& s)
{
const std::vector<Node>& vec = s.getVec();
diff --git a/src/expr/sequence.h b/src/expr/sequence.h
index 833e79441..2e0721b4a 100644
--- a/src/expr/sequence.h
+++ b/src/expr/sequence.h
@@ -144,6 +144,10 @@ class Sequence
*/
static size_t maxSize();
+ //!!!!!!!!!!!!!!! temporary
+ ExprSequence toExprSequence();
+ //!!!!!!!!!!!!!!! end temporary
+
private:
/**
* Returns a negative number if *this < y, 0 if *this and y are equal and a
diff --git a/src/expr/type.cpp b/src/expr/type.cpp
index 031dcb3f0..2067beef5 100644
--- a/src/expr/type.cpp
+++ b/src/expr/type.cpp
@@ -353,6 +353,12 @@ bool Type::isSet() const {
return d_typeNode->isSet();
}
+bool Type::isSequence() const
+{
+ NodeManagerScope nms(d_nodeManager);
+ return d_typeNode->isSequence();
+}
+
/** Is this a sort kind */
bool Type::isSort() const {
NodeManagerScope nms(d_nodeManager);
@@ -516,6 +522,11 @@ SetType::SetType(const Type& t) : Type(t)
PrettyCheckArgument(isNull() || isSet(), this);
}
+SequenceType::SequenceType(const Type& t) : Type(t)
+{
+ PrettyCheckArgument(isNull() || isSequence(), this);
+}
+
SortType::SortType(const Type& t) : Type(t)
{
PrettyCheckArgument(isNull() || isSort(), this);
@@ -550,6 +561,11 @@ Type SetType::getElementType() const {
return makeType(d_typeNode->getSetElementType());
}
+Type SequenceType::getElementType() const
+{
+ return makeType(d_typeNode->getSequenceElementType());
+}
+
DatatypeType ConstructorType::getRangeType() const {
return DatatypeType(makeType(d_typeNode->getConstructorRangeType()));
}
diff --git a/src/expr/type.h b/src/expr/type.h
index 529c40930..0cdf55626 100644
--- a/src/expr/type.h
+++ b/src/expr/type.h
@@ -373,7 +373,13 @@ protected:
*/
bool isSet() const;
- /**
+ /**
+ * Is this a Sequence type?
+ * @return true if the type is a Sequence type
+ */
+ bool isSequence() const;
+
+ /**
* Is this a datatype type?
* @return true if the type is a datatype type
*/
@@ -515,15 +521,26 @@ class CVC4_PUBLIC ArrayType : public Type {
Type getConstituentType() const;
};/* class ArrayType */
-/** Class encapsulating an set type. */
+/** Class encapsulating a set type. */
class CVC4_PUBLIC SetType : public Type {
public:
/** Construct from the base type */
SetType(const Type& type = Type());
- /** Get the index type */
+ /** Get the element type */
+ Type getElementType() const;
+}; /* class SetType */
+
+/** Class encapsulating a sequence type. */
+class CVC4_PUBLIC SequenceType : public Type
+{
+ public:
+ /** Construct from the base type */
+ SequenceType(const Type& type = Type());
+
+ /** Get the element type */
Type getElementType() const;
-};/* class SetType */
+}; /* class SetType */
/** Class encapsulating a user-defined sort. */
class CVC4_PUBLIC SortType : public Type {
diff --git a/src/expr/type_node.cpp b/src/expr/type_node.cpp
index 110db6162..e191be0c2 100644
--- a/src/expr/type_node.cpp
+++ b/src/expr/type_node.cpp
@@ -122,7 +122,7 @@ bool TypeNode::isFiniteInternal(bool usortFinite)
{
ret = true;
}
- else if (isString() || isRegExp() || isReal())
+ else if (isString() || isRegExp() || isSequence() || isReal())
{
ret = false;
}
@@ -245,6 +245,10 @@ bool TypeNode::isClosedEnumerable()
{
ret = getSetElementType().isClosedEnumerable();
}
+ else if (isSequence())
+ {
+ ret = getSequenceElementType().isClosedEnumerable();
+ }
else if (isDatatype())
{
// avoid infinite loops: initially set to true
@@ -353,6 +357,12 @@ bool TypeNode::isComparableTo(TypeNode t) const {
return false;
}
+TypeNode TypeNode::getSequenceElementType() const
+{
+ Assert(isSequence());
+ return (*this)[0];
+}
+
TypeNode TypeNode::getBaseType() const {
TypeNode realt = NodeManager::currentNM()->realType();
if (isSubtypeOf(realt)) {
diff --git a/src/expr/type_node.h b/src/expr/type_node.h
index 70392fb01..c9771bd3d 100644
--- a/src/expr/type_node.h
+++ b/src/expr/type_node.h
@@ -518,6 +518,9 @@ public:
/** Is this a Set type? */
bool isSet() const;
+ /** Is this a Sequence type? */
+ bool isSequence() const;
+
/** Get the index type (for array types) */
TypeNode getArrayIndexType() const;
@@ -536,6 +539,8 @@ public:
/** Get the element type (for set types) */
TypeNode getSetElementType() const;
+ /** Get the element type (for sequence types) */
+ TypeNode getSequenceElementType() const;
/**
* Is this a function type? Function-like things (e.g. datatype
* selectors) that aren't actually functions are NOT considered
@@ -964,6 +969,11 @@ inline bool TypeNode::isSet() const {
return getKind() == kind::SET_TYPE;
}
+inline bool TypeNode::isSequence() const
+{
+ return getKind() == kind::SEQUENCE_TYPE;
+}
+
inline TypeNode TypeNode::getSetElementType() const {
Assert(isSet());
return (*this)[0];
diff --git a/src/options/quantifiers_options.toml b/src/options/quantifiers_options.toml
index 1834c90c4..8ae6ea89a 100644
--- a/src/options/quantifiers_options.toml
+++ b/src/options/quantifiers_options.toml
@@ -46,9 +46,6 @@ header = "options/quantifiers_options.h"
[[option.mode.SIMPLE]]
name = "simple"
help = "Do simple prenexing of same sign quantifiers."
-[[option.mode.DISJ_NORMAL]]
- name = "dnorm"
- help = "Prenex to disjunctive prenex normal form."
[[option.mode.NORMAL]]
name = "norm"
help = "Prenex to prenex normal form."
diff --git a/src/options/smt_options.toml b/src/options/smt_options.toml
index 08e6f317c..449c0c31e 100644
--- a/src/options/smt_options.toml
+++ b/src/options/smt_options.toml
@@ -346,7 +346,7 @@ header = "options/smt_options.h"
long = "unconstrained-simp"
type = "bool"
default = "false"
- help = "turn on unconstrained simplification (see Bruttomesso/Brummayer PhD thesis)"
+ help = "turn on unconstrained simplification (see Bruttomesso/Brummayer PhD thesis). Fully supported only in (subsets of) the logic QF_ABV."
[[option]]
name = "repeatSimp"
diff --git a/src/options/strings_options.toml b/src/options/strings_options.toml
index 3cf8f5852..32c4c64c7 100644
--- a/src/options/strings_options.toml
+++ b/src/options/strings_options.toml
@@ -55,15 +55,6 @@ header = "options/strings_options.h"
help = "perform string preprocessing lazily"
[[option]]
- name = "stringLenGeqZ"
- category = "regular"
- long = "strings-len-geqz"
- type = "bool"
- default = "false"
- read_only = true
- help = "strings length greater than zero lemmas"
-
-[[option]]
name = "stringLenNorm"
category = "regular"
long = "strings-len-norm"
diff --git a/src/parser/cvc/Cvc.g b/src/parser/cvc/Cvc.g
index 8e4152e2e..e604c7769 100644
--- a/src/parser/cvc/Cvc.g
+++ b/src/parser/cvc/Cvc.g
@@ -1159,7 +1159,7 @@ declareVariables[std::unique_ptr<CVC4::Command>* cmd, CVC4::api::Sort& t,
PARSER_STATE->checkDeclaration(*i, CHECK_UNDECLARED, SYM_VARIABLE);
api::Term func = PARSER_STATE->mkVar(
*i,
- t.getType(),
+ api::Sort(SOLVER, t.getType()),
ExprManager::VAR_FLAG_GLOBAL | ExprManager::VAR_FLAG_DEFINED);
PARSER_STATE->defineVar(*i, f);
Command* decl =
@@ -1654,7 +1654,7 @@ tupleStore[CVC4::api::Term& f]
}
const Datatype & dt = ((DatatypeType)t.getType()).getDatatype();
f2 = SOLVER->mkTerm(
- api::APPLY_SELECTOR, api::Term(dt[0][k].getSelector()), f);
+ api::APPLY_SELECTOR, api::Term(SOLVER, dt[0][k].getSelector()), f);
}
( ( arrayStore[f2]
| DOT ( tupleStore[f2]
@@ -1687,7 +1687,7 @@ recordStore[CVC4::api::Term& f]
}
const Datatype & dt = ((DatatypeType)t.getType()).getDatatype();
f2 = SOLVER->mkTerm(
- api::APPLY_SELECTOR, api::Term(dt[0][id].getSelector()), f);
+ api::APPLY_SELECTOR, api::Term(SOLVER, dt[0][id].getSelector()), f);
}
( ( arrayStore[f2]
| DOT ( tupleStore[f2]
@@ -1831,7 +1831,9 @@ postfixTerm[CVC4::api::Term& f]
PARSER_STATE->parseError(std::string("no such field `") + id + "' in record");
}
const Datatype & dt = ((DatatypeType)type.getType()).getDatatype();
- f = SOLVER->mkTerm(api::APPLY_SELECTOR,api::Term(dt[0][id].getSelector()), f);
+ f = SOLVER->mkTerm(api::APPLY_SELECTOR,
+ api::Term(SOLVER, dt[0][id].getSelector()),
+ f);
}
| k=numeral
{
@@ -1846,7 +1848,9 @@ postfixTerm[CVC4::api::Term& f]
PARSER_STATE->parseError(ss.str());
}
const Datatype & dt = ((DatatypeType)type.getType()).getDatatype();
- f = SOLVER->mkTerm(api::APPLY_SELECTOR,api::Term(dt[0][k].getSelector()), f);
+ f = SOLVER->mkTerm(api::APPLY_SELECTOR,
+ api::Term(SOLVER, dt[0][k].getSelector()),
+ f);
}
)
)*
@@ -1857,7 +1861,7 @@ postfixTerm[CVC4::api::Term& f]
| ABS_TOK LPAREN formula[f] RPAREN
{ f = MK_TERM(CVC4::api::ABS, f); }
| DIVISIBLE_TOK LPAREN formula[f] COMMA n=numeral RPAREN
- { f = MK_TERM(SOLVER->mkOp(CVC4::api::DIVISIBLE,n), f); }
+ { f = MK_TERM(SOLVER->mkOp(CVC4::api::DIVISIBLE, n), f); }
| DISTINCT_TOK LPAREN
formula[f] { args.push_back(f); }
( COMMA formula[f] { args.push_back(f); } )* RPAREN
@@ -1868,7 +1872,7 @@ postfixTerm[CVC4::api::Term& f]
)
( typeAscription[f, t]
{
- f = PARSER_STATE->applyTypeAscription(f,t).getExpr();
+ f = PARSER_STATE->applyTypeAscription(f,t);
}
)?
;
@@ -1885,8 +1889,8 @@ relationTerm[CVC4::api::Term& f]
args.push_back(f);
types.push_back(f.getSort());
api::Sort t = SOLVER->mkTupleSort(types);
- const Datatype& dt = ((DatatypeType)t.getType()).getDatatype();
- args.insert( args.begin(), api::Term(dt[0].getConstructor()) );
+ const Datatype& dt = Datatype(((DatatypeType)t.getType()).getDatatype());
+ args.insert(args.begin(), api::Term(SOLVER, dt[0].getConstructor()));
f = MK_TERM(api::APPLY_CONSTRUCTOR, args);
}
| IDEN_TOK LPAREN formula[f] RPAREN
@@ -2136,7 +2140,7 @@ simpleTerm[CVC4::api::Term& f]
}
api::Sort dtype = SOLVER->mkTupleSort(types);
const Datatype& dt = ((DatatypeType)dtype.getType()).getDatatype();
- args.insert( args.begin(), dt[0].getConstructor() );
+ args.insert(args.begin(), api::Term(SOLVER, dt[0].getConstructor()));
f = MK_TERM(api::APPLY_CONSTRUCTOR, args);
}
}
@@ -2146,7 +2150,9 @@ simpleTerm[CVC4::api::Term& f]
{ std::vector<api::Sort> types;
api::Sort dtype = SOLVER->mkTupleSort(types);
const Datatype& dt = ((DatatypeType)dtype.getType()).getDatatype();
- f = MK_TERM(api::APPLY_CONSTRUCTOR, api::Term(dt[0].getConstructor())); }
+ f = MK_TERM(api::APPLY_CONSTRUCTOR,
+ api::Term(SOLVER, dt[0].getConstructor()));
+ }
/* empty record literal */
| PARENHASH HASHPAREN
@@ -2154,7 +2160,8 @@ simpleTerm[CVC4::api::Term& f]
api::Sort dtype = SOLVER->mkRecordSort(
std::vector<std::pair<std::string, api::Sort>>());
const Datatype& dt = ((DatatypeType)dtype.getType()).getDatatype();
- f = MK_TERM(api::APPLY_CONSTRUCTOR, api::Term(dt[0].getConstructor()));
+ f = MK_TERM(api::APPLY_CONSTRUCTOR,
+ api::Term(SOLVER, dt[0].getConstructor()));
}
/* empty set literal */
| LBRACE RBRACE
@@ -2252,7 +2259,7 @@ simpleTerm[CVC4::api::Term& f]
}
api::Sort dtype = SOLVER->mkRecordSort(typeIds);
const Datatype& dt = ((DatatypeType)dtype.getType()).getDatatype();
- args.insert( args.begin(), dt[0].getConstructor() );
+ args.insert(args.begin(), api::Term(SOLVER, dt[0].getConstructor()));
f = MK_TERM(api::APPLY_CONSTRUCTOR, args);
}
@@ -2360,8 +2367,9 @@ constructorDef[CVC4::api::DatatypeDecl& type]
std::unique_ptr<CVC4::api::DatatypeConstructorDecl> ctor;
}
: identifier[id,CHECK_UNDECLARED,SYM_SORT]
- {
- ctor.reset(new CVC4::api::DatatypeConstructorDecl(id));
+ {
+ ctor.reset(new CVC4::api::DatatypeConstructorDecl(
+ SOLVER->mkDatatypeConstructorDecl(id)));
}
( LPAREN
selector[&ctor]
diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp
index c860d14c7..b24f9ae9d 100644
--- a/src/parser/parser.cpp
+++ b/src/parser/parser.cpp
@@ -82,14 +82,9 @@ api::Term Parser::getSymbol(const std::string& name, SymbolType type)
{
checkDeclaration(name, CHECK_DECLARED, type);
assert(isDeclared(name, type));
-
- if (type == SYM_VARIABLE) {
- // Functions share var namespace
- return d_symtab->lookup(name);
- }
-
- assert(false); // Unhandled(type);
- return Expr();
+ assert(type == SYM_VARIABLE);
+ // Functions share var namespace
+ return api::Term(d_solver, d_symtab->lookup(name));
}
api::Term Parser::getVariable(const std::string& name)
@@ -166,7 +161,7 @@ api::Sort Parser::getSort(const std::string& name)
{
checkDeclaration(name, CHECK_DECLARED, SYM_SORT);
assert(isDeclared(name, SYM_SORT));
- api::Sort t = api::Sort(d_symtab->lookupType(name));
+ api::Sort t = api::Sort(d_solver, d_symtab->lookupType(name));
return t;
}
@@ -175,8 +170,8 @@ api::Sort Parser::getSort(const std::string& name,
{
checkDeclaration(name, CHECK_DECLARED, SYM_SORT);
assert(isDeclared(name, SYM_SORT));
- api::Sort t =
- api::Sort(d_symtab->lookupType(name, api::sortVectorToTypes(params)));
+ api::Sort t = api::Sort(
+ d_solver, d_symtab->lookupType(name, api::sortVectorToTypes(params)));
return t;
}
@@ -237,7 +232,8 @@ std::vector<api::Term> Parser::bindBoundVars(
std::vector<api::Term> vars;
for (std::pair<std::string, api::Sort>& i : sortedVarNames)
{
- vars.push_back(bindBoundVar(i.first, i.second.getType()));
+ vars.push_back(
+ bindBoundVar(i.first, api::Sort(d_solver, i.second.getType())));
}
return vars;
}
@@ -251,7 +247,7 @@ api::Term Parser::mkAnonymousFunction(const std::string& prefix,
}
stringstream name;
name << prefix << "_anon_" << ++d_anonymousFunctionCount;
- return mkVar(name.str(), type.getType(), flags);
+ return mkVar(name.str(), api::Sort(d_solver, type.getType()), flags);
}
std::vector<api::Term> Parser::bindVars(const std::vector<std::string> names,
@@ -334,7 +330,8 @@ void Parser::defineParameterizedType(const std::string& name,
api::Sort Parser::mkSort(const std::string& name, uint32_t flags)
{
Debug("parser") << "newSort(" << name << ")" << std::endl;
- api::Sort type = d_solver->getExprManager()->mkSort(name, flags);
+ api::Sort type =
+ api::Sort(d_solver, d_solver->getExprManager()->mkSort(name, flags));
defineType(
name,
type,
@@ -348,8 +345,9 @@ api::Sort Parser::mkSortConstructor(const std::string& name,
{
Debug("parser") << "newSortConstructor(" << name << ", " << arity << ")"
<< std::endl;
- api::Sort type =
- d_solver->getExprManager()->mkSortConstructor(name, arity, flags);
+ api::Sort type = api::Sort(
+ d_solver,
+ d_solver->getExprManager()->mkSortConstructor(name, arity, flags));
defineType(
name,
vector<api::Sort>(arity),
@@ -379,8 +377,10 @@ api::Sort Parser::mkUnresolvedTypeConstructor(
{
Debug("parser") << "newSortConstructor(P)(" << name << ", " << params.size()
<< ")" << std::endl;
- api::Sort unresolved = d_solver->getExprManager()->mkSortConstructor(
- name, params.size(), ExprManager::SORT_FLAG_PLACEHOLDER);
+ api::Sort unresolved =
+ api::Sort(d_solver,
+ d_solver->getExprManager()->mkSortConstructor(
+ name, params.size(), ExprManager::SORT_FLAG_PLACEHOLDER));
defineType(name, params, unresolved);
api::Sort t = getSort(name, params);
d_unresolved.insert(unresolved);
@@ -588,11 +588,12 @@ api::Term Parser::applyTypeAscription(api::Term t, api::Sort s)
Expr e = t.getExpr();
const DatatypeConstructor& dtc =
Datatype::datatypeOf(e)[Datatype::indexOf(e)];
- t = api::Term(em->mkExpr(
- kind::APPLY_TYPE_ASCRIPTION,
- em->mkConst(
- AscriptionType(dtc.getSpecializedConstructorType(s.getType()))),
- e));
+ t = api::Term(
+ d_solver,
+ em->mkExpr(kind::APPLY_TYPE_ASCRIPTION,
+ em->mkConst(AscriptionType(
+ dtc.getSpecializedConstructorType(s.getType()))),
+ e));
}
// the type of t does not match the sort s by design (constructor type
// vs datatype type), thus we use an alternative check here.
@@ -624,7 +625,7 @@ api::Term Parser::mkVar(const std::string& name,
uint32_t flags)
{
return api::Term(
- d_solver->getExprManager()->mkVar(name, type.getType(), flags));
+ d_solver, d_solver->getExprManager()->mkVar(name, type.getType(), flags));
}
//!!!!!!!!!!! temporary
@@ -892,16 +893,16 @@ std::vector<unsigned> Parser::processAdHocStringEsc(const std::string& s)
return str;
}
-Expr Parser::mkStringConstant(const std::string& s)
+api::Term Parser::mkStringConstant(const std::string& s)
{
ExprManager* em = d_solver->getExprManager();
if (language::isInputLang_smt2_6(em->getOptions().getInputLanguage()))
{
- return d_solver->mkString(s, true).getExpr();
+ return api::Term(d_solver, d_solver->mkString(s, true).getExpr());
}
// otherwise, we must process ad-hoc escape sequences
std::vector<unsigned> str = processAdHocStringEsc(s);
- return d_solver->mkString(str).getExpr();
+ return api::Term(d_solver, d_solver->mkString(str).getExpr());
}
} /* CVC4::parser namespace */
diff --git a/src/parser/parser.h b/src/parser/parser.h
index 7941cfdd5..b5dc83902 100644
--- a/src/parser/parser.h
+++ b/src/parser/parser.h
@@ -808,7 +808,7 @@ public:
inline SymbolTable* getSymbolTable() const {
return d_symtab;
}
-
+
//------------------------ operator overloading
/** is this function overloaded? */
bool isOverloadedFunction(api::Term fun)
@@ -822,7 +822,8 @@ public:
*/
api::Term getOverloadedConstantForType(const std::string& name, api::Sort t)
{
- return d_symtab->getOverloadedConstantForType(name, t.getType());
+ return api::Term(d_solver,
+ d_symtab->getOverloadedConstantForType(name, t.getType()));
}
/**
@@ -833,8 +834,9 @@ public:
api::Term getOverloadedFunctionForTypes(const std::string& name,
std::vector<api::Sort>& argTypes)
{
- return d_symtab->getOverloadedFunctionForTypes(
- name, api::sortVectorToTypes(argTypes));
+ return api::Term(d_solver,
+ d_symtab->getOverloadedFunctionForTypes(
+ name, api::sortVectorToTypes(argTypes)));
}
//------------------------ end operator overloading
/**
@@ -845,7 +847,7 @@ public:
* SMT-LIB 2.6 or higher), or otherwise calling the solver to construct
* the string.
*/
- Expr mkStringConstant(const std::string& s);
+ api::Term mkStringConstant(const std::string& s);
private:
/** ad-hoc string escaping
diff --git a/src/parser/smt2/Smt2.g b/src/parser/smt2/Smt2.g
index d591c29de..62bf7e974 100644
--- a/src/parser/smt2/Smt2.g
+++ b/src/parser/smt2/Smt2.g
@@ -101,7 +101,7 @@ namespace CVC4 {
struct myExpr : public CVC4::api::Term {
myExpr() : CVC4::api::Term() {}
myExpr(void*) : CVC4::api::Term() {}
- myExpr(const Expr& e) : CVC4::api::Term(e) {}
+ myExpr(const Expr& e) : CVC4::api::Term(d_solver, e) {}
myExpr(const myExpr& e) : CVC4::api::Term(e) {}
};/* struct myExpr */
}/* CVC4::parser::smt2 namespace */
@@ -286,7 +286,7 @@ command [std::unique_ptr<CVC4::Command>* cmd]
{ PARSER_STATE->popScope();
// Do NOT call mkSort, since that creates a new sort!
// This name is not its own distinct sort, it's an alias.
- PARSER_STATE->defineParameterizedType(name, sorts, t.getType());
+ PARSER_STATE->defineParameterizedType(name, sorts, t);
cmd->reset(new DefineTypeCommand(
name, api::sortVectorToTypes(sorts), t.getType()));
}
@@ -800,7 +800,7 @@ sygusGrammarV1[CVC4::api::Sort & ret,
PARSER_STATE->getUnresolvedSorts().clear();
- ret = datatypeTypes[0];
+ ret = api::Sort(SOLVER, datatypeTypes[0]);
};
// SyGuS grammar term.
@@ -893,7 +893,7 @@ sygusGTerm[CVC4::SygusGTerm& sgt, const std::string& fun]
<< "expression " << atomTerm << std::endl;
std::stringstream ss;
ss << atomTerm;
- sgt.d_op.d_expr = atomTerm.getExpr();
+ sgt.d_op.d_expr = atomTerm;
sgt.d_name = ss.str();
sgt.d_gterm_type = SygusGTerm::gterm_op;
}
@@ -1692,7 +1692,13 @@ termNonVariable[CVC4::api::Term& expr, CVC4::api::Term& expr2]
std::vector<api::Sort> argTypes;
}
: LPAREN_TOK quantOp[kind]
- { PARSER_STATE->pushScope(true); }
+ {
+ if (!PARSER_STATE->isTheoryEnabled(theory::THEORY_QUANTIFIERS))
+ {
+ PARSER_STATE->parseError("Quantifier used in non-quantified logic.");
+ }
+ PARSER_STATE->pushScope(true);
+ }
boundVarList[bvl]
term[f, f2] RPAREN_TOK
{
@@ -1791,8 +1797,10 @@ termNonVariable[CVC4::api::Term& expr, CVC4::api::Term& expr2]
Expr ef = f.getExpr();
if (Datatype::datatypeOf(ef).isParametric())
{
- type = Datatype::datatypeOf(ef)[Datatype::indexOf(ef)]
- .getSpecializedConstructorType(expr.getSort().getType());
+ type = api::Sort(
+ SOLVER,
+ Datatype::datatypeOf(ef)[Datatype::indexOf(ef)]
+ .getSpecializedConstructorType(expr.getSort().getType()));
}
argTypes = type.getConstructorDomainSorts();
}
@@ -1914,10 +1922,10 @@ termNonVariable[CVC4::api::Term& expr, CVC4::api::Term& expr2]
sorts.emplace_back(arg.getSort());
terms.emplace_back(arg);
}
- expr = SOLVER->mkTuple(sorts, terms).getExpr();
+ expr = SOLVER->mkTuple(sorts, terms);
}
| /* an atomic term (a term with no subterms) */
- termAtomic[atomTerm] { expr = atomTerm.getExpr(); }
+ termAtomic[atomTerm] { expr = atomTerm; }
;
@@ -2513,7 +2521,8 @@ constructorDef[CVC4::api::DatatypeDecl& type]
}
: symbol[id,CHECK_NONE,SYM_VARIABLE]
{
- ctor = new api::DatatypeConstructorDecl(id);
+ ctor = new api::DatatypeConstructorDecl(
+ SOLVER->mkDatatypeConstructorDecl(id));
}
( LPAREN_TOK selector[*ctor] RPAREN_TOK )*
{ // make the constructor
@@ -2630,8 +2639,8 @@ CHAR_TOK : { PARSER_STATE->isTheoryEnabled(theory::THEORY_STRINGS) }? 'char';
TUPLE_CONST_TOK: { PARSER_STATE->isTheoryEnabled(theory::THEORY_DATATYPES) }? 'mkTuple';
TUPLE_SEL_TOK: { PARSER_STATE->isTheoryEnabled(theory::THEORY_DATATYPES) }? 'tupSel';
-HO_ARROW_TOK : { PARSER_STATE->getLogic().isHigherOrder() }? '->';
-HO_LAMBDA_TOK : { PARSER_STATE->getLogic().isHigherOrder() }? 'lambda';
+HO_ARROW_TOK : { PARSER_STATE->isHoEnabled() }? '->';
+HO_LAMBDA_TOK : { PARSER_STATE->isHoEnabled() }? 'lambda';
/**
* A sequence of printable ASCII characters (except backslash) that starts
diff --git a/src/parser/smt2/smt2.cpp b/src/parser/smt2/smt2.cpp
index 91260d1db..608e47a6b 100644
--- a/src/parser/smt2/smt2.cpp
+++ b/src/parser/smt2/smt2.cpp
@@ -315,6 +315,12 @@ bool Smt2::isTheoryEnabled(theory::TheoryId theory) const
return d_logic.isTheoryEnabled(theory);
}
+bool Smt2::isHoEnabled() const
+{
+ return getLogic().isHigherOrder()
+ && d_solver->getExprManager()->getOptions().getUfHo();
+}
+
bool Smt2::logicIsSet() {
return d_logicSet;
}
@@ -1371,7 +1377,7 @@ void Smt2::mkSygusDatatype(api::DatatypeDecl& dt,
if( std::find( types.begin(), types.end(), t )==types.end() ){
types.push_back( t );
//identity element
- api::Sort bt = dt.getDatatype().getSygusType();
+ api::Sort bt = api::Sort(d_solver, dt.getDatatype().getSygusType());
Debug("parser-sygus") << ": make identity function for " << bt << ", argument type " << t << std::endl;
std::stringstream ss;
@@ -1475,7 +1481,7 @@ api::Term Smt2::purifySygusGTerm(api::Term term,
api::Term ret = d_solver->mkVar(term.getSort());
Trace("parser-sygus2-debug")
<< "...unresolved non-terminal, intro " << ret << std::endl;
- args.push_back(ret.getExpr());
+ args.push_back(api::Term(d_solver, ret.getExpr()));
cargs.push_back(itn->second);
return ret;
}
@@ -1565,8 +1571,7 @@ void Smt2::parseOpApplyTypeAscription(ParseOp& p, api::Sort type)
Trace("parser-qid") << " " << p.d_expr.getKind() << " " << p.d_expr.getSort();
Trace("parser-qid") << std::endl;
// otherwise, we process the type ascription
- p.d_expr =
- applyTypeAscription(api::Term(p.d_expr), api::Sort(type)).getExpr();
+ p.d_expr = applyTypeAscription(p.d_expr, type);
}
api::Term Smt2::parseOpToExpr(ParseOp& p)
@@ -1770,8 +1775,10 @@ api::Term Smt2::applyParseOp(ParseOp& p, std::vector<api::Term>& args)
parseError(ss.str());
}
const Datatype& dt = ((DatatypeType)t.getType()).getDatatype();
- api::Term ret = d_solver->mkTerm(
- api::APPLY_SELECTOR, api::Term(dt[0][n].getSelector()), args[0]);
+ api::Term ret =
+ d_solver->mkTerm(api::APPLY_SELECTOR,
+ api::Term(d_solver, dt[0][n].getSelector()),
+ args[0]);
Debug("parser") << "applyParseOp: return selector " << ret << std::endl;
return ret;
}
diff --git a/src/parser/smt2/smt2.h b/src/parser/smt2/smt2.h
index 35d088601..af1e36795 100644
--- a/src/parser/smt2/smt2.h
+++ b/src/parser/smt2/smt2.h
@@ -98,6 +98,13 @@ class Smt2 : public Parser
bool isTheoryEnabled(theory::TheoryId theory) const;
+ /**
+ * Checks if higher-order support is enabled.
+ *
+ * @return true if higher-order support is enabled, false otherwise
+ */
+ bool isHoEnabled() const;
+
bool logicIsSet() override;
/**
diff --git a/src/parser/tptp/Tptp.g b/src/parser/tptp/Tptp.g
index c2f4675b1..e26709595 100644
--- a/src/parser/tptp/Tptp.g
+++ b/src/parser/tptp/Tptp.g
@@ -1441,7 +1441,7 @@ tffLetTermBinding[std::vector<CVC4::api::Term> & bvlist,
PARSER_STATE->checkLetBinding(bvlist, lhs, rhs, false);
std::vector<api::Term> lchildren(++lhs.begin(), lhs.end());
rhs = MK_TERM(api::LAMBDA, MK_TERM(api::BOUND_VAR_LIST, lchildren), rhs);
- lhs = api::Term(lhs.getExpr().getOperator());
+ lhs = api::Term(SOLVER, lhs.getExpr().getOperator());
}
| LPAREN_TOK tffLetTermBinding[bvlist, lhs, rhs] RPAREN_TOK
;
@@ -1463,7 +1463,7 @@ tffLetFormulaBinding[std::vector<CVC4::api::Term> & bvlist,
PARSER_STATE->checkLetBinding(bvlist, lhs, rhs, true);
std::vector<api::Term> lchildren(++lhs.begin(), lhs.end());
rhs = MK_TERM(api::LAMBDA, MK_TERM(api::BOUND_VAR_LIST, lchildren), rhs);
- lhs = api::Term(lhs.getExpr().getOperator());
+ lhs = api::Term(SOLVER, lhs.getExpr().getOperator());
}
| LPAREN_TOK tffLetFormulaBinding[bvlist, lhs, rhs] RPAREN_TOK
;
diff --git a/src/preprocessing/passes/unconstrained_simplifier.cpp b/src/preprocessing/passes/unconstrained_simplifier.cpp
index 5d544ae57..b74909824 100644
--- a/src/preprocessing/passes/unconstrained_simplifier.cpp
+++ b/src/preprocessing/passes/unconstrained_simplifier.cpp
@@ -91,6 +91,15 @@ void UnconstrainedSimplifier::visitAll(TNode assertion)
d_unconstrained.insert(current);
}
}
+ else if (current.isClosure())
+ {
+ // Throw an exception. This should never happen in practice unless the
+ // user specifically enabled unconstrained simplification in an illegal
+ // logic.
+ throw LogicException(
+ "Cannot use unconstrained simplification in this logic, due to "
+ "(possibly internally introduced) quantified formula.");
+ }
else
{
for (TNode childNode : current)
diff --git a/src/preprocessing/passes/unconstrained_simplifier.h b/src/preprocessing/passes/unconstrained_simplifier.h
index ac4fd0a03..7fc13e17d 100644
--- a/src/preprocessing/passes/unconstrained_simplifier.h
+++ b/src/preprocessing/passes/unconstrained_simplifier.h
@@ -62,7 +62,11 @@ class UnconstrainedSimplifier : public PreprocessingPass
theory::SubstitutionMap d_substitutions;
const LogicInfo& d_logicInfo;
-
+ /**
+ * Visit all subterms in assertion. This method throws a LogicException if
+ * there is a subterm that is unhandled by this preprocessing pass (e.g. a
+ * quantified formula).
+ */
void visitAll(TNode assertion);
Node newUnconstrainedVar(TypeNode t, TNode var);
void processUnconstrained();
diff --git a/src/smt/set_defaults.cpp b/src/smt/set_defaults.cpp
index e06363883..bae7fbe68 100644
--- a/src/smt/set_defaults.cpp
+++ b/src/smt/set_defaults.cpp
@@ -538,18 +538,6 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic)
smte.setOption("produce-models", SExpr("true"));
}
- // Set the options for the theoryOf
- if (!options::theoryOfMode.wasSetByUser())
- {
- if (logic.isSharingEnabled() && !logic.isTheoryEnabled(THEORY_BV)
- && !logic.isTheoryEnabled(THEORY_STRINGS)
- && !logic.isTheoryEnabled(THEORY_SETS))
- {
- Trace("smt") << "setting theoryof-mode to term-based" << std::endl;
- options::theoryOfMode.set(options::TheoryOfMode::THEORY_OF_TERM_BASED);
- }
- }
-
/////////////////////////////////////////////////////////////////////////////
// Theory widening
//
@@ -609,6 +597,18 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic)
}
/////////////////////////////////////////////////////////////////////////////
+ // Set the options for the theoryOf
+ if (!options::theoryOfMode.wasSetByUser())
+ {
+ if (logic.isSharingEnabled() && !logic.isTheoryEnabled(THEORY_BV)
+ && !logic.isTheoryEnabled(THEORY_STRINGS)
+ && !logic.isTheoryEnabled(THEORY_SETS))
+ {
+ Trace("smt") << "setting theoryof-mode to term-based" << std::endl;
+ options::theoryOfMode.set(options::TheoryOfMode::THEORY_OF_TERM_BASED);
+ }
+ }
+
// by default, symmetry breaker is on only for non-incremental QF_UF
if (!options::ufSymmetryBreaker.wasSetByUser())
{
@@ -1161,11 +1161,8 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic)
// prenexing
if (options::cegqiNestedQE())
{
- // only complete with prenex = disj_normal or normal
- if (options::prenexQuant() <= options::PrenexQuantMode::DISJ_NORMAL)
- {
- options::prenexQuant.set(options::PrenexQuantMode::DISJ_NORMAL);
- }
+ // only complete with prenex = normal
+ options::prenexQuant.set(options::PrenexQuantMode::NORMAL);
}
else if (options::globalNegate())
{
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index 3c0a2cd8f..9e382cdcf 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -1022,72 +1022,110 @@ void SmtEngine::setInfo(const std::string& key, const CVC4::SExpr& value)
throw UnrecognizedOptionException();
}
-CVC4::SExpr SmtEngine::getInfo(const std::string& key) const {
+bool SmtEngine::isValidGetInfoFlag(const std::string& key) const
+{
+ if (key == "all-statistics" || key == "error-behavior" || key == "name"
+ || key == "version" || key == "authors" || key == "status"
+ || key == "reason-unknown" || key == "assertion-stack-levels"
+ || key == "all-options")
+ {
+ return true;
+ }
+ return false;
+}
+CVC4::SExpr SmtEngine::getInfo(const std::string& key) const
+{
SmtScope smts(this);
Trace("smt") << "SMT getInfo(" << key << ")" << endl;
- if(key == "all-statistics") {
+ if (!isValidGetInfoFlag(key))
+ {
+ throw UnrecognizedOptionException();
+ }
+ if (key == "all-statistics")
+ {
vector<SExpr> stats;
- for(StatisticsRegistry::const_iterator i = NodeManager::fromExprManager(d_exprManager)->getStatisticsRegistry()->begin();
- i != NodeManager::fromExprManager(d_exprManager)->getStatisticsRegistry()->end();
- ++i) {
+ for (StatisticsRegistry::const_iterator i =
+ NodeManager::fromExprManager(d_exprManager)
+ ->getStatisticsRegistry()
+ ->begin();
+ i
+ != NodeManager::fromExprManager(d_exprManager)
+ ->getStatisticsRegistry()
+ ->end();
+ ++i)
+ {
vector<SExpr> v;
v.push_back((*i).first);
v.push_back((*i).second);
stats.push_back(v);
}
- for(StatisticsRegistry::const_iterator i = d_statisticsRegistry->begin();
- i != d_statisticsRegistry->end();
- ++i) {
+ for (StatisticsRegistry::const_iterator i = d_statisticsRegistry->begin();
+ i != d_statisticsRegistry->end();
+ ++i)
+ {
vector<SExpr> v;
v.push_back((*i).first);
v.push_back((*i).second);
stats.push_back(v);
}
return SExpr(stats);
- } else if(key == "error-behavior") {
+ }
+ if (key == "error-behavior")
+ {
return SExpr(SExpr::Keyword("immediate-exit"));
- } else if(key == "name") {
+ }
+ if (key == "name")
+ {
return SExpr(Configuration::getName());
- } else if(key == "version") {
+ }
+ if (key == "version")
+ {
return SExpr(Configuration::getVersionString());
- } else if(key == "authors") {
+ }
+ if (key == "authors")
+ {
return SExpr(Configuration::about());
- } else if(key == "status") {
+ }
+ if (key == "status")
+ {
// sat | unsat | unknown
- switch(d_status.asSatisfiabilityResult().isSat()) {
- case Result::SAT:
- return SExpr(SExpr::Keyword("sat"));
- case Result::UNSAT:
- return SExpr(SExpr::Keyword("unsat"));
- default:
- return SExpr(SExpr::Keyword("unknown"));
- }
- } else if(key == "reason-unknown") {
- if(!d_status.isNull() && d_status.isUnknown()) {
+ switch (d_status.asSatisfiabilityResult().isSat())
+ {
+ case Result::SAT: return SExpr(SExpr::Keyword("sat"));
+ case Result::UNSAT: return SExpr(SExpr::Keyword("unsat"));
+ default: return SExpr(SExpr::Keyword("unknown"));
+ }
+ }
+ if (key == "reason-unknown")
+ {
+ if (!d_status.isNull() && d_status.isUnknown())
+ {
stringstream ss;
ss << d_status.whyUnknown();
string s = ss.str();
transform(s.begin(), s.end(), s.begin(), ::tolower);
return SExpr(SExpr::Keyword(s));
- } else {
+ }
+ else
+ {
throw RecoverableModalException(
"Can't get-info :reason-unknown when the "
"last result wasn't unknown!");
}
- } else if(key == "assertion-stack-levels") {
+ }
+ if (key == "assertion-stack-levels")
+ {
AlwaysAssert(d_userLevels.size()
<= std::numeric_limits<unsigned long int>::max());
return SExpr(static_cast<unsigned long int>(d_userLevels.size()));
- } else if(key == "all-options") {
- // get the options, like all-statistics
- std::vector< std::vector<std::string> > current_options =
- Options::current()->getOptions();
- return SExpr::parseListOfListOfAtoms(current_options);
- } else {
- throw UnrecognizedOptionException();
}
+ Assert(key == "all-options");
+ // get the options, like all-statistics
+ std::vector<std::vector<std::string>> current_options =
+ Options::current()->getOptions();
+ return SExpr::parseListOfListOfAtoms(current_options);
}
void SmtEngine::debugCheckFormals(const std::vector<Expr>& formals, Expr func)
diff --git a/src/smt/smt_engine.h b/src/smt/smt_engine.h
index 672bec821..75737b603 100644
--- a/src/smt/smt_engine.h
+++ b/src/smt/smt_engine.h
@@ -141,6 +141,27 @@ class CVC4_PUBLIC SmtEngine
public:
/* ....................................................................... */
+ /**
+ * The current mode of the solver, which is an extension of Figure 4.1 on
+ * page 52 of the SMT-LIB version 2.6 standard
+ * http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf
+ */
+ enum SmtMode
+ {
+ // the initial state of the solver
+ SMT_MODE_START,
+ // normal state of the solver, after assert/push/pop/declare/define
+ SMT_MODE_ASSERT,
+ // immediately after a check-sat returning "sat"
+ SMT_MODE_SAT,
+ // immediately after a check-sat returning "unknown"
+ SMT_MODE_SAT_UNKNOWN,
+ // immediately after a check-sat returning "unsat"
+ SMT_MODE_UNSAT,
+ // immediately after a successful call to get-abduct
+ SMT_MODE_ABDUCT
+ };
+
/** Construct an SmtEngine with the given expression manager. */
SmtEngine(ExprManager* em);
/** Destruct the SMT engine. */
@@ -162,6 +183,9 @@ class CVC4_PUBLIC SmtEngine
/** Return the user context level. */
size_t getNumUserLevels() { return d_userLevels.size(); }
+ /** Return the current mode of the solver. */
+ SmtMode getSmtMode() { return d_smtMode; }
+
/**
* Set the logic of the script.
* @throw ModalException, LogicException
@@ -189,6 +213,9 @@ class CVC4_PUBLIC SmtEngine
*/
void setInfo(const std::string& key, const CVC4::SExpr& value);
+ /** Return true if given keyword is a valid SMT-LIB v2 get-info flag. */
+ bool isValidGetInfoFlag(const std::string& key) const;
+
/** Query information about the SMT environment. */
CVC4::SExpr getInfo(const std::string& key) const;
@@ -838,27 +865,6 @@ class CVC4_PUBLIC SmtEngine
/** The types for the recursive function definitions */
typedef context::CDList<Node> NodeList;
- /**
- * The current mode of the solver, which is an extension of Figure 4.1 on
- * page 52 of the SMT-LIB version 2.6 standard
- * http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf
- */
- enum SmtMode
- {
- // the initial state of the solver
- SMT_MODE_START,
- // normal state of the solver, after assert/push/pop/declare/define
- SMT_MODE_ASSERT,
- // immediately after a check-sat returning "sat"
- SMT_MODE_SAT,
- // immediately after a check-sat returning "unknown"
- SMT_MODE_SAT_UNKNOWN,
- // immediately after a check-sat returning "unsat"
- SMT_MODE_UNSAT,
- // immediately after a successful call to get-abduct
- SMT_MODE_ABDUCT
- };
-
// disallow copy/assignment
SmtEngine(const SmtEngine&) = delete;
SmtEngine& operator=(const SmtEngine&) = delete;
diff --git a/src/theory/arith/nl_constraint.cpp b/src/theory/arith/nl/nl_constraint.cpp
index 8fb4535ea..c4c4dfbe7 100644
--- a/src/theory/arith/nl_constraint.cpp
+++ b/src/theory/arith/nl/nl_constraint.cpp
@@ -12,7 +12,7 @@
** \brief Implementation of utilities for non-linear constraints
**/
-#include "theory/arith/nl_constraint.h"
+#include "theory/arith/nl/nl_constraint.h"
#include "theory/arith/arith_msum.h"
#include "theory/arith/arith_utilities.h"
@@ -22,6 +22,7 @@ using namespace CVC4::kind;
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
ConstraintDb::ConstraintDb(MonomialDb& mdb) : d_mdb(mdb) {}
@@ -118,6 +119,7 @@ bool ConstraintDb::isMaximal(Node atom, Node x) const
return itcm->second.find(x) != itcm->second.end();
}
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nl_constraint.h b/src/theory/arith/nl/nl_constraint.h
index faa3cc812..e86ac4b66 100644
--- a/src/theory/arith/nl_constraint.h
+++ b/src/theory/arith/nl/nl_constraint.h
@@ -12,19 +12,20 @@
** \brief Utilities for non-linear constraints
**/
-#ifndef CVC4__THEORY__ARITH__NL_CONSTRAINT_H
-#define CVC4__THEORY__ARITH__NL_CONSTRAINT_H
+#ifndef CVC4__THEORY__ARITH__NL__NL_CONSTRAINT_H
+#define CVC4__THEORY__ARITH__NL__NL_CONSTRAINT_H
#include <map>
#include <vector>
#include "expr/kind.h"
#include "expr/node.h"
-#include "theory/arith/nl_monomial.h"
+#include "theory/arith/nl/nl_monomial.h"
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
/** constraint information
*
@@ -79,6 +80,7 @@ class ConstraintDb
std::map<Node, std::map<Node, ConstraintInfo> > d_c_info;
};
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nl_lemma_utils.cpp b/src/theory/arith/nl/nl_lemma_utils.cpp
index e43a77b06..ca34d91a9 100644
--- a/src/theory/arith/nl_lemma_utils.cpp
+++ b/src/theory/arith/nl/nl_lemma_utils.cpp
@@ -12,13 +12,14 @@
** \brief Implementation of utilities for the non-linear solver
**/
-#include "theory/arith/nl_lemma_utils.h"
+#include "theory/arith/nl/nl_lemma_utils.h"
-#include "theory/arith/nl_model.h"
+#include "theory/arith/nl/nl_model.h"
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
bool SortNlModel::operator()(Node i, Node j)
{
@@ -58,6 +59,7 @@ Node ArgTrie::add(Node d, const std::vector<Node>& args)
return at->d_data;
}
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nl_lemma_utils.h b/src/theory/arith/nl/nl_lemma_utils.h
index bd729dad9..64a4deb17 100644
--- a/src/theory/arith/nl_lemma_utils.h
+++ b/src/theory/arith/nl/nl_lemma_utils.h
@@ -12,8 +12,8 @@
** \brief Utilities for processing lemmas from the non-linear solver
**/
-#ifndef CVC4__THEORY__ARITH__NL_LEMMA_UTILS_H
-#define CVC4__THEORY__ARITH__NL_LEMMA_UTILS_H
+#ifndef CVC4__THEORY__ARITH__NL__NL_LEMMA_UTILS_H
+#define CVC4__THEORY__ARITH__NL__NL_LEMMA_UTILS_H
#include <tuple>
#include <vector>
@@ -22,6 +22,7 @@
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
class NlModel;
@@ -98,6 +99,7 @@ class ArgTrie
Node add(Node d, const std::vector<Node>& args);
};
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nl_model.cpp b/src/theory/arith/nl/nl_model.cpp
index 0d47c8874..d5df96bd8 100644
--- a/src/theory/arith/nl_model.cpp
+++ b/src/theory/arith/nl/nl_model.cpp
@@ -12,7 +12,7 @@
** \brief Model object for the non-linear extension class
**/
-#include "theory/arith/nl_model.h"
+#include "theory/arith/nl/nl_model.h"
#include "expr/node_algorithm.h"
#include "options/arith_options.h"
@@ -25,6 +25,7 @@ using namespace CVC4::kind;
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
NlModel::NlModel(context::Context* c) : d_used_approx(false)
{
@@ -320,7 +321,7 @@ bool NlModel::checkModel(const std::vector<Node>& assertions,
Node mg = nm->mkSkolem("model", nm->booleanType());
gs.push_back(mg);
// assert the constructed model as assertions
- for (const std::pair<const Node, std::pair<Node, Node> > cb :
+ for (const std::pair<const Node, std::pair<Node, Node>> cb :
d_check_model_bounds)
{
Node l = cb.second.first;
@@ -350,7 +351,7 @@ bool NlModel::addCheckModelSubstitution(TNode v, TNode s)
}
// if we previously had an approximate bound, the exact bound should be in its
// range
- std::map<Node, std::pair<Node, Node> >::iterator itb =
+ std::map<Node, std::pair<Node, Node>>::iterator itb =
d_check_model_bounds.find(v);
if (itb != d_check_model_bounds.end())
{
@@ -852,7 +853,7 @@ bool NlModel::simpleCheckModelLit(Node lit)
for (const Node& v : vs)
{
// is it a valid variable?
- std::map<Node, std::pair<Node, Node> >::iterator bit =
+ std::map<Node, std::pair<Node, Node>>::iterator bit =
d_check_model_bounds.find(v);
if (!expr::hasSubterm(invalid_vsum, v) && bit != d_check_model_bounds.end())
{
@@ -1041,7 +1042,7 @@ bool NlModel::simpleCheckModelMsum(const std::map<Node, Node>& msum, bool pol)
}
Trace("nl-ext-cms-debug") << " ";
}
- std::map<Node, std::pair<Node, Node> >::iterator bit =
+ std::map<Node, std::pair<Node, Node>>::iterator bit =
d_check_model_bounds.find(vc);
// if there is a model bound for this term
if (bit != d_check_model_bounds.end())
@@ -1284,7 +1285,7 @@ void NlModel::getModelValueRepair(
// values for variables that we solved for, using techniques specific to
// this class.
NodeManager* nm = NodeManager::currentNM();
- for (const std::pair<const Node, std::pair<Node, Node> >& cb :
+ for (const std::pair<const Node, std::pair<Node, Node>>& cb :
d_check_model_bounds)
{
Node l = cb.second.first;
@@ -1342,6 +1343,7 @@ void NlModel::getModelValueRepair(
}
}
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nl_model.h b/src/theory/arith/nl/nl_model.h
index 5129a7a32..61193fc12 100644
--- a/src/theory/arith/nl_model.h
+++ b/src/theory/arith/nl/nl_model.h
@@ -12,8 +12,8 @@
** \brief Model object for the non-linear extension class
**/
-#ifndef CVC4__THEORY__ARITH__NL_MODEL_H
-#define CVC4__THEORY__ARITH__NL_MODEL_H
+#ifndef CVC4__THEORY__ARITH__NL__NL_MODEL_H
+#define CVC4__THEORY__ARITH__NL__NL_MODEL_H
#include <map>
#include <unordered_map>
@@ -28,6 +28,7 @@
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
class NonlinearExtension;
@@ -307,7 +308,7 @@ class NlModel
* (2) variables we have solved quadratic equations for, whose value
* involves approximations of square roots.
*/
- std::map<Node, std::pair<Node, Node> > d_check_model_bounds;
+ std::map<Node, std::pair<Node, Node>> d_check_model_bounds;
/**
* The map from literals that our model construction solved, to the variable
* that was solved for. Examples of such literals are:
@@ -326,6 +327,7 @@ class NlModel
std::unordered_set<Node, NodeHashFunction> d_tautology;
}; /* class NlModel */
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nl_monomial.cpp b/src/theory/arith/nl/nl_monomial.cpp
index be472217d..e8e7aceba 100644
--- a/src/theory/arith/nl_monomial.cpp
+++ b/src/theory/arith/nl/nl_monomial.cpp
@@ -12,10 +12,10 @@
** \brief Implementation of utilities for monomials
**/
-#include "theory/arith/nl_monomial.h"
+#include "theory/arith/nl/nl_monomial.h"
#include "theory/arith/arith_utilities.h"
-#include "theory/arith/nl_lemma_utils.h"
+#include "theory/arith/nl/nl_lemma_utils.h"
#include "theory/rewriter.h"
using namespace CVC4::kind;
@@ -23,6 +23,7 @@ using namespace CVC4::kind;
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
// Returns a[key] if key is in a or value otherwise.
unsigned getCountWithDefault(const NodeMultiset& a, Node key, unsigned value)
@@ -329,6 +330,7 @@ Node MonomialDb::mkMonomialRemFactor(Node n,
return ret;
}
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nl_monomial.h b/src/theory/arith/nl/nl_monomial.h
index 81665c4d9..b226730ac 100644
--- a/src/theory/arith/nl_monomial.h
+++ b/src/theory/arith/nl/nl_monomial.h
@@ -12,8 +12,8 @@
** \brief Utilities for monomials
**/
-#ifndef CVC4__THEORY__ARITH__NL_MONOMIAL_H
-#define CVC4__THEORY__ARITH__NL_MONOMIAL_H
+#ifndef CVC4__THEORY__ARITH__NL__NL_MONOMIAL_H
+#define CVC4__THEORY__ARITH__NL__NL_MONOMIAL_H
#include <map>
#include <vector>
@@ -23,6 +23,7 @@
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
class MonomialDb;
class NlModel;
@@ -140,6 +141,7 @@ class MonomialDb
std::map<Node, std::map<Node, Node> > d_m_contain_umult;
};
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nl_solver.cpp b/src/theory/arith/nl/nl_solver.cpp
index 893d3dbd7..12cb02c70 100644
--- a/src/theory/arith/nl_solver.cpp
+++ b/src/theory/arith/nl/nl_solver.cpp
@@ -12,7 +12,7 @@
** \brief Implementation of non-linear solver
**/
-#include "theory/arith/nl_solver.h"
+#include "theory/arith/nl/nl_solver.h"
#include "options/arith_options.h"
#include "theory/arith/arith_msum.h"
@@ -25,6 +25,7 @@ using namespace CVC4::kind;
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
void debugPrintBound(const char* c, Node coeff, Node x, Kind type, Node rhs)
{
@@ -1580,6 +1581,7 @@ std::vector<Node> NlSolver::checkMonomialInferResBounds()
return lemmas;
}
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nl_solver.h b/src/theory/arith/nl/nl_solver.h
index 73ca97f00..35c51569b 100644
--- a/src/theory/arith/nl_solver.h
+++ b/src/theory/arith/nl/nl_solver.h
@@ -27,15 +27,16 @@
#include "context/context.h"
#include "expr/kind.h"
#include "expr/node.h"
-#include "theory/arith/nl_constraint.h"
-#include "theory/arith/nl_lemma_utils.h"
-#include "theory/arith/nl_model.h"
-#include "theory/arith/nl_monomial.h"
+#include "theory/arith/nl/nl_constraint.h"
+#include "theory/arith/nl/nl_lemma_utils.h"
+#include "theory/arith/nl/nl_model.h"
+#include "theory/arith/nl/nl_monomial.h"
#include "theory/arith/theory_arith.h"
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
typedef std::map<Node, unsigned> NodeMultiset;
@@ -361,6 +362,7 @@ class NlSolver
Node getFactorSkolem(Node n, std::vector<Node>& lemmas);
}; /* class NlSolver */
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nonlinear_extension.cpp b/src/theory/arith/nl/nonlinear_extension.cpp
index b638d8a59..4b2d2fd37 100644
--- a/src/theory/arith/nonlinear_extension.cpp
+++ b/src/theory/arith/nl/nonlinear_extension.cpp
@@ -15,7 +15,7 @@
** \todo document this file
**/
-#include "theory/arith/nonlinear_extension.h"
+#include "theory/arith/nl/nonlinear_extension.h"
#include "options/arith_options.h"
#include "theory/arith/arith_utilities.h"
@@ -28,6 +28,7 @@ using namespace CVC4::kind;
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
NonlinearExtension::NonlinearExtension(TheoryArith& containing,
eq::EqualityEngine* ee)
@@ -49,27 +50,37 @@ NonlinearExtension::NonlinearExtension(TheoryArith& containing,
NonlinearExtension::~NonlinearExtension() {}
bool NonlinearExtension::getCurrentSubstitution(
- int effort, const std::vector<Node>& vars, std::vector<Node>& subs,
- std::map<Node, std::vector<Node> >& exp) {
+ int effort,
+ const std::vector<Node>& vars,
+ std::vector<Node>& subs,
+ std::map<Node, std::vector<Node>>& exp)
+{
// get the constant equivalence classes
- std::map<Node, std::vector<int> > rep_to_subs_index;
+ std::map<Node, std::vector<int>> rep_to_subs_index;
bool retVal = false;
- for (unsigned i = 0; i < vars.size(); i++) {
+ for (unsigned i = 0; i < vars.size(); i++)
+ {
Node n = vars[i];
- if (d_ee->hasTerm(n)) {
+ if (d_ee->hasTerm(n))
+ {
Node nr = d_ee->getRepresentative(n);
- if (nr.isConst()) {
+ if (nr.isConst())
+ {
subs.push_back(nr);
Trace("nl-subs") << "Basic substitution : " << n << " -> " << nr
<< std::endl;
exp[n].push_back(n.eqNode(nr));
retVal = true;
- } else {
+ }
+ else
+ {
rep_to_subs_index[nr].push_back(i);
subs.push_back(n);
}
- } else {
+ }
+ else
+ {
subs.push_back(n);
}
}
@@ -79,8 +90,10 @@ bool NonlinearExtension::getCurrentSubstitution(
}
std::pair<bool, Node> NonlinearExtension::isExtfReduced(
- int effort, Node n, Node on, const std::vector<Node>& exp) const {
- if (n != d_zero) {
+ int effort, Node n, Node on, const std::vector<Node>& exp) const
+{
+ if (n != d_zero)
+ {
Kind k = n.getKind();
return std::make_pair(k != NONLINEAR_MULT && !isTranscendentalKind(k),
Node::null());
@@ -88,15 +101,15 @@ std::pair<bool, Node> NonlinearExtension::isExtfReduced(
Assert(n == d_zero);
if (on.getKind() == NONLINEAR_MULT)
{
- Trace("nl-ext-zero-exp") << "Infer zero : " << on << " == " << n
- << std::endl;
+ Trace("nl-ext-zero-exp")
+ << "Infer zero : " << on << " == " << n << std::endl;
// minimize explanation if a substitution+rewrite results in zero
const std::set<Node> vars(on.begin(), on.end());
for (unsigned i = 0, size = exp.size(); i < size; i++)
{
- Trace("nl-ext-zero-exp") << " exp[" << i << "] = " << exp[i]
- << std::endl;
+ Trace("nl-ext-zero-exp")
+ << " exp[" << i << "] = " << exp[i] << std::endl;
std::vector<Node> eqs;
if (exp[i].getKind() == EQUAL)
{
@@ -119,8 +132,8 @@ std::pair<bool, Node> NonlinearExtension::isExtfReduced(
{
if (eqs[j][r] == d_zero && vars.find(eqs[j][1 - r]) != vars.end())
{
- Trace("nl-ext-zero-exp") << "...single exp : " << eqs[j]
- << std::endl;
+ Trace("nl-ext-zero-exp")
+ << "...single exp : " << eqs[j] << std::endl;
return std::make_pair(true, eqs[j]);
}
}
@@ -337,9 +350,10 @@ std::vector<Node> NonlinearExtension::checkModelEval(
const std::vector<Node>& assertions)
{
std::vector<Node> false_asserts;
- for (size_t i = 0; i < assertions.size(); ++i) {
+ for (size_t i = 0; i < assertions.size(); ++i)
+ {
Node lit = assertions[i];
- Node atom = lit.getKind()==NOT ? lit[0] : lit;
+ Node atom = lit.getKind() == NOT ? lit[0] : lit;
Node litv = d_model.computeConcreteModelValue(lit);
Trace("nl-ext-mv-assert") << "M[[ " << lit << " ]] -> " << litv;
if (litv != d_true)
@@ -403,7 +417,8 @@ int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions,
}
//----------------------------------- possibly split on zero
- if (options::nlExtSplitZero()) {
+ if (options::nlExtSplitZero())
+ {
Trace("nl-ext") << "Get zero split lemmas..." << std::endl;
lemmas = d_nlSlv.checkSplitZero();
filterLemmas(lemmas, lems);
@@ -415,7 +430,8 @@ int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions,
}
}
- //-----------------------------------initial lemmas for transcendental functions
+ //-----------------------------------initial lemmas for transcendental
+ //functions
lemmas = d_trSlv.checkTranscendentalInitialRefine();
filterLemmas(lemmas, lems);
if (!lems.empty())
@@ -445,8 +461,10 @@ int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions,
return lems.size();
}
- //-----------------------------------lemmas based on magnitude of non-zero monomials
- for (unsigned c = 0; c < 3; c++) {
+ //-----------------------------------lemmas based on magnitude of non-zero
+ //monomials
+ for (unsigned c = 0; c < 3; c++)
+ {
// c is effort level
lemmas = d_nlSlv.checkMonomialMagnitude(c);
unsigned nlem = lemmas.size();
@@ -462,7 +480,7 @@ int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions,
//-----------------------------------inferred bounds lemmas
// e.g. x >= t => y*x >= y*t
- std::vector< Node > nt_lemmas;
+ std::vector<Node> nt_lemmas;
lemmas =
d_nlSlv.checkMonomialInferBounds(nt_lemmas, assertions, false_asserts);
// Trace("nl-ext") << "Bound lemmas : " << lemmas.size() << ", " <<
@@ -494,7 +512,8 @@ int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions,
//------------------------------------factoring lemmas
// x*y + x*z >= t => exists k. k = y + z ^ x*k >= t
- if( options::nlExtFactor() ){
+ if (options::nlExtFactor())
+ {
lemmas = d_nlSlv.checkFactoring(assertions, false_asserts);
filterLemmas(lemmas, lems);
if (!lems.empty())
@@ -507,7 +526,8 @@ int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions,
//------------------------------------resolution bound inferences
// e.g. ( y>=0 ^ s <= x*z ^ x*y <= t ) => y*s <= z*t
- if (options::nlExtResBound()) {
+ if (options::nlExtResBound())
+ {
lemmas = d_nlSlv.checkMonomialInferResBounds();
filterLemmas(lemmas, lems);
if (!lems.empty())
@@ -517,7 +537,7 @@ int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions,
return lems.size();
}
}
-
+
//------------------------------------tangent planes
if (options::nlExtTangentPlanes() && !options::nlExtTangentPlanesInterleave())
{
@@ -535,7 +555,8 @@ int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions,
return 0;
}
-void NonlinearExtension::check(Theory::Effort e) {
+void NonlinearExtension::check(Theory::Effort e)
+{
Trace("nl-ext") << std::endl;
Trace("nl-ext") << "NonlinearExtension::check, effort = " << e
<< ", built model = " << d_builtModel.get() << std::endl;
@@ -543,15 +564,20 @@ void NonlinearExtension::check(Theory::Effort e) {
{
d_containing.getExtTheory()->clearCache();
d_needsLastCall = true;
- if (options::nlExtRewrites()) {
+ if (options::nlExtRewrites())
+ {
std::vector<Node> nred;
- if (!d_containing.getExtTheory()->doInferences(0, nred)) {
+ if (!d_containing.getExtTheory()->doInferences(0, nred))
+ {
Trace("nl-ext") << "...sent no lemmas, # extf to reduce = "
<< nred.size() << std::endl;
- if (nred.empty()) {
+ if (nred.empty())
+ {
d_needsLastCall = false;
}
- } else {
+ }
+ else
+ {
Trace("nl-ext") << "...sent lemmas." << std::endl;
}
}
@@ -809,7 +835,7 @@ void NonlinearExtension::presolve()
Trace("nl-ext") << "NonlinearExtension::presolve" << std::endl;
}
-
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/nonlinear_extension.h b/src/theory/arith/nl/nonlinear_extension.h
index 5aa2070a6..855310daa 100644
--- a/src/theory/arith/nonlinear_extension.h
+++ b/src/theory/arith/nl/nonlinear_extension.h
@@ -15,8 +15,8 @@
** multiplication via axiom instantiations.
**/
-#ifndef CVC4__THEORY__ARITH__NONLINEAR_EXTENSION_H
-#define CVC4__THEORY__ARITH__NONLINEAR_EXTENSION_H
+#ifndef CVC4__THEORY__ARITH__NL__NONLINEAR_EXTENSION_H
+#define CVC4__THEORY__ARITH__NL__NONLINEAR_EXTENSION_H
#include <stdint.h>
#include <map>
@@ -25,16 +25,17 @@
#include "context/cdlist.h"
#include "expr/kind.h"
#include "expr/node.h"
-#include "theory/arith/nl_lemma_utils.h"
-#include "theory/arith/nl_model.h"
-#include "theory/arith/nl_solver.h"
+#include "theory/arith/nl/nl_lemma_utils.h"
+#include "theory/arith/nl/nl_model.h"
+#include "theory/arith/nl/nl_solver.h"
+#include "theory/arith/nl/transcendental_solver.h"
#include "theory/arith/theory_arith.h"
-#include "theory/arith/transcendental_solver.h"
#include "theory/uf/equality_engine.h"
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
/** Non-linear extension class
*
@@ -60,7 +61,8 @@ namespace arith {
* for valid arithmetic theory lemmas, based on the current set of assertions,
* where d_out is the output channel of TheoryArith.
*/
-class NonlinearExtension {
+class NonlinearExtension
+{
typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
public:
@@ -84,9 +86,10 @@ class NonlinearExtension {
* that hold in the current context. We call { vars -> subs } a "derivable
* substituion" (see Reynolds et al. FroCoS 2017).
*/
- bool getCurrentSubstitution(int effort, const std::vector<Node>& vars,
+ bool getCurrentSubstitution(int effort,
+ const std::vector<Node>& vars,
std::vector<Node>& subs,
- std::map<Node, std::vector<Node> >& exp);
+ std::map<Node, std::vector<Node>>& exp);
/** Is the term n in reduced form?
*
* Used for context-dependent simplification.
@@ -103,7 +106,9 @@ class NonlinearExtension {
* The second part of the pair is used for constructing
* minimal explanations for context-dependent simplifications.
*/
- std::pair<bool, Node> isExtfReduced(int effort, Node n, Node on,
+ std::pair<bool, Node> isExtfReduced(int effort,
+ Node n,
+ Node on,
const std::vector<Node>& exp) const;
/** Check at effort level e.
*
@@ -157,6 +162,7 @@ class NonlinearExtension {
* on the output channel of TheoryArith in this function.
*/
void presolve();
+
private:
/** Model-based refinement
*
@@ -179,7 +185,6 @@ class NonlinearExtension {
std::vector<Node>& mlemsPp,
std::map<Node, NlLemmaSideEffect>& lemSE);
-
/** check last call
*
* Check assertions for consistency in the effort LAST_CALL with a subset of
@@ -328,6 +333,7 @@ class NonlinearExtension {
context::CDO<bool> d_builtModel;
}; /* class NonlinearExtension */
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/transcendental_solver.cpp b/src/theory/arith/nl/transcendental_solver.cpp
index 665accc0a..3e10f6397 100644
--- a/src/theory/arith/transcendental_solver.cpp
+++ b/src/theory/arith/nl/transcendental_solver.cpp
@@ -12,7 +12,7 @@
** \brief Implementation of solver for handling transcendental functions.
**/
-#include "theory/arith/transcendental_solver.h"
+#include "theory/arith/nl/transcendental_solver.h"
#include <cmath>
#include <set>
@@ -29,6 +29,7 @@ using namespace CVC4::kind;
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
TranscendentalSolver::TranscendentalSolver(NlModel& m) : d_model(m)
{
@@ -1470,6 +1471,7 @@ Node TranscendentalSolver::mkValidPhase(Node a, Node pi)
NodeManager::currentNM()->mkNode(MULT, mkRationalNode(-1), pi), a, pi);
}
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/transcendental_solver.h b/src/theory/arith/nl/transcendental_solver.h
index 88de49af3..5cd57d8fa 100644
--- a/src/theory/arith/transcendental_solver.h
+++ b/src/theory/arith/nl/transcendental_solver.h
@@ -12,8 +12,8 @@
** \brief Solving for handling transcendental functions.
**/
-#ifndef CVC4__THEORY__ARITH__TRANSCENDENTAL_SOLVER_H
-#define CVC4__THEORY__ARITH__TRANSCENDENTAL_SOLVER_H
+#ifndef CVC4__THEORY__ARITH__NL__TRANSCENDENTAL_SOLVER_H
+#define CVC4__THEORY__ARITH__NL__TRANSCENDENTAL_SOLVER_H
#include <map>
#include <unordered_map>
@@ -21,12 +21,13 @@
#include <vector>
#include "expr/node.h"
-#include "theory/arith/nl_lemma_utils.h"
-#include "theory/arith/nl_model.h"
+#include "theory/arith/nl/nl_lemma_utils.h"
+#include "theory/arith/nl/nl_model.h"
namespace CVC4 {
namespace theory {
namespace arith {
+namespace nl {
/** Transcendental solver class
*
@@ -421,6 +422,7 @@ class TranscendentalSolver
Node d_pi_bound[2];
}; /* class TranscendentalSolver */
+} // namespace nl
} // namespace arith
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp
index 09b6d742a..3ff3966cc 100644
--- a/src/theory/arith/theory_arith_private.cpp
+++ b/src/theory/arith/theory_arith_private.cpp
@@ -55,7 +55,7 @@
#include "theory/arith/dio_solver.h"
#include "theory/arith/linear_equality.h"
#include "theory/arith/matrix.h"
-#include "theory/arith/nonlinear_extension.h"
+#include "theory/arith/nl/nonlinear_extension.h"
#include "theory/arith/normal_form.h"
#include "theory/arith/partial_model.h"
#include "theory/arith/simplex.h"
@@ -162,7 +162,7 @@ TheoryArithPrivate::TheoryArithPrivate(TheoryArith& containing,
d_nlin_inverse_skolem(u)
{
if( options::nlExt() ){
- d_nonlinearExtension = new NonlinearExtension(
+ d_nonlinearExtension = new nl::NonlinearExtension(
containing, d_congruenceManager.getEqualityEngine());
}
}
@@ -1112,14 +1112,8 @@ void TheoryArithPrivate::checkNonLinearLogic(Node term)
}
}
-struct ArithElimOpAttributeId
-{
-};
-typedef expr::Attribute<ArithElimOpAttributeId, Node> ArithElimOpAttribute;
-
Node TheoryArithPrivate::eliminateOperatorsRec(Node n)
{
- ArithElimOpAttribute aeoa;
Trace("arith-elim") << "Begin elim: " << n << std::endl;
NodeManager* nm = NodeManager::currentNM();
std::unordered_map<Node, Node, TNodeHashFunction> visited;
@@ -1138,18 +1132,11 @@ Node TheoryArithPrivate::eliminateOperatorsRec(Node n)
}
else if (it == visited.end())
{
- if (cur.hasAttribute(aeoa))
- {
- visited[cur] = cur.getAttribute(aeoa);
- }
- else
+ visited[cur] = Node::null();
+ visit.push_back(cur);
+ for (const Node& cn : cur)
{
- visited[cur] = Node::null();
- visit.push_back(cur);
- for (const Node& cn : cur)
- {
- visit.push_back(cn);
- }
+ visit.push_back(cn);
}
}
else if (it->second.isNull())
@@ -1180,7 +1167,6 @@ Node TheoryArithPrivate::eliminateOperatorsRec(Node n)
// are defined in terms of other non-standard operators.
ret = eliminateOperatorsRec(retElim);
}
- cur.setAttribute(aeoa, ret);
visited[cur] = ret;
}
} while (!visit.empty());
diff --git a/src/theory/arith/theory_arith_private.h b/src/theory/arith/theory_arith_private.h
index 8198dbcf1..822b38f69 100644
--- a/src/theory/arith/theory_arith_private.h
+++ b/src/theory/arith/theory_arith_private.h
@@ -83,7 +83,9 @@ namespace inferbounds {
}
class InferBoundsResult;
+namespace nl {
class NonlinearExtension;
+}
/**
* Implementation of QF_LRA.
@@ -372,7 +374,7 @@ private:
AttemptSolutionSDP d_attemptSolSimplex;
/** non-linear algebraic approach */
- NonlinearExtension * d_nonlinearExtension;
+ nl::NonlinearExtension* d_nonlinearExtension;
bool solveRealRelaxation(Theory::Effort effortLevel);
diff --git a/src/theory/booleans/proof_checker.cpp b/src/theory/booleans/proof_checker.cpp
new file mode 100644
index 000000000..8fdbe9f6b
--- /dev/null
+++ b/src/theory/booleans/proof_checker.cpp
@@ -0,0 +1,568 @@
+/********************* */
+/*! \file proof_checker.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Haniel Barbosa, Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of equality proof checker
+ **/
+
+#include "theory/booleans/proof_checker.h"
+
+namespace CVC4 {
+namespace theory {
+namespace booleans {
+
+void BoolProofRuleChecker::registerTo(ProofChecker* pc)
+{
+ pc->registerChecker(PfRule::SPLIT, this);
+ pc->registerChecker(PfRule::AND_ELIM, this);
+ pc->registerChecker(PfRule::AND_INTRO, this);
+ pc->registerChecker(PfRule::NOT_OR_ELIM, this);
+ pc->registerChecker(PfRule::IMPLIES_ELIM, this);
+ pc->registerChecker(PfRule::NOT_IMPLIES_ELIM1, this);
+ pc->registerChecker(PfRule::NOT_IMPLIES_ELIM2, this);
+ pc->registerChecker(PfRule::EQUIV_ELIM1, this);
+ pc->registerChecker(PfRule::EQUIV_ELIM2, this);
+ pc->registerChecker(PfRule::NOT_EQUIV_ELIM1, this);
+ pc->registerChecker(PfRule::NOT_EQUIV_ELIM2, this);
+ pc->registerChecker(PfRule::XOR_ELIM1, this);
+ pc->registerChecker(PfRule::XOR_ELIM2, this);
+ pc->registerChecker(PfRule::NOT_XOR_ELIM1, this);
+ pc->registerChecker(PfRule::NOT_XOR_ELIM2, this);
+ pc->registerChecker(PfRule::ITE_ELIM1, this);
+ pc->registerChecker(PfRule::ITE_ELIM2, this);
+ pc->registerChecker(PfRule::NOT_ITE_ELIM1, this);
+ pc->registerChecker(PfRule::NOT_ITE_ELIM2, this);
+ pc->registerChecker(PfRule::NOT_AND, this);
+ pc->registerChecker(PfRule::CNF_AND_POS, this);
+ pc->registerChecker(PfRule::CNF_AND_NEG, this);
+ pc->registerChecker(PfRule::CNF_OR_POS, this);
+ pc->registerChecker(PfRule::CNF_OR_NEG, this);
+ pc->registerChecker(PfRule::CNF_IMPLIES_POS, this);
+ pc->registerChecker(PfRule::CNF_IMPLIES_NEG1, this);
+ pc->registerChecker(PfRule::CNF_IMPLIES_NEG2, this);
+ pc->registerChecker(PfRule::CNF_EQUIV_POS1, this);
+ pc->registerChecker(PfRule::CNF_EQUIV_POS2, this);
+ pc->registerChecker(PfRule::CNF_EQUIV_NEG1, this);
+ pc->registerChecker(PfRule::CNF_EQUIV_NEG2, this);
+ pc->registerChecker(PfRule::CNF_XOR_POS1, this);
+ pc->registerChecker(PfRule::CNF_XOR_POS2, this);
+ pc->registerChecker(PfRule::CNF_XOR_NEG1, this);
+ pc->registerChecker(PfRule::CNF_XOR_NEG2, this);
+ pc->registerChecker(PfRule::CNF_ITE_POS1, this);
+ pc->registerChecker(PfRule::CNF_ITE_POS2, this);
+ pc->registerChecker(PfRule::CNF_ITE_POS3, this);
+ pc->registerChecker(PfRule::CNF_ITE_NEG1, this);
+ pc->registerChecker(PfRule::CNF_ITE_NEG2, this);
+ pc->registerChecker(PfRule::CNF_ITE_NEG3, this);
+}
+
+Node BoolProofRuleChecker::checkInternal(PfRule id,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args)
+{
+ if (id == PfRule::SPLIT)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, args[0], args[0].notNode());
+ }
+ // natural deduction rules
+ if (id == PfRule::AND_ELIM)
+ {
+ Assert(children.size() == 1);
+ Assert(args.size() == 1);
+ uint32_t i;
+ if (children[0].getKind() != kind::AND || !getUInt32(args[0], i))
+ {
+ return Node::null();
+ }
+ if (i >= children[0].getNumChildren())
+ {
+ return Node::null();
+ }
+ return children[0][i];
+ }
+ if (id == PfRule::AND_INTRO)
+ {
+ Assert(children.size() >= 1);
+ return children.size() == 1
+ ? children[0]
+ : NodeManager::currentNM()->mkNode(kind::AND, children);
+ }
+ if (id == PfRule::NOT_OR_ELIM)
+ {
+ Assert(children.size() == 1);
+ Assert(args.size() == 1);
+ uint32_t i;
+ if (children[0].getKind() != kind::NOT
+ || children[0][0].getKind() != kind::OR || !getUInt32(args[0], i))
+ {
+ return Node::null();
+ }
+ if (i >= children[0][0].getNumChildren())
+ {
+ return Node::null();
+ }
+ return children[0][0][i].notNode();
+ }
+ if (id == PfRule::IMPLIES_ELIM)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::IMPLIES)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0].notNode(), children[0][1]);
+ }
+ if (id == PfRule::NOT_IMPLIES_ELIM1)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::NOT
+ || children[0][0].getKind() != kind::IMPLIES)
+ {
+ return Node::null();
+ }
+ return children[0][0][0];
+ }
+ if (id == PfRule::NOT_IMPLIES_ELIM2)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::NOT
+ || children[0][0].getKind() != kind::IMPLIES)
+ {
+ return Node::null();
+ }
+ return children[0][0][1].notNode();
+ }
+ if (id == PfRule::EQUIV_ELIM1)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::EQUAL)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0].notNode(), children[0][1]);
+ }
+ if (id == PfRule::EQUIV_ELIM2)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::EQUAL)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0], children[0][1].notNode());
+ }
+ if (id == PfRule::NOT_EQUIV_ELIM1)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::NOT
+ || children[0][0].getKind() != kind::EQUAL)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0][0], children[0][0][1]);
+ }
+ if (id == PfRule::NOT_EQUIV_ELIM2)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::NOT
+ || children[0][0].getKind() != kind::EQUAL)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0][0].notNode(), children[0][0][1].notNode());
+ }
+ if (id == PfRule::XOR_ELIM1)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::XOR)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0], children[0][1]);
+ }
+ if (id == PfRule::XOR_ELIM2)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::XOR)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0].notNode(), children[0][1].notNode());
+ }
+ if (id == PfRule::NOT_XOR_ELIM1)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::NOT
+ || children[0][0].getKind() != kind::XOR)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0][0], children[0][0][1].notNode());
+ }
+ if (id == PfRule::NOT_XOR_ELIM2)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::NOT
+ || children[0][0].getKind() != kind::XOR)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0][0].notNode(), children[0][0][1]);
+ }
+ if (id == PfRule::ITE_ELIM1)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::ITE)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0].notNode(), children[0][1]);
+ }
+ if (id == PfRule::ITE_ELIM2)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::ITE)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0], children[0][2]);
+ }
+ if (id == PfRule::NOT_ITE_ELIM1)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::NOT
+ || children[0][0].getKind() != kind::ITE)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0][0].notNode(), children[0][0][1].notNode());
+ }
+ if (id == PfRule::NOT_ITE_ELIM2)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::NOT
+ || children[0][0].getKind() != kind::ITE)
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, children[0][0][0], children[0][0][2].notNode());
+ }
+ // De Morgan
+ if (id == PfRule::NOT_AND)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::NOT
+ || children[0][0].getKind() != kind::AND)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts;
+ for (unsigned i = 0, size = children[0][0].getNumChildren(); i < size; ++i)
+ {
+ disjuncts.push_back(children[0][0][i].notNode());
+ }
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ // valid clauses rules for Tseitin CNF transformation
+ if (id == PfRule::CNF_AND_POS)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 2);
+ uint32_t i;
+ if (args[0].getKind() != kind::AND || !getUInt32(args[1], i))
+ {
+ return Node::null();
+ }
+ if (i >= args[0].getNumChildren())
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, args[0].notNode(), args[0][i]);
+ }
+ if (id == PfRule::CNF_AND_NEG)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::AND)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0]};
+ for (unsigned i = 0, size = args[0].getNumChildren(); i < size; ++i)
+ {
+ disjuncts.push_back(args[0][i].notNode());
+ }
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_OR_POS)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::OR)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0].notNode()};
+ for (unsigned i = 0, size = args[0].getNumChildren(); i < size; ++i)
+ {
+ disjuncts.push_back(args[0][i]);
+ }
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_OR_NEG)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 2);
+ uint32_t i;
+ if (args[0].getKind() != kind::OR || !getUInt32(args[1], i))
+ {
+ return Node::null();
+ }
+ if (i >= args[0].getNumChildren())
+ {
+ return Node::null();
+ }
+ return NodeManager::currentNM()->mkNode(
+ kind::OR, args[0], args[0][i].notNode());
+ }
+ if (id == PfRule::CNF_IMPLIES_POS)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::IMPLIES)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{
+ args[0].notNode(), args[0][0].notNode(), args[0][1]};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_IMPLIES_NEG1)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::IMPLIES)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0], args[0][0]};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_IMPLIES_NEG2)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::IMPLIES)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0], args[0][1].notNode()};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_EQUIV_POS1)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::EQUAL)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{
+ args[0].notNode(), args[0][0].notNode(), args[0][1]};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_EQUIV_POS2)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::EQUAL)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{
+ args[0].notNode(), args[0][0], args[0][1].notNode()};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_EQUIV_NEG1)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::EQUAL)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0], args[0][0], args[0][1]};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_EQUIV_NEG2)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::EQUAL)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{
+ args[0], args[0][0].notNode(), args[0][1].notNode()};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_XOR_POS1)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::XOR)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0].notNode(), args[0][0], args[0][1]};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_XOR_POS2)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::XOR)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{
+ args[0].notNode(), args[0][0].notNode(), args[0][1].notNode()};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_XOR_NEG1)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::XOR)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0], args[0][0].notNode(), args[0][1]};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_XOR_NEG2)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::XOR)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0], args[0][0], args[0][1].notNode()};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_ITE_POS1)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::ITE)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{
+ args[0].notNode(), args[0][0].notNode(), args[0][1]};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_ITE_POS2)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::ITE)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0].notNode(), args[0][0], args[0][2]};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_ITE_POS3)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::ITE)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0].notNode(), args[0][1], args[0][2]};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_ITE_NEG1)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::ITE)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{
+ args[0], args[0][0].notNode(), args[0][1].notNode()};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_ITE_NEG2)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::ITE)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{args[0], args[0][0], args[0][2].notNode()};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::CNF_ITE_NEG3)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ if (args[0].getKind() != kind::ITE)
+ {
+ return Node::null();
+ }
+ std::vector<Node> disjuncts{
+ args[0], args[0][1].notNode(), args[0][2].notNode()};
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ // no rule
+ return Node::null();
+}
+
+} // namespace booleans
+} // namespace theory
+} // namespace CVC4
diff --git a/src/theory/booleans/proof_checker.h b/src/theory/booleans/proof_checker.h
new file mode 100644
index 000000000..56414ff91
--- /dev/null
+++ b/src/theory/booleans/proof_checker.h
@@ -0,0 +1,49 @@
+/********************* */
+/*! \file proof_checker.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Haniel Barbosa, Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 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 Boolean proof checker utility
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__THEORY__BOOLEANS__PROOF_CHECKER_H
+#define CVC4__THEORY__BOOLEANS__PROOF_CHECKER_H
+
+#include "expr/node.h"
+#include "expr/proof_checker.h"
+#include "expr/proof_node.h"
+
+namespace CVC4 {
+namespace theory {
+namespace booleans {
+
+/** A checker for boolean reasoning in proofs */
+class BoolProofRuleChecker : public ProofRuleChecker
+{
+ public:
+ BoolProofRuleChecker() {}
+ ~BoolProofRuleChecker() {}
+
+ /** Register all rules owned by this rule checker into pc. */
+ void registerTo(ProofChecker* pc) override;
+
+ protected:
+ /** Return the conclusion of the given proof step, or null if it is invalid */
+ Node checkInternal(PfRule id,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args) override;
+};
+
+} // namespace booleans
+} // namespace theory
+} // namespace CVC4
+
+#endif /* CVC4__THEORY__BOOLEANS__PROOF_CHECKER_H */
diff --git a/src/theory/builtin/proof_checker.cpp b/src/theory/builtin/proof_checker.cpp
new file mode 100644
index 000000000..8d2a1540c
--- /dev/null
+++ b/src/theory/builtin/proof_checker.cpp
@@ -0,0 +1,359 @@
+/********************* */
+/*! \file proof_checker.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of equality proof checker
+ **/
+
+#include "theory/builtin/proof_checker.h"
+
+#include "expr/proof_skolem_cache.h"
+#include "theory/rewriter.h"
+#include "theory/theory.h"
+
+using namespace CVC4::kind;
+
+namespace CVC4 {
+namespace theory {
+
+const char* toString(MethodId id)
+{
+ switch (id)
+ {
+ case MethodId::RW_REWRITE: return "RW_REWRITE";
+ case MethodId::RW_IDENTITY: return "RW_IDENTITY";
+ case MethodId::SB_DEFAULT: return "SB_DEFAULT";
+ case MethodId::SB_LITERAL: return "SB_LITERAL";
+ case MethodId::SB_FORMULA: return "SB_FORMULA";
+ default: return "MethodId::Unknown";
+ };
+}
+
+std::ostream& operator<<(std::ostream& out, MethodId id)
+{
+ out << toString(id);
+ return out;
+}
+
+Node mkMethodId(MethodId id)
+{
+ return NodeManager::currentNM()->mkConst(Rational(static_cast<uint32_t>(id)));
+}
+
+namespace builtin {
+
+void BuiltinProofRuleChecker::registerTo(ProofChecker* pc)
+{
+ pc->registerChecker(PfRule::ASSUME, this);
+ pc->registerChecker(PfRule::SCOPE, this);
+ pc->registerChecker(PfRule::SUBS, this);
+ pc->registerChecker(PfRule::REWRITE, this);
+ pc->registerChecker(PfRule::MACRO_SR_EQ_INTRO, this);
+ pc->registerChecker(PfRule::MACRO_SR_PRED_INTRO, this);
+ pc->registerChecker(PfRule::MACRO_SR_PRED_ELIM, this);
+ pc->registerChecker(PfRule::MACRO_SR_PRED_TRANSFORM, this);
+}
+
+Node BuiltinProofRuleChecker::applyRewrite(Node n, MethodId idr)
+{
+ Node nk = ProofSkolemCache::getSkolemForm(n);
+ Node nkr = applyRewriteExternal(nk, idr);
+ return ProofSkolemCache::getWitnessForm(nkr);
+}
+
+Node BuiltinProofRuleChecker::applySubstitution(Node n, Node exp, MethodId ids)
+{
+ if (exp.isNull() || exp.getKind() != EQUAL)
+ {
+ return Node::null();
+ }
+ Node nk = ProofSkolemCache::getSkolemForm(n);
+ Node nks = applySubstitutionExternal(nk, exp, ids);
+ return ProofSkolemCache::getWitnessForm(nks);
+}
+
+Node BuiltinProofRuleChecker::applySubstitution(Node n,
+ const std::vector<Node>& exp,
+ MethodId ids)
+{
+ Node nk = ProofSkolemCache::getSkolemForm(n);
+ Node nks = applySubstitutionExternal(nk, exp, ids);
+ return ProofSkolemCache::getWitnessForm(nks);
+}
+
+Node BuiltinProofRuleChecker::applySubstitutionRewrite(
+ Node n, const std::vector<Node>& exp, MethodId ids, MethodId idr)
+{
+ Node nk = ProofSkolemCache::getSkolemForm(n);
+ Node nks = applySubstitutionExternal(nk, exp, ids);
+ Node nksr = applyRewriteExternal(nks, idr);
+ return ProofSkolemCache::getWitnessForm(nksr);
+}
+
+Node BuiltinProofRuleChecker::applyRewriteExternal(Node n, MethodId idr)
+{
+ Trace("builtin-pfcheck-debug")
+ << "applyRewriteExternal (" << idr << "): " << n << std::endl;
+ if (idr == MethodId::RW_REWRITE)
+ {
+ return Rewriter::rewrite(n);
+ }
+ else if (idr == MethodId::RW_IDENTITY)
+ {
+ // does nothing
+ return n;
+ }
+ // unknown rewriter
+ Assert(false)
+ << "BuiltinProofRuleChecker::applyRewriteExternal: no rewriter for "
+ << idr << std::endl;
+ return n;
+}
+
+Node BuiltinProofRuleChecker::applySubstitutionExternal(Node n,
+ Node exp,
+ MethodId ids)
+{
+ Assert(!exp.isNull());
+ Node expk = ProofSkolemCache::getSkolemForm(exp);
+ TNode var, subs;
+ if (ids == MethodId::SB_DEFAULT)
+ {
+ if (expk.getKind() != EQUAL)
+ {
+ return Node::null();
+ }
+ var = expk[0];
+ subs = expk[1];
+ }
+ else if (ids == MethodId::SB_LITERAL)
+ {
+ bool polarity = expk.getKind() != NOT;
+ var = polarity ? expk : expk[0];
+ subs = NodeManager::currentNM()->mkConst(polarity);
+ }
+ else if (ids == MethodId::SB_FORMULA)
+ {
+ var = expk;
+ subs = NodeManager::currentNM()->mkConst(true);
+ }
+ else
+ {
+ Assert(false) << "BuiltinProofRuleChecker::applySubstitutionExternal: no "
+ "substitution for "
+ << ids << std::endl;
+ }
+ return n.substitute(var, subs);
+}
+
+Node BuiltinProofRuleChecker::applySubstitutionExternal(
+ Node n, const std::vector<Node>& exp, MethodId ids)
+{
+ Node curr = n;
+ // apply substitution one at a time, in reverse order
+ for (size_t i = 0, nexp = exp.size(); i < nexp; i++)
+ {
+ if (exp[nexp - 1 - i].isNull())
+ {
+ return Node::null();
+ }
+ curr = applySubstitutionExternal(curr, exp[nexp - 1 - i], ids);
+ if (curr.isNull())
+ {
+ break;
+ }
+ }
+ return curr;
+}
+
+bool BuiltinProofRuleChecker::getMethodId(TNode n, MethodId& i)
+{
+ uint32_t index;
+ if (!getUInt32(n, index))
+ {
+ return false;
+ }
+ i = static_cast<MethodId>(index);
+ return true;
+}
+
+Node BuiltinProofRuleChecker::checkInternal(PfRule id,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args)
+{
+ // compute what was proven
+ if (id == PfRule::ASSUME)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ Assert(args[0].getType().isBoolean());
+ return args[0];
+ }
+ else if (id == PfRule::SCOPE)
+ {
+ Assert(children.size() == 1);
+ if (args.empty())
+ {
+ // no antecedant
+ return children[0];
+ }
+ Node ant = mkAnd(args);
+ // if the conclusion is false, its the negated antencedant only
+ if (children[0].isConst() && !children[0].getConst<bool>())
+ {
+ return ant.notNode();
+ }
+ return NodeManager::currentNM()->mkNode(IMPLIES, ant, children[0]);
+ }
+ else if (id == PfRule::SUBS)
+ {
+ Assert(children.size() > 0);
+ Assert(1 <= args.size() && args.size() <= 2);
+ MethodId ids = MethodId::SB_DEFAULT;
+ if (args.size() == 2 && !getMethodId(args[1], ids))
+ {
+ return Node::null();
+ }
+ std::vector<Node> exp;
+ for (size_t i = 0, nchild = children.size(); i < nchild; i++)
+ {
+ exp.push_back(children[i]);
+ }
+ Node res = applySubstitution(args[0], exp);
+ return args[0].eqNode(res);
+ }
+ else if (id == PfRule::REWRITE)
+ {
+ Assert(children.empty());
+ Assert(1 <= args.size() && args.size() <= 2);
+ MethodId ids = MethodId::RW_REWRITE;
+ if (args.size() == 2 && !getMethodId(args[1], ids))
+ {
+ return Node::null();
+ }
+ Node res = applyRewrite(args[0]);
+ return args[0].eqNode(res);
+ }
+ else if (id == PfRule::MACRO_SR_EQ_INTRO)
+ {
+ Assert(1 <= args.size() && args.size() <= 3);
+ MethodId ids, idr;
+ if (!getMethodIds(args, ids, idr, 1))
+ {
+ return Node::null();
+ }
+ Node res = applySubstitutionRewrite(args[0], children, idr);
+ return args[0].eqNode(res);
+ }
+ else if (id == PfRule::MACRO_SR_PRED_INTRO)
+ {
+ Trace("builtin-pfcheck") << "Check " << id << " " << children.size() << " "
+ << args.size() << std::endl;
+ Assert(1 <= args.size() && args.size() <= 3);
+ MethodId ids, idr;
+ if (!getMethodIds(args, ids, idr, 1))
+ {
+ return Node::null();
+ }
+ Node res = applySubstitutionRewrite(args[0], children, ids, idr);
+ if (res.isNull())
+ {
+ return Node::null();
+ }
+ // **** NOTE: can rewrite the witness form here. This enables certain lemmas
+ // to be provable, e.g. (= k t) where k is a purification Skolem for t.
+ res = Rewriter::rewrite(res);
+ if (!res.isConst() || !res.getConst<bool>())
+ {
+ Trace("builtin-pfcheck")
+ << "Failed to rewrite to true, res=" << res << std::endl;
+ return Node::null();
+ }
+ return args[0];
+ }
+ else if (id == PfRule::MACRO_SR_PRED_ELIM)
+ {
+ Trace("builtin-pfcheck") << "Check " << id << " " << children.size() << " "
+ << args.size() << std::endl;
+ Assert(children.size() >= 1);
+ Assert(args.size() <= 2);
+ std::vector<Node> exp;
+ exp.insert(exp.end(), children.begin() + 1, children.end());
+ MethodId ids, idr;
+ if (!getMethodIds(args, ids, idr, 0))
+ {
+ return Node::null();
+ }
+ Node res1 = applySubstitutionRewrite(children[0], exp, ids, idr);
+ Trace("builtin-pfcheck") << "Returned " << res1 << std::endl;
+ return res1;
+ }
+ else if (id == PfRule::MACRO_SR_PRED_TRANSFORM)
+ {
+ Trace("builtin-pfcheck") << "Check " << id << " " << children.size() << " "
+ << args.size() << std::endl;
+ Assert(children.size() >= 1);
+ Assert(1 <= args.size() && args.size() <= 3);
+ Assert(args[0].getType().isBoolean());
+ MethodId ids, idr;
+ if (!getMethodIds(args, ids, idr, 1))
+ {
+ return Node::null();
+ }
+ std::vector<Node> exp;
+ exp.insert(exp.end(), children.begin() + 1, children.end());
+ Node res1 = applySubstitutionRewrite(children[0], exp, ids, idr);
+ Node res2 = applySubstitutionRewrite(args[0], exp, ids, idr);
+ // can rewrite the witness forms
+ res1 = Rewriter::rewrite(res1);
+ res2 = Rewriter::rewrite(res2);
+ if (res1.isNull() || res1 != res2)
+ {
+ Trace("builtin-pfcheck") << "Failed to match results" << std::endl;
+ Trace("builtin-pfcheck-debug") << res1 << " vs " << res2 << std::endl;
+ return Node::null();
+ }
+ return args[0];
+ }
+ // no rule
+ return Node::null();
+}
+
+bool BuiltinProofRuleChecker::getMethodIds(const std::vector<Node>& args,
+ MethodId& ids,
+ MethodId& idr,
+ size_t index)
+{
+ ids = MethodId::SB_DEFAULT;
+ idr = MethodId::RW_REWRITE;
+ if (args.size() > index)
+ {
+ if (!getMethodId(args[index], ids))
+ {
+ Trace("builtin-pfcheck")
+ << "Failed to get id from " << args[index] << std::endl;
+ return false;
+ }
+ }
+ if (args.size() > index + 1)
+ {
+ if (!getMethodId(args[index + 1], idr))
+ {
+ Trace("builtin-pfcheck")
+ << "Failed to get id from " << args[index + 1] << std::endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace builtin
+} // namespace theory
+} // namespace CVC4
diff --git a/src/theory/builtin/proof_checker.h b/src/theory/builtin/proof_checker.h
new file mode 100644
index 000000000..f4424b107
--- /dev/null
+++ b/src/theory/builtin/proof_checker.h
@@ -0,0 +1,150 @@
+/********************* */
+/*! \file proof_checker.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 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 Equality proof checker utility
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__THEORY__BUILTIN__PROOF_CHECKER_H
+#define CVC4__THEORY__BUILTIN__PROOF_CHECKER_H
+
+#include "expr/node.h"
+#include "expr/proof_checker.h"
+#include "expr/proof_node.h"
+
+namespace CVC4 {
+namespace theory {
+
+/**
+ * Identifiers for rewriters and substitutions, which we abstractly
+ * classify as "methods". Methods have a unique identifier in the internal
+ * proof calculus implemented by the checker below.
+ *
+ * A "rewriter" is abstractly a method from Node to Node, where the output
+ * is semantically equivalent to the input. The identifiers below list
+ * various methods that have this contract. This identifier is used
+ * in a number of the builtin rules.
+ *
+ * A substitution is a method for turning a formula into a substitution.
+ */
+enum class MethodId : uint32_t
+{
+ //---------------------------- Rewriters
+ // Rewriter::rewrite(n)
+ RW_REWRITE,
+ // identity
+ RW_IDENTITY,
+ //---------------------------- Substitutions
+ // (= x y) is interpreted as x -> y, using Node::substitute
+ SB_DEFAULT,
+ // P, (not P) are interpreted as P -> true, P -> false using Node::substitute
+ SB_LITERAL,
+ // P is interpreted as P -> true using Node::substitute
+ SB_FORMULA,
+};
+/** Converts a rewriter id to a string. */
+const char* toString(MethodId id);
+/** Write a rewriter id to out */
+std::ostream& operator<<(std::ostream& out, MethodId id);
+/** Make a method id node */
+Node mkMethodId(MethodId id);
+
+namespace builtin {
+
+/** A checker for builtin proofs */
+class BuiltinProofRuleChecker : public ProofRuleChecker
+{
+ public:
+ BuiltinProofRuleChecker() {}
+ ~BuiltinProofRuleChecker() {}
+ /**
+ * Apply rewrite on n (in witness form). This encapsulates the exact behavior
+ * of a REWRITE step in a proof. Rewriting is performed on the Skolem form of
+ * n.
+ *
+ * @param n The node (in witness form) to rewrite,
+ * @param idr The method identifier of the rewriter, by default RW_REWRITE
+ * specifying a call to Rewriter::rewrite.
+ * @return The rewritten form of n.
+ */
+ static Node applyRewrite(Node n, MethodId idr = MethodId::RW_REWRITE);
+ /**
+ * Apply substitution on n (in witness form). This encapsulates the exact
+ * behavior of a SUBS step in a proof. Substitution is on the Skolem form of
+ * n.
+ *
+ * @param n The node (in witness form) to substitute,
+ * @param exp The (set of) equalities (in witness form) corresponding to the
+ * substitution
+ * @param ids The method identifier of the substitution, by default SB_DEFAULT
+ * specifying that lhs/rhs of equalities are interpreted as a substitution.
+ * @return The substituted form of n.
+ */
+ static Node applySubstitution(Node n,
+ Node exp,
+ MethodId ids = MethodId::SB_DEFAULT);
+ static Node applySubstitution(Node n,
+ const std::vector<Node>& exp,
+ MethodId ids = MethodId::SB_DEFAULT);
+ /** Apply substitution + rewriting
+ *
+ * Combines the above two steps.
+ *
+ * @param n The node (in witness form) to substitute and rewrite,
+ * @param exp The (set of) equalities (in witness form) corresponding to the
+ * substitution
+ * @param ids The method identifier of the substitution.
+ * @param idr The method identifier of the rewriter.
+ * @return The substituted, rewritten form of n.
+ */
+ static Node applySubstitutionRewrite(Node n,
+ const std::vector<Node>& exp,
+ MethodId ids = MethodId::SB_DEFAULT,
+ MethodId idr = MethodId::RW_REWRITE);
+ /** get a rewriter Id from a node, return false if we fail */
+ static bool getMethodId(TNode n, MethodId& i);
+
+ /** Register all rules owned by this rule checker into pc. */
+ void registerTo(ProofChecker* pc) override;
+
+ protected:
+ /** Return the conclusion of the given proof step, or null if it is invalid */
+ Node checkInternal(PfRule id,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args) override;
+ /** get method identifiers */
+ bool getMethodIds(const std::vector<Node>& args,
+ MethodId& ids,
+ MethodId& idr,
+ size_t index);
+ /**
+ * Apply rewrite (on Skolem form). id is the identifier of the rewriter.
+ */
+ static Node applyRewriteExternal(Node n, MethodId idr = MethodId::RW_REWRITE);
+ /**
+ * Apply substitution for n (on Skolem form), where exp is an equality
+ * (or set of equalities) in Witness form. Returns the result of
+ * n * sigma{ids}(exp), where sigma{ids} is a substitution based on method
+ * identifier ids.
+ */
+ static Node applySubstitutionExternal(Node n, Node exp, MethodId ids);
+ /** Same as above, for a list of substitutions in exp */
+ static Node applySubstitutionExternal(Node n,
+ const std::vector<Node>& exp,
+ MethodId ids);
+};
+
+} // namespace builtin
+} // namespace theory
+} // namespace CVC4
+
+#endif /* CVC4__THEORY__BUILTIN__PROOF_CHECKER_H */
diff --git a/src/theory/datatypes/theory_datatypes_utils.cpp b/src/theory/datatypes/theory_datatypes_utils.cpp
index ee0fd814e..ea67ab79d 100644
--- a/src/theory/datatypes/theory_datatypes_utils.cpp
+++ b/src/theory/datatypes/theory_datatypes_utils.cpp
@@ -23,6 +23,7 @@
#include "smt/smt_engine_scope.h"
#include "theory/evaluator.h"
#include "theory/rewriter.h"
+#include "printer/sygus_print_callback.h"
using namespace CVC4;
using namespace CVC4::kind;
@@ -711,6 +712,223 @@ Node sygusToBuiltinEval(Node n, const std::vector<Node>& args)
return visited[n];
}
+void getFreeSymbolsSygusType(TypeNode sdt,
+ std::unordered_set<Node, NodeHashFunction>& syms)
+{
+ // datatype types we need to process
+ std::vector<TypeNode> typeToProcess;
+ // datatype types we have processed
+ std::map<TypeNode, TypeNode> typesProcessed;
+ typeToProcess.push_back(sdt);
+ while (!typeToProcess.empty())
+ {
+ std::vector<TypeNode> typeNextToProcess;
+ for (const TypeNode& curr : typeToProcess)
+ {
+ Assert(curr.isDatatype() && curr.getDType().isSygus());
+ const DType& dtc = curr.getDType();
+ for (unsigned j = 0, ncons = dtc.getNumConstructors(); j < ncons; j++)
+ {
+ // collect the symbols from the operator
+ Node op = dtc[j].getSygusOp();
+ expr::getSymbols(op, syms);
+ // traverse the argument types
+ for (unsigned k = 0, nargs = dtc[j].getNumArgs(); k < nargs; k++)
+ {
+ TypeNode argt = dtc[j].getArgType(k);
+ if (!argt.isDatatype() || !argt.getDType().isSygus())
+ {
+ // not a sygus datatype
+ continue;
+ }
+ if (typesProcessed.find(argt) == typesProcessed.end())
+ {
+ typeNextToProcess.push_back(argt);
+ }
+ }
+ }
+ }
+ typeToProcess.clear();
+ typeToProcess.insert(typeToProcess.end(),
+ typeNextToProcess.begin(),
+ typeNextToProcess.end());
+ }
+}
+
+TypeNode substituteAndGeneralizeSygusType(TypeNode sdt,
+ const std::vector<Node>& syms,
+ const std::vector<Node>& vars)
+{
+ NodeManager* nm = NodeManager::currentNM();
+ const DType& sdtd = sdt.getDType();
+ // compute the new formal argument list
+ std::vector<Node> formalVars;
+ Node prevVarList = sdtd.getSygusVarList();
+ if (!prevVarList.isNull())
+ {
+ for (const Node& v : prevVarList)
+ {
+ // if it is not being replaced
+ if (std::find(syms.begin(), syms.end(), v) != syms.end())
+ {
+ formalVars.push_back(v);
+ }
+ }
+ }
+ for (const Node& v : vars)
+ {
+ if (v.getKind() == BOUND_VARIABLE)
+ {
+ formalVars.push_back(v);
+ }
+ }
+ // make the sygus variable list for the formal argument list
+ Node abvl = nm->mkNode(BOUND_VAR_LIST, formalVars);
+ Trace("sygus-abduct-debug") << "...finish" << std::endl;
+
+ // must convert all constructors to version with variables in "vars"
+ std::vector<SygusDatatype> sdts;
+ std::set<Type> unres;
+
+ Trace("dtsygus-gen-debug") << "Process sygus type:" << std::endl;
+ Trace("dtsygus-gen-debug") << sdtd.getName() << std::endl;
+
+ // datatype types we need to process
+ std::vector<TypeNode> dtToProcess;
+ // datatype types we have processed
+ std::map<TypeNode, TypeNode> dtProcessed;
+ dtToProcess.push_back(sdt);
+ std::stringstream ssutn0;
+ ssutn0 << sdtd.getName() << "_s";
+ TypeNode abdTNew =
+ nm->mkSort(ssutn0.str(), ExprManager::SORT_FLAG_PLACEHOLDER);
+ unres.insert(abdTNew.toType());
+ dtProcessed[sdt] = abdTNew;
+
+ // We must convert all symbols in the sygus datatype type sdt to
+ // apply the substitution { syms -> vars }, where syms is the free
+ // variables of the input problem, and vars is the formal argument list
+ // of the function-to-synthesize.
+
+ // We are traversing over the subfield types of the datatype to convert
+ // them into the form described above.
+ while (!dtToProcess.empty())
+ {
+ std::vector<TypeNode> dtNextToProcess;
+ for (const TypeNode& curr : dtToProcess)
+ {
+ Assert(curr.isDatatype() && curr.getDType().isSygus());
+ const DType& dtc = curr.getDType();
+ std::stringstream ssdtn;
+ ssdtn << dtc.getName() << "_s";
+ sdts.push_back(SygusDatatype(ssdtn.str()));
+ Trace("dtsygus-gen-debug")
+ << "Process datatype " << sdts.back().getName() << "..." << std::endl;
+ for (unsigned j = 0, ncons = dtc.getNumConstructors(); j < ncons; j++)
+ {
+ Node op = dtc[j].getSygusOp();
+ // apply the substitution to the argument
+ Node ops =
+ op.substitute(syms.begin(), syms.end(), vars.begin(), vars.end());
+ Trace("dtsygus-gen-debug") << " Process constructor " << op << " / "
+ << ops << "..." << std::endl;
+ std::vector<TypeNode> cargs;
+ for (unsigned k = 0, nargs = dtc[j].getNumArgs(); k < nargs; k++)
+ {
+ TypeNode argt = dtc[j].getArgType(k);
+ std::map<TypeNode, TypeNode>::iterator itdp = dtProcessed.find(argt);
+ TypeNode argtNew;
+ if (itdp == dtProcessed.end())
+ {
+ std::stringstream ssutn;
+ ssutn << argt.getDType().getName() << "_s";
+ argtNew =
+ nm->mkSort(ssutn.str(), ExprManager::SORT_FLAG_PLACEHOLDER);
+ Trace("dtsygus-gen-debug") << " ...unresolved type " << argtNew
+ << " for " << argt << std::endl;
+ unres.insert(argtNew.toType());
+ dtProcessed[argt] = argtNew;
+ dtNextToProcess.push_back(argt);
+ }
+ else
+ {
+ argtNew = itdp->second;
+ }
+ Trace("dtsygus-gen-debug")
+ << " Arg #" << k << ": " << argtNew << std::endl;
+ cargs.push_back(argtNew);
+ }
+ // callback prints as the expression
+ std::shared_ptr<SygusPrintCallback> spc;
+ std::vector<Expr> args;
+ if (op.getKind() == LAMBDA)
+ {
+ Node opBody = op[1];
+ for (const Node& v : op[0])
+ {
+ args.push_back(v.toExpr());
+ }
+ spc = std::make_shared<printer::SygusExprPrintCallback>(
+ opBody.toExpr(), args);
+ }
+ else if (cargs.empty())
+ {
+ spc = std::make_shared<printer::SygusExprPrintCallback>(op.toExpr(),
+ args);
+ }
+ std::stringstream ss;
+ ss << ops.getKind();
+ Trace("dtsygus-gen-debug") << "Add constructor : " << ops << std::endl;
+ sdts.back().addConstructor(ops, ss.str(), cargs, spc);
+ }
+ Trace("dtsygus-gen-debug")
+ << "Set sygus : " << dtc.getSygusType() << " " << abvl << std::endl;
+ TypeNode stn = dtc.getSygusType();
+ sdts.back().initializeDatatype(
+ stn, abvl, dtc.getSygusAllowConst(), dtc.getSygusAllowAll());
+ }
+ dtToProcess.clear();
+ dtToProcess.insert(
+ dtToProcess.end(), dtNextToProcess.begin(), dtNextToProcess.end());
+ }
+ Trace("dtsygus-gen-debug")
+ << "Make " << sdts.size() << " datatype types..." << std::endl;
+ // extract the datatypes
+ std::vector<Datatype> datatypes;
+ for (unsigned i = 0, ndts = sdts.size(); i < ndts; i++)
+ {
+ datatypes.push_back(sdts[i].getDatatype());
+ }
+ // make the datatype types
+ std::vector<DatatypeType> datatypeTypes =
+ nm->toExprManager()->mkMutualDatatypeTypes(
+ datatypes, unres, ExprManager::DATATYPE_FLAG_PLACEHOLDER);
+ TypeNode sdtS = TypeNode::fromType(datatypeTypes[0]);
+ if (Trace.isOn("dtsygus-gen-debug"))
+ {
+ Trace("dtsygus-gen-debug") << "Made datatype types:" << std::endl;
+ for (unsigned j = 0, ndts = datatypeTypes.size(); j < ndts; j++)
+ {
+ const DType& dtj = TypeNode::fromType(datatypeTypes[j]).getDType();
+ Trace("dtsygus-gen-debug") << "#" << j << ": " << dtj << std::endl;
+ for (unsigned k = 0, ncons = dtj.getNumConstructors(); k < ncons; k++)
+ {
+ for (unsigned l = 0, nargs = dtj[k].getNumArgs(); l < nargs; l++)
+ {
+ if (!dtj[k].getArgType(l).isDatatype())
+ {
+ Trace("dtsygus-gen-debug")
+ << "Argument " << l << " of " << dtj[k]
+ << " is not datatype : " << dtj[k].getArgType(l) << std::endl;
+ AlwaysAssert(false);
+ }
+ }
+ }
+ }
+ }
+ return sdtS;
+}
+
} // namespace utils
} // namespace datatypes
} // namespace theory
diff --git a/src/theory/datatypes/theory_datatypes_utils.h b/src/theory/datatypes/theory_datatypes_utils.h
index 58f719910..038922f37 100644
--- a/src/theory/datatypes/theory_datatypes_utils.h
+++ b/src/theory/datatypes/theory_datatypes_utils.h
@@ -245,6 +245,46 @@ Node sygusToBuiltin(Node c, bool isExternal = false);
*/
Node sygusToBuiltinEval(Node n, const std::vector<Node>& args);
+/** Get free symbols in a sygus datatype type
+ *
+ * Add the free symbols (expr::getSymbols) in terms that can be generated by
+ * sygus datatype sdt to the set syms. For example, given sdt encodes the
+ * grammar:
+ * G -> a | +( b, G ) | c | e
+ * We have that { a, b, c, e } are added to syms. Notice that expr::getSymbols
+ * excludes variables whose kind is BOUND_VARIABLE.
+ */
+void getFreeSymbolsSygusType(TypeNode sdt,
+ std::unordered_set<Node, NodeHashFunction>& syms);
+
+/** Substitute and generalize a sygus datatype type
+ *
+ * This transforms a sygus datatype sdt into another one sdt' that generates
+ * terms t such that t * { vars -> syms } is generated by sdt.
+ *
+ * The arguments syms and vars should be vectors of the same size and types.
+ * It is recommended that the arguments in syms and vars should be variables
+ * (return true for .isVar()) but this is not required.
+ *
+ * The variables in vars of type BOUND_VARIABLE are added to the
+ * formal argument list of t. Other symbols are not.
+ *
+ * For example, given sdt encodes the grammar:
+ * G -> a | +( b, G ) | c | e
+ * Let syms = { a, b, c } and vars = { x_a, x_b, d }, where x_a and x_b have
+ * type BOUND_VARIABLE and d does not.
+ * The returned type encodes the grammar:
+ * G' -> x_a | +( x_b, G' ) | d | e
+ * Additionally, x_a and x_b are treated as formal arguments of a function
+ * to synthesize whose syntax restrictions are specified by G'.
+ *
+ * This method traverses the type definition of the datatype corresponding to
+ * the argument sdt.
+ */
+TypeNode substituteAndGeneralizeSygusType(TypeNode sdt,
+ const std::vector<Node>& syms,
+ const std::vector<Node>& vars);
+
// ------------------------ end sygus utils
} // namespace utils
diff --git a/src/theory/quantifiers/cegqi/ceg_bv_instantiator.cpp b/src/theory/quantifiers/cegqi/ceg_bv_instantiator.cpp
index f94fee66b..472dabf68 100644
--- a/src/theory/quantifiers/cegqi/ceg_bv_instantiator.cpp
+++ b/src/theory/quantifiers/cegqi/ceg_bv_instantiator.cpp
@@ -633,7 +633,7 @@ struct SortBvExtractInterval
};
void BvInstantiatorPreprocess::registerCounterexampleLemma(
- std::vector<Node>& lems, std::vector<Node>& ce_vars)
+ Node lem, std::vector<Node>& ceVars, std::vector<Node>& auxLems)
{
// new variables
std::vector<Node> vars;
@@ -647,12 +647,8 @@ void BvInstantiatorPreprocess::registerCounterexampleLemma(
// map from terms to bitvector extracts applied to that term
std::map<Node, std::vector<Node> > extract_map;
std::unordered_set<TNode, TNodeHashFunction> visited;
- for (unsigned i = 0, size = lems.size(); i < size; i++)
- {
- Trace("cegqi-bv-pp-debug2")
- << "Register ce lemma # " << i << " : " << lems[i] << std::endl;
- collectExtracts(lems[i], extract_map, visited);
- }
+ Trace("cegqi-bv-pp-debug2") << "Register ce lemma " << lem << std::endl;
+ collectExtracts(lem, extract_map, visited);
for (std::pair<const Node, std::vector<Node> >& es : extract_map)
{
// sort based on the extract start position
@@ -721,10 +717,10 @@ void BvInstantiatorPreprocess::registerCounterexampleLemma(
Trace("cegqi-bv-pp") << "Adding " << new_lems.size() << " lemmas..."
<< std::endl;
- lems.insert(lems.end(), new_lems.begin(), new_lems.end());
+ auxLems.insert(auxLems.end(), new_lems.begin(), new_lems.end());
Trace("cegqi-bv-pp") << "Adding " << vars.size() << " variables..."
<< std::endl;
- ce_vars.insert(ce_vars.end(), vars.begin(), vars.end());
+ ceVars.insert(ceVars.end(), vars.begin(), vars.end());
}
}
diff --git a/src/theory/quantifiers/cegqi/ceg_bv_instantiator.h b/src/theory/quantifiers/cegqi/ceg_bv_instantiator.h
index 3ad45d5be..6f6c216f6 100644
--- a/src/theory/quantifiers/cegqi/ceg_bv_instantiator.h
+++ b/src/theory/quantifiers/cegqi/ceg_bv_instantiator.h
@@ -168,32 +168,32 @@ class BvInstantiatorPreprocess : public InstantiatorPreprocess
~BvInstantiatorPreprocess() override {}
/** register counterexample lemma
*
- * This method modifies the contents of lems based on the extract terms
- * it contains when the option --cbqi-bv-rm-extract is enabled. It introduces
+ * This method adds to auxLems based on the extract terms that lem
+ * contains when the option --cbqi-bv-rm-extract is enabled. It introduces
* a dummy equality so that segments of terms t under extracts can be solved
* independently.
*
- * For example:
+ * For example, if lem is:
* P[ ((extract 7 4) t), ((extract 3 0) t)]
- * becomes:
- * P[((extract 7 4) t), ((extract 3 0) t)] ^
+ * then we add:
* t = concat( x74, x30 )
- * where x74 and x30 are fresh variables of type BV_4.
+ * to auxLems, where x74 and x30 are fresh variables of type BV_4, which are
+ * added to ceVars.
*
- * Another example:
+ * Another example, for:
* P[ ((extract 7 3) t), ((extract 4 0) t)]
- * becomes:
- * P[((extract 7 4) t), ((extract 3 0) t)] ^
+ * we add:
* t = concat( x75, x44, x30 )
- * where x75, x44 and x30 are fresh variables of type BV_3, BV_1, and BV_4
- * respectively.
+ * to auxLems where x75, x44 and x30 are fresh variables of type BV_3, BV_1,
+ * and BV_4 respectively, which are added to ceVars.
*
- * Notice we leave the original conjecture alone. This is done for performance
+ * Notice we leave the original lem alone. This is done for performance
* since the added equalities ensure we are able to construct the proper
* solved forms for variables in t and for the intermediate variables above.
*/
- void registerCounterexampleLemma(std::vector<Node>& lems,
- std::vector<Node>& ce_vars) override;
+ void registerCounterexampleLemma(Node lem,
+ std::vector<Node>& ceVars,
+ std::vector<Node>& auxLems) override;
private:
/** collect extracts
diff --git a/src/theory/quantifiers/cegqi/ceg_instantiator.cpp b/src/theory/quantifiers/cegqi/ceg_instantiator.cpp
index 186024219..95a4037fc 100644
--- a/src/theory/quantifiers/cegqi/ceg_instantiator.cpp
+++ b/src/theory/quantifiers/cegqi/ceg_instantiator.cpp
@@ -21,7 +21,6 @@
#include "expr/node_algorithm.h"
#include "options/quantifiers_options.h"
-#include "smt/term_formula_removal.h"
#include "theory/arith/arith_msum.h"
#include "theory/quantifiers/cegqi/inst_strategy_cegqi.h"
#include "theory/quantifiers/first_order_model.h"
@@ -1571,18 +1570,21 @@ void CegInstantiator::collectCeAtoms( Node n, std::map< Node, bool >& visited )
}
}
-void CegInstantiator::registerCounterexampleLemma( std::vector< Node >& lems, std::vector< Node >& ce_vars ) {
+void CegInstantiator::registerCounterexampleLemma(Node lem,
+ std::vector<Node>& ceVars,
+ std::vector<Node>& auxLems)
+{
Trace("cegqi-reg") << "Register counterexample lemma..." << std::endl;
d_input_vars.clear();
- d_input_vars.insert(d_input_vars.end(), ce_vars.begin(), ce_vars.end());
+ d_input_vars.insert(d_input_vars.end(), ceVars.begin(), ceVars.end());
//Assert( d_vars.empty() );
d_vars.clear();
registerTheoryId(THEORY_UF);
- for (unsigned i = 0; i < ce_vars.size(); i++)
+ for (const Node& cv : ceVars)
{
- Trace("cegqi-reg") << " register input variable : " << ce_vars[i] << std::endl;
- registerVariable(ce_vars[i]);
+ Trace("cegqi-reg") << " register input variable : " << cv << std::endl;
+ registerVariable(cv);
}
// preprocess with all relevant instantiator preprocessors
@@ -1592,7 +1594,7 @@ void CegInstantiator::registerCounterexampleLemma( std::vector< Node >& lems, st
pvars.insert(pvars.end(), d_vars.begin(), d_vars.end());
for (std::pair<const TheoryId, InstantiatorPreprocess*>& p : d_tipp)
{
- p.second->registerCounterexampleLemma(lems, pvars);
+ p.second->registerCounterexampleLemma(lem, pvars, auxLems);
}
// must register variables generated by preprocessors
Trace("cegqi-debug") << "Register variables from theory-specific methods "
@@ -1600,28 +1602,43 @@ void CegInstantiator::registerCounterexampleLemma( std::vector< Node >& lems, st
<< std::endl;
for (unsigned i = d_input_vars.size(), size = pvars.size(); i < size; ++i)
{
- Trace("cegqi-reg") << " register theory preprocess variable : " << pvars[i]
- << std::endl;
+ Trace("cegqi-reg") << " register inst preprocess variable : " << pvars[i]
+ << std::endl;
registerVariable(pvars[i]);
}
- //remove ITEs
- IteSkolemMap iteSkolemMap;
- d_qe->getTheoryEngine()->getTermFormulaRemover()->run(lems, iteSkolemMap);
- for(IteSkolemMap::iterator i = iteSkolemMap.begin(); i != iteSkolemMap.end(); ++i) {
- Trace("cegqi-reg") << " register aux variable : " << i->first << std::endl;
- registerVariable(i->first);
- }
- for( unsigned i=0; i<lems.size(); i++ ){
- Trace("cegqi-debug") << "Counterexample lemma (pre-rewrite) " << i << " : " << lems[i] << std::endl;
- Node rlem = lems[i];
- rlem = Rewriter::rewrite( rlem );
- // also must preprocess to ensure that the counterexample atoms we
- // collect below are identical to the atoms that we add to the CNF stream
- rlem = d_qe->getTheoryEngine()->preprocess(rlem);
- Trace("cegqi-debug") << "Counterexample lemma (post-rewrite) " << i << " : " << rlem << std::endl;
- lems[i] = rlem;
+ // register variables that were introduced during TheoryEngine preprocessing
+ std::unordered_set<Node, NodeHashFunction> ceSyms;
+ expr::getSymbols(lem, ceSyms);
+ std::unordered_set<Node, NodeHashFunction> qSyms;
+ expr::getSymbols(d_quant, qSyms);
+ // all variables that are in counterexample lemma but not in quantified
+ // formula
+ for (const Node& ces : ceSyms)
+ {
+ if (qSyms.find(ces) != qSyms.end())
+ {
+ // a free symbol of the quantified formula.
+ continue;
+ }
+ if (std::find(d_vars.begin(), d_vars.end(), ces) != d_vars.end())
+ {
+ // already processed variable
+ continue;
+ }
+ if (ces.getType().isBoolean())
+ {
+ // Boolean variables, including the counterexample literal, don't matter
+ // since they are always assigned a model value.
+ continue;
+ }
+ Trace("cegqi-reg") << " register theory preprocess variable : " << ces
+ << std::endl;
+ // register the variable, which was introduced by TheoryEngine's preprocess
+ // method, e.g. an ITE skolem.
+ registerVariable(ces);
}
+
// determine variable order: must do Reals before Ints
Trace("cegqi-debug") << "Determine variable order..." << std::endl;
if (!d_vars.empty())
@@ -1673,8 +1690,10 @@ void CegInstantiator::registerCounterexampleLemma( std::vector< Node >& lems, st
// the original body
d_is_nested_quant = false;
std::map< Node, bool > visited;
- for( unsigned i=0; i<lems.size(); i++ ){
- collectCeAtoms( lems[i], visited );
+ collectCeAtoms(lem, visited);
+ for (const Node& alem : auxLems)
+ {
+ collectCeAtoms(alem, visited);
}
}
diff --git a/src/theory/quantifiers/cegqi/ceg_instantiator.h b/src/theory/quantifiers/cegqi/ceg_instantiator.h
index 7351e60f0..08f7a1262 100644
--- a/src/theory/quantifiers/cegqi/ceg_instantiator.h
+++ b/src/theory/quantifiers/cegqi/ceg_instantiator.h
@@ -224,21 +224,20 @@ class CegInstantiator {
void presolve(Node q);
/** Register the counterexample lemma
*
- * lems : contains the conjuncts of the counterexample lemma of the
- * quantified formula we are processing. The counterexample
- * lemma is the formula { ~phi[e/x] } in Figure 1 of Reynolds
- * et al. FMSD 2017.
- * ce_vars : contains the variables e. Notice these are variables of
- * INST_CONSTANT kind, since we do not permit bound
- * variables in assertions.
- *
- * This method may modify the set of lemmas lems based on:
- * - ITE removal,
- * - Theory-specific preprocessing of instantiation lemmas.
- * It may also introduce new variables to ce_vars if necessary.
- */
- void registerCounterexampleLemma(std::vector<Node>& lems,
- std::vector<Node>& ce_vars);
+ * @param lem contains the counterexample lemma of the quantified formula we
+ * are processing. The counterexample lemma is the formula { ~phi[e/x] } in
+ * Figure 1 of Reynolds et al. FMSD 2017.
+ * @param ce_vars contains the variables e. Notice these are variables of
+ * INST_CONSTANT kind, since we do not permit bound variables in assertions.
+ * This method may add additional variables to this vector if it decides there
+ * are additional auxiliary variables to solve for.
+ * @param auxLems : if this method decides that additional lemmas should be
+ * sent on the output channel, they are added to this vector, and sent out by
+ * the caller of this method.
+ */
+ void registerCounterexampleLemma(Node lem,
+ std::vector<Node>& ce_vars,
+ std::vector<Node>& auxLems);
//------------------------------interface for instantiators
/** get quantifiers engine */
QuantifiersEngine* getQuantifiersEngine() { return d_qe; }
@@ -829,8 +828,9 @@ class InstantiatorPreprocess
* of counterexample lemmas, with the same contract as
* CegInstantiation::registerCounterexampleLemma.
*/
- virtual void registerCounterexampleLemma(std::vector<Node>& lems,
- std::vector<Node>& ce_vars)
+ virtual void registerCounterexampleLemma(Node lem,
+ std::vector<Node>& ceVars,
+ std::vector<Node>& auxLems)
{
}
};
diff --git a/src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp b/src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp
index 208eb0bf8..8693f97f4 100644
--- a/src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp
+++ b/src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp
@@ -593,15 +593,18 @@ void InstStrategyCegqi::registerCounterexampleLemma(Node q, Node lem)
{
ce_vars.push_back(tutil->getInstantiationConstant(q, i));
}
- std::vector<Node> lems;
- lems.push_back(lem);
CegInstantiator* cinst = getInstantiator(q);
- cinst->registerCounterexampleLemma(lems, ce_vars);
- for (unsigned i = 0, size = lems.size(); i < size; i++)
+ LemmaStatus status = d_quantEngine->getOutputChannel().lemma(lem);
+ Node ppLem = status.getRewrittenLemma();
+ Trace("cegqi-debug") << "Counterexample lemma (post-preprocess): " << ppLem
+ << std::endl;
+ std::vector<Node> auxLems;
+ cinst->registerCounterexampleLemma(ppLem, ce_vars, auxLems);
+ for (unsigned i = 0, size = auxLems.size(); i < size; i++)
{
- Trace("cegqi-debug") << "Counterexample lemma " << i << " : " << lems[i]
- << std::endl;
- d_quantEngine->addLemma(lems[i], false);
+ Trace("cegqi-debug") << "Auxiliary CE lemma " << i << " : " << auxLems[i]
+ << std::endl;
+ d_quantEngine->addLemma(auxLems[i], false);
}
}
diff --git a/src/theory/quantifiers/extended_rewrite.cpp b/src/theory/quantifiers/extended_rewrite.cpp
index 1f42c384f..8803a9df8 100644
--- a/src/theory/quantifiers/extended_rewrite.cpp
+++ b/src/theory/quantifiers/extended_rewrite.cpp
@@ -586,6 +586,11 @@ Node ExtendedRewriter::extendedRewriteAndOr(Node n)
Node ExtendedRewriter::extendedRewritePullIte(Kind itek, Node n)
{
Assert(n.getKind() != ITE);
+ if (n.isClosure())
+ {
+ // don't pull ITE out of quantifiers
+ return n;
+ }
NodeManager* nm = NodeManager::currentNM();
TypeNode tn = n.getType();
std::vector<Node> children;
diff --git a/src/theory/quantifiers/fmf/full_model_check.cpp b/src/theory/quantifiers/fmf/full_model_check.cpp
index af3a94d96..91cacdc2e 100644
--- a/src/theory/quantifiers/fmf/full_model_check.cpp
+++ b/src/theory/quantifiers/fmf/full_model_check.cpp
@@ -592,139 +592,168 @@ void FullModelChecker::debugPrint(const char * tr, Node n, bool dispStar) {
int FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
Trace("fmc") << "Full model check " << f << ", effort = " << effort << "..." << std::endl;
+ // register the quantifier
+ registerQuantifiedFormula(f);
Assert(!d_qe->inConflict());
- if( optUseModel() ){
- FirstOrderModelFmc * fmfmc = fm->asFirstOrderModelFmc();
- if (effort==0) {
- //register the quantifier
- if (d_quant_cond.find(f)==d_quant_cond.end()) {
- std::vector< TypeNode > types;
- for(unsigned i=0; i<f[0].getNumChildren(); i++){
- types.push_back(f[0][i].getType());
+ // we do not do model-based quantifier instantiation if the option
+ // disables it, or if the quantified formula has an unhandled type.
+ if (!optUseModel() || !isHandled(f))
+ {
+ return 0;
+ }
+ FirstOrderModelFmc* fmfmc = fm->asFirstOrderModelFmc();
+ if (effort == 0)
+ {
+ if (options::mbqiMode() == options::MbqiMode::NONE)
+ {
+ // just exhaustive instantiate
+ Node c = mkCondDefault(fmfmc, f);
+ d_quant_models[f].addEntry(fmfmc, c, d_false);
+ if (!exhaustiveInstantiate(fmfmc, f, c, -1))
+ {
+ return 0;
+ }
+ return 1;
+ }
+ // model check the quantifier
+ doCheck(fmfmc, f, d_quant_models[f], f[1]);
+ std::vector<Node>& mcond = d_quant_models[f].d_cond;
+ Trace("fmc") << "Definition for quantifier " << f << " is : " << std::endl;
+ Assert(!mcond.empty());
+ d_quant_models[f].debugPrint("fmc", Node::null(), this);
+ Trace("fmc") << std::endl;
+
+ // consider all entries going to non-true
+ Instantiate* instq = d_qe->getInstantiate();
+ for (unsigned i = 0, msize = mcond.size(); i < msize; i++)
+ {
+ if (d_quant_models[f].d_value[i] == d_true)
+ {
+ // already satisfied
+ continue;
+ }
+ Trace("fmc-inst") << "Instantiate based on " << mcond[i] << "..."
+ << std::endl;
+ bool hasStar = false;
+ std::vector<Node> inst;
+ for (unsigned j = 0, nchild = mcond[i].getNumChildren(); j < nchild; j++)
+ {
+ if (fmfmc->isStar(mcond[i][j]))
+ {
+ hasStar = true;
+ inst.push_back(fmfmc->getModelBasisTerm(mcond[i][j].getType()));
+ }
+ else
+ {
+ inst.push_back(mcond[i][j]);
}
- TypeNode typ = NodeManager::currentNM()->mkFunctionType( types, NodeManager::currentNM()->booleanType() );
- Node op = NodeManager::currentNM()->mkSkolem( "qfmc", typ, "op created for full-model checking" );
- d_quant_cond[f] = op;
}
-
- if (options::mbqiMode() == options::MbqiMode::NONE)
+ bool addInst = true;
+ if (hasStar)
{
- //just exhaustive instantiate
- Node c = mkCondDefault( fmfmc, f );
- d_quant_models[f].addEntry( fmfmc, c, d_false );
- return exhaustiveInstantiate( fmfmc, f, c, -1);
+ // try obvious (specified by inst)
+ Node ev = d_quant_models[f].evaluate(fmfmc, inst);
+ if (ev == d_true)
+ {
+ addInst = false;
+ Trace("fmc-debug")
+ << "...do not instantiate, evaluation was " << ev << std::endl;
+ }
}
else
{
- //model check the quantifier
- doCheck(fmfmc, f, d_quant_models[f], f[1]);
- Trace("fmc") << "Definition for quantifier " << f << " is : " << std::endl;
- Assert(!d_quant_models[f].d_cond.empty());
- d_quant_models[f].debugPrint("fmc", Node::null(), this);
- Trace("fmc") << std::endl;
-
- //consider all entries going to non-true
- for (unsigned i=0; i<d_quant_models[f].d_cond.size(); i++) {
- if( d_quant_models[f].d_value[i]!=d_true ) {
- Trace("fmc-inst") << "Instantiate based on " << d_quant_models[f].d_cond[i] << "..." << std::endl;
- bool hasStar = false;
- std::vector< Node > inst;
- for (unsigned j=0; j<d_quant_models[f].d_cond[i].getNumChildren(); j++) {
- if (fmfmc->isStar(d_quant_models[f].d_cond[i][j])) {
- hasStar = true;
- inst.push_back(fmfmc->getModelBasisTerm(d_quant_models[f].d_cond[i][j].getType()));
- }else{
- inst.push_back(d_quant_models[f].d_cond[i][j]);
- }
- }
- bool addInst = true;
- if( hasStar ){
- //try obvious (specified by inst)
- Node ev = d_quant_models[f].evaluate(fmfmc, inst);
- if (ev==d_true) {
- addInst = false;
- Trace("fmc-debug") << "...do not instantiate, evaluation was " << ev << std::endl;
- }
- }else{
- //for debugging
- if (Trace.isOn("fmc-test-inst")) {
- Node ev = d_quant_models[f].evaluate(fmfmc, inst);
- if( ev==d_true ){
- Message() << "WARNING: instantiation was true! " << f << " "
- << d_quant_models[f].d_cond[i] << std::endl;
- AlwaysAssert(false);
- }else{
- Trace("fmc-test-inst") << "...instantiation evaluated to false." << std::endl;
- }
- }
- }
- if( addInst ){
- if( options::fmfBound() ){
- std::vector< Node > cond;
- cond.push_back(d_quant_cond[f]);
- cond.insert( cond.end(), inst.begin(), inst.end() );
- //need to do exhaustive instantiate algorithm to set things properly (should only add one instance)
- Node c = mkCond( cond );
- unsigned prevInst = d_addedLemmas;
- exhaustiveInstantiate( fmfmc, f, c, -1 );
- if( d_addedLemmas==prevInst ){
- d_star_insts[f].push_back(i);
- }
- }else{
- //just add the instance
- d_triedLemmas++;
- if (d_qe->getInstantiate()->addInstantiation(f, inst, true))
- {
- Trace("fmc-debug-inst") << "** Added instantiation." << std::endl;
- d_addedLemmas++;
- if( d_qe->inConflict() || options::fmfOneInstPerRound() ){
- break;
- }
- }else{
- Trace("fmc-debug-inst") << "** Instantiation was duplicate." << std::endl;
- //this can happen if evaluation is unknown, or if we are generalizing a star that already has a value
- //if( !hasStar && d_quant_models[f].d_value[i]==d_false ){
- // Trace("fmc-warn") << "**** FMC warning: inconsistent duplicate instantiation." << std::endl;
- //}
- //this assertion can happen if two instantiations from this round are identical
- // (0,1)->false (1,0)->false for forall xy. f( x, y ) = f( y, x )
- //Assert( hasStar || d_quant_models[f].d_value[i]!=d_false );
- //might try it next effort level
- d_star_insts[f].push_back(i);
- }
- }
- }else{
- Trace("fmc-debug-inst") << "** Instantiation was already true." << std::endl;
- //might try it next effort level
- d_star_insts[f].push_back(i);
- }
+ // for debugging
+ if (Trace.isOn("fmc-test-inst"))
+ {
+ Node ev = d_quant_models[f].evaluate(fmfmc, inst);
+ if (ev == d_true)
+ {
+ Message() << "WARNING: instantiation was true! " << f << " "
+ << mcond[i] << std::endl;
+ AlwaysAssert(false);
+ }
+ else
+ {
+ Trace("fmc-test-inst")
+ << "...instantiation evaluated to false." << std::endl;
}
}
}
- }else{
- if (!d_star_insts[f].empty()) {
- Trace("fmc-exh") << "Exhaustive instantiate " << f << std::endl;
- Trace("fmc-exh") << "Definition was : " << std::endl;
- d_quant_models[f].debugPrint("fmc-exh", Node::null(), this);
- Trace("fmc-exh") << std::endl;
- Def temp;
- //simplify the exceptions?
- for( int i=(d_star_insts[f].size()-1); i>=0; i--) {
- //get witness for d_star_insts[f][i]
- int j = d_star_insts[f][i];
- if( temp.addEntry(fmfmc, d_quant_models[f].d_cond[j], d_quant_models[f].d_value[j] ) ){
- if( !exhaustiveInstantiate(fmfmc, f, d_quant_models[f].d_cond[j], j ) ){
- //something went wrong, resort to exhaustive instantiation
- return 0;
- }
- }
+ if (!addInst)
+ {
+ Trace("fmc-debug-inst")
+ << "** Instantiation was already true." << std::endl;
+ // might try it next effort level
+ d_star_insts[f].push_back(i);
+ continue;
+ }
+ if (options::fmfBound())
+ {
+ std::vector<Node> cond;
+ cond.push_back(d_quant_cond[f]);
+ cond.insert(cond.end(), inst.begin(), inst.end());
+ // need to do exhaustive instantiate algorithm to set things properly
+ // (should only add one instance)
+ Node c = mkCond(cond);
+ unsigned prevInst = d_addedLemmas;
+ exhaustiveInstantiate(fmfmc, f, c, -1);
+ if (d_addedLemmas == prevInst)
+ {
+ d_star_insts[f].push_back(i);
}
+ continue;
+ }
+ // just add the instance
+ d_triedLemmas++;
+ if (instq->addInstantiation(f, inst, true))
+ {
+ Trace("fmc-debug-inst") << "** Added instantiation." << std::endl;
+ d_addedLemmas++;
+ if (d_qe->inConflict() || options::fmfOneInstPerRound())
+ {
+ break;
+ }
+ }
+ else
+ {
+ Trace("fmc-debug-inst")
+ << "** Instantiation was duplicate." << std::endl;
+ // might try it next effort level
+ d_star_insts[f].push_back(i);
}
}
return 1;
- }else{
- return 0;
}
+ // Get the list of instantiation regions (described by "star entries" in the
+ // definition) that were not tried at the previous effort level. For each
+ // of these, we add one instantiation.
+ std::vector<Node>& mcond = d_quant_models[f].d_cond;
+ if (!d_star_insts[f].empty())
+ {
+ if (Trace.isOn("fmc-exh"))
+ {
+ Trace("fmc-exh") << "Exhaustive instantiate " << f << std::endl;
+ Trace("fmc-exh") << "Definition was : " << std::endl;
+ d_quant_models[f].debugPrint("fmc-exh", Node::null(), this);
+ Trace("fmc-exh") << std::endl;
+ }
+ Def temp;
+ // simplify the exceptions?
+ for (int i = (d_star_insts[f].size() - 1); i >= 0; i--)
+ {
+ // get witness for d_star_insts[f][i]
+ int j = d_star_insts[f][i];
+ if (temp.addEntry(fmfmc, mcond[j], d_quant_models[f].d_value[j]))
+ {
+ if (!exhaustiveInstantiate(fmfmc, f, mcond[j], j))
+ {
+ // something went wrong, resort to exhaustive instantiation
+ return 0;
+ }
+ }
+ }
+ }
+ return 1;
}
/** Representative bound fmc entry
@@ -1290,3 +1319,33 @@ Node FullModelChecker::getFunctionValue(FirstOrderModelFmc * fm, Node op, const
bool FullModelChecker::useSimpleModels() {
return options::fmfFmcSimple();
}
+
+void FullModelChecker::registerQuantifiedFormula(Node q)
+{
+ if (d_quant_cond.find(q) != d_quant_cond.end())
+ {
+ return;
+ }
+ NodeManager* nm = NodeManager::currentNM();
+ std::vector<TypeNode> types;
+ for (const Node& v : q[0])
+ {
+ TypeNode tn = v.getType();
+ if (tn.isFunction())
+ {
+ // we will not use model-based quantifier instantiation for q, since
+ // the model-based instantiation algorithm does not handle (universally
+ // quantified) functions
+ d_unhandledQuant.insert(q);
+ }
+ types.push_back(tn);
+ }
+ TypeNode typ = nm->mkFunctionType(types, nm->booleanType());
+ Node op = nm->mkSkolem("qfmc", typ, "op for full-model checking");
+ d_quant_cond[q] = op;
+}
+
+bool FullModelChecker::isHandled(Node q) const
+{
+ return d_unhandledQuant.find(q) == d_unhandledQuant.end();
+}
diff --git a/src/theory/quantifiers/fmf/full_model_check.h b/src/theory/quantifiers/fmf/full_model_check.h
index 7dd1991f5..60de5d1eb 100644
--- a/src/theory/quantifiers/fmf/full_model_check.h
+++ b/src/theory/quantifiers/fmf/full_model_check.h
@@ -86,7 +86,16 @@ protected:
Node d_false;
std::map<TypeNode, std::map< Node, int > > d_rep_ids;
std::map<Node, Def > d_quant_models;
+ /**
+ * The predicate for the quantified formula. This is used to express
+ * conditions under which the quantified formula is false in the model.
+ * For example, for quantified formula (forall x:Int, y:U. P), this is
+ * a predicate of type (Int x U) -> Bool.
+ */
std::map<Node, Node > d_quant_cond;
+ /** A set of quantified formulas that cannot be handled by model-based
+ * quantifier instantiation */
+ std::unordered_set<Node, NodeHashFunction> d_unhandledQuant;
std::map< TypeNode, Node > d_array_cond;
std::map< Node, Node > d_array_term_cond;
std::map< Node, std::vector< int > > d_star_insts;
@@ -155,6 +164,16 @@ public:
bool processBuildModel(TheoryModel* m) override;
bool useSimpleModels();
+
+ private:
+ /**
+ * Register quantified formula.
+ * This checks whether q can be handled by model-based instantiation and
+ * initializes the necessary information if so.
+ */
+ void registerQuantifiedFormula(Node q);
+ /** Is quantified formula q handled by model-based instantiation? */
+ bool isHandled(Node q) const;
};/* class FullModelChecker */
}/* CVC4::theory::quantifiers::fmcheck namespace */
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
index df86922bc..43c6e73bc 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.cpp
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -1342,15 +1342,19 @@ Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >&
}
Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, std::vector< Node >& nargs, bool pol, bool prenexAgg ){
- if( body.getKind()==FORALL ){
+ NodeManager* nm = NodeManager::currentNM();
+ Kind k = body.getKind();
+ if (k == FORALL)
+ {
if( ( pol || prenexAgg ) && ( options::prenexQuantUser() || body.getNumChildren()==2 ) ){
std::vector< Node > terms;
std::vector< Node > subs;
//for doing prenexing of same-signed quantifiers
//must rename each variable that already exists
- for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
- terms.push_back( body[0][i] );
- subs.push_back( NodeManager::currentNM()->mkBoundVar( body[0][i].getType() ) );
+ for (const Node& v : body[0])
+ {
+ terms.push_back(v);
+ subs.push_back(nm->mkBoundVar(v.getType()));
}
if( pol ){
args.insert( args.end(), subs.begin(), subs.end() );
@@ -1362,161 +1366,134 @@ Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, s
return newBody;
}
//must remove structure
- }else if( prenexAgg && body.getKind()==kind::ITE && body.getType().isBoolean() ){
- Node nn = NodeManager::currentNM()->mkNode( kind::AND,
- NodeManager::currentNM()->mkNode( kind::OR, body[0].notNode(), body[1] ),
- NodeManager::currentNM()->mkNode( kind::OR, body[0], body[2] ) );
+ }
+ else if (prenexAgg && k == ITE && body.getType().isBoolean())
+ {
+ Node nn = nm->mkNode(AND,
+ nm->mkNode(OR, body[0].notNode(), body[1]),
+ nm->mkNode(OR, body[0], body[2]));
return computePrenex( nn, args, nargs, pol, prenexAgg );
- }else if( prenexAgg && body.getKind()==kind::EQUAL && body[0].getType().isBoolean() ){
- Node nn = NodeManager::currentNM()->mkNode( kind::AND,
- NodeManager::currentNM()->mkNode( kind::OR, body[0].notNode(), body[1] ),
- NodeManager::currentNM()->mkNode( kind::OR, body[0], body[1].notNode() ) );
+ }
+ else if (prenexAgg && k == EQUAL && body[0].getType().isBoolean())
+ {
+ Node nn = nm->mkNode(AND,
+ nm->mkNode(OR, body[0].notNode(), body[1]),
+ nm->mkNode(OR, body[0], body[1].notNode()));
return computePrenex( nn, args, nargs, pol, prenexAgg );
}else if( body.getType().isBoolean() ){
- Assert(body.getKind() != EXISTS);
+ Assert(k != EXISTS);
bool childrenChanged = false;
std::vector< Node > newChildren;
- for( unsigned i=0; i<body.getNumChildren(); i++ ){
+ for (size_t i = 0, nchild = body.getNumChildren(); i < nchild; i++)
+ {
bool newHasPol;
bool newPol;
QuantPhaseReq::getPolarity( body, i, true, pol, newHasPol, newPol );
- if( newHasPol ){
- Node n = computePrenex( body[i], args, nargs, newPol, prenexAgg );
- newChildren.push_back( n );
- if( n!=body[i] ){
- childrenChanged = true;
- }
- }else{
+ if (!newHasPol)
+ {
newChildren.push_back( body[i] );
+ continue;
}
+ Node n = computePrenex(body[i], args, nargs, newPol, prenexAgg);
+ newChildren.push_back(n);
+ childrenChanged = n != body[i] || childrenChanged;
}
if( childrenChanged ){
- if( body.getKind()==NOT && newChildren[0].getKind()==NOT ){
+ if (k == NOT && newChildren[0].getKind() == NOT)
+ {
return newChildren[0][0];
- }else{
- return NodeManager::currentNM()->mkNode( body.getKind(), newChildren );
}
+ return nm->mkNode(k, newChildren);
}
}
return body;
}
-Node QuantifiersRewriter::computePrenexAgg( Node n, bool topLevel, std::map< unsigned, std::map< Node, Node > >& visited ){
- unsigned tindex = topLevel ? 0 : 1;
- std::map< Node, Node >::iterator itv = visited[tindex].find( n );
- if( itv!=visited[tindex].end() ){
+Node QuantifiersRewriter::computePrenexAgg(Node n,
+ std::map<Node, Node>& visited)
+{
+ std::map< Node, Node >::iterator itv = visited.find( n );
+ if( itv!=visited.end() ){
return itv->second;
}
- if (expr::hasClosure(n))
+ if (!expr::hasClosure(n))
+ {
+ // trivial
+ return n;
+ }
+ NodeManager* nm = NodeManager::currentNM();
+ Node ret = n;
+ if (n.getKind() == NOT)
+ {
+ ret = computePrenexAgg(n[0], visited).negate();
+ }
+ else if (n.getKind() == FORALL)
{
- Node ret = n;
- if (topLevel
- && options::prenexQuant() == options::PrenexQuantMode::DISJ_NORMAL
- && (n.getKind() == AND || (n.getKind() == NOT && n[0].getKind() == OR)))
+ std::vector<Node> children;
+ children.push_back(computePrenexAgg(n[1], visited));
+ std::vector<Node> args;
+ args.insert(args.end(), n[0].begin(), n[0].end());
+ // for each child, strip top level quant
+ for (unsigned i = 0; i < children.size(); i++)
{
- std::vector< Node > children;
- Node nc = n.getKind()==NOT ? n[0] : n;
- for( unsigned i=0; i<nc.getNumChildren(); i++ ){
- Node ncc = computePrenexAgg( nc[i], true, visited );
- if( n.getKind()==NOT ){
- ncc = ncc.negate();
- }
- children.push_back( ncc );
+ if (children[i].getKind() == FORALL)
+ {
+ args.insert(args.end(), children[i][0].begin(), children[i][0].end());
+ children[i] = children[i][1];
}
- ret = NodeManager::currentNM()->mkNode( AND, children );
}
- else if (n.getKind() == NOT)
+ // keep the pattern
+ std::vector<Node> iplc;
+ if (n.getNumChildren() == 3)
{
- ret = computePrenexAgg( n[0], false, visited ).negate();
+ iplc.insert(iplc.end(), n[2].begin(), n[2].end());
}
- else if (n.getKind() == FORALL)
+ Node nb = children.size() == 1 ? children[0] : nm->mkNode(OR, children);
+ ret = mkForall(args, nb, iplc, true);
+ }
+ else
+ {
+ std::vector<Node> args;
+ std::vector<Node> nargs;
+ Node nn = computePrenex(n, args, nargs, true, true);
+ if (n != nn)
{
- /*
- Node nn = computePrenexAgg( n[1], false );
- if( nn!=n[1] ){
- if( n.getNumChildren()==2 ){
- return NodeManager::currentNM()->mkNode( FORALL, n[0], nn );
- }else{
- return NodeManager::currentNM()->mkNode( FORALL, n[0], nn, n[2] );
- }
- }
- */
- std::vector< Node > children;
- if (n[1].getKind() == OR
- && options::prenexQuant() == options::PrenexQuantMode::DISJ_NORMAL)
+ Node nnn = computePrenexAgg(nn, visited);
+ // merge prenex
+ if (nnn.getKind() == FORALL)
{
- for( unsigned i=0; i<n[1].getNumChildren(); i++ ){
- children.push_back( computePrenexAgg( n[1][i], false, visited ) );
+ args.insert(args.end(), nnn[0].begin(), nnn[0].end());
+ nnn = nnn[1];
+ // pos polarity variables are inner
+ if (!args.empty())
+ {
+ nnn = mkForall(args, nnn, true);
}
+ args.clear();
}
- else
+ else if (nnn.getKind() == NOT && nnn[0].getKind() == FORALL)
{
- children.push_back( computePrenexAgg( n[1], false, visited ) );
+ nargs.insert(nargs.end(), nnn[0][0].begin(), nnn[0][0].end());
+ nnn = nnn[0][1].negate();
}
- std::vector< Node > args;
- for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
- args.push_back( n[0][i] );
+ if (!nargs.empty())
+ {
+ nnn = mkForall(nargs, nnn.negate(), true).negate();
}
- std::vector< Node > nargs;
- //for each child, strip top level quant
- for( unsigned i=0; i<children.size(); i++ ){
- if( children[i].getKind()==FORALL ){
- for( unsigned j=0; j<children[i][0].getNumChildren(); j++ ){
- args.push_back( children[i][0][j] );
- }
- children[i] = children[i][1];
- }
+ if (!args.empty())
+ {
+ nnn = mkForall(args, nnn, true);
}
- // keep the pattern
- std::vector< Node > iplc;
- if( n.getNumChildren()==3 ){
- for( unsigned i=0; i<n[2].getNumChildren(); i++ ){
- iplc.push_back( n[2][i] );
- }
- }
- Node nb = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( OR, children );
- ret = mkForall( args, nb, iplc, true );
+ ret = nnn;
}
else
{
- std::vector< Node > args;
- std::vector< Node > nargs;
- Node nn = computePrenex( n, args, nargs, true, true );
- if( n!=nn ){
- Node nnn = computePrenexAgg( nn, false, visited );
- //merge prenex
- if( nnn.getKind()==FORALL ){
- for( unsigned i=0; i<nnn[0].getNumChildren(); i++ ){
- args.push_back( nnn[0][i] );
- }
- nnn = nnn[1];
- //pos polarity variables are inner
- if( !args.empty() ){
- nnn = mkForall( args, nnn, true );
- }
- args.clear();
- }else if( nnn.getKind()==NOT && nnn[0].getKind()==FORALL ){
- for( unsigned i=0; i<nnn[0][0].getNumChildren(); i++ ){
- nargs.push_back( nnn[0][0][i] );
- }
- nnn = nnn[0][1].negate();
- }
- if( !nargs.empty() ){
- nnn = mkForall( nargs, nnn.negate(), true ).negate();
- }
- if( !args.empty() ){
- nnn = mkForall( args, nnn, true );
- }
- ret = nnn;
- }else{
- Assert(args.empty());
- Assert(nargs.empty());
- }
+ Assert(args.empty());
+ Assert(nargs.empty());
}
- visited[tindex][n] = ret;
- return ret;
}
- return n;
+ visited[n] = ret;
+ return ret;
}
Node QuantifiersRewriter::computeSplit( std::vector< Node >& args, Node body, QAttributes& qa ) {
@@ -1925,8 +1902,7 @@ Node QuantifiersRewriter::computeOperation(Node f,
if( computeOption==COMPUTE_ELIM_SYMBOLS ){
n = computeElimSymbols( n );
}else if( computeOption==COMPUTE_MINISCOPING ){
- if (options::prenexQuant() == options::PrenexQuantMode::DISJ_NORMAL
- || options::prenexQuant() == options::PrenexQuantMode::NORMAL)
+ if (options::prenexQuant() == options::PrenexQuantMode::NORMAL)
{
if( !qa.d_qid_num.isNull() ){
//already processed this, return self
@@ -1957,8 +1933,7 @@ Node QuantifiersRewriter::computeOperation(Node f,
}
else if (computeOption == COMPUTE_PRENEX)
{
- if (options::prenexQuant() == options::PrenexQuantMode::DISJ_NORMAL
- || options::prenexQuant() == options::PrenexQuantMode::NORMAL)
+ if (options::prenexQuant() == options::PrenexQuantMode::NORMAL)
{
//will rewrite at preprocess time
return f;
@@ -2091,12 +2066,11 @@ Node QuantifiersRewriter::preprocess( Node n, bool isInst ) {
}
}
//pull all quantifiers globally
- if (options::prenexQuant() == options::PrenexQuantMode::DISJ_NORMAL
- || options::prenexQuant() == options::PrenexQuantMode::NORMAL)
+ if (options::prenexQuant() == options::PrenexQuantMode::NORMAL)
{
Trace("quantifiers-prenex") << "Prenexing : " << n << std::endl;
- std::map< unsigned, std::map< Node, Node > > visited;
- n = computePrenexAgg( n, true, visited );
+ std::map<Node, Node> visited;
+ n = computePrenexAgg(n, visited);
n = Rewriter::rewrite( n );
Trace("quantifiers-prenex") << "Prenexing returned : " << n << std::endl;
//Assert( isPrenexNormalForm( n ) );
diff --git a/src/theory/quantifiers/quantifiers_rewriter.h b/src/theory/quantifiers/quantifiers_rewriter.h
index 2a3180e78..c8995ef4e 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.h
+++ b/src/theory/quantifiers/quantifiers_rewriter.h
@@ -234,8 +234,27 @@ class QuantifiersRewriter : public TheoryRewriter
static Node computeElimSymbols( Node body );
static Node computeMiniscoping( std::vector< Node >& args, Node body, QAttributes& qa );
static Node computeAggressiveMiniscoping( std::vector< Node >& args, Node body );
+ /**
+ * This function removes top-level quantifiers from subformulas of body
+ * appearing with overall polarity pol. It adds quantified variables that
+ * appear in positive polarity positions into args, and those at negative
+ * polarity positions in nargs.
+ *
+ * If prenexAgg is true, we ensure that all top-level quantifiers are
+ * eliminated from subformulas. This means that we must expand ITE and
+ * Boolean equalities to ensure that quantifiers are at fixed polarities.
+ *
+ * For example, calling this function on:
+ * (or (forall ((x Int)) (P x z)) (not (forall ((y Int)) (Q y z))))
+ * would return:
+ * (or (P x z) (not (Q y z)))
+ * and add {x} to args, and {y} to nargs.
+ */
static Node computePrenex( Node body, std::vector< Node >& args, std::vector< Node >& nargs, bool pol, bool prenexAgg );
- static Node computePrenexAgg( Node n, bool topLevel, std::map< unsigned, std::map< Node, Node > >& visited );
+ /**
+ * Apply prenexing aggressively. Returns the prenex normal form of n.
+ */
+ static Node computePrenexAgg(Node n, std::map<Node, Node>& visited);
static Node computeSplit( std::vector< Node >& args, Node body, QAttributes& qa );
private:
static Node computeOperation(Node f,
diff --git a/src/theory/quantifiers/sygus/sygus_abduct.cpp b/src/theory/quantifiers/sygus/sygus_abduct.cpp
index a58c5d841..ef2e7e445 100644
--- a/src/theory/quantifiers/sygus/sygus_abduct.cpp
+++ b/src/theory/quantifiers/sygus/sygus_abduct.cpp
@@ -19,7 +19,6 @@
#include "expr/dtype.h"
#include "expr/node_algorithm.h"
#include "expr/sygus_datatype.h"
-#include "printer/sygus_print_callback.h"
#include "theory/datatypes/theory_datatypes_utils.h"
#include "theory/quantifiers/quantifiers_attributes.h"
#include "theory/quantifiers/quantifiers_rewriter.h"
@@ -58,6 +57,12 @@ Node SygusAbduct::mkAbductionConjecture(const std::string& name,
for (const Node& s : symset)
{
TypeNode tn = s.getType();
+ if (tn.isConstructor() || tn.isSelector() || tn.isTester())
+ {
+ // datatype symbols should be considered interpreted symbols here, not
+ // (higher-order) variables.
+ continue;
+ }
// Notice that we allow for non-first class (e.g. function) variables here.
// This is applicable to the case where we are doing get-abduct in a logic
// with UF.
@@ -73,8 +78,6 @@ Node SygusAbduct::mkAbductionConjecture(const std::string& name,
SygusVarToTermAttribute sta;
vlv.setAttribute(sta, s);
}
- // make the sygus variable list
- Node abvl = nm->mkNode(BOUND_VAR_LIST, varlist);
Trace("sygus-abduct-debug") << "...finish" << std::endl;
Trace("sygus-abduct-debug") << "Make abduction predicate..." << std::endl;
@@ -84,163 +87,23 @@ Node SygusAbduct::mkAbductionConjecture(const std::string& name,
Node abd = nm->mkBoundVar(name.c_str(), abdType);
Trace("sygus-abduct-debug") << "...finish" << std::endl;
- // if provided, we will associate it with the function-to-synthesize
+ // the sygus variable list
+ Node abvl;
+ // if provided, we will associate the provide sygus datatype type with the
+ // function-to-synthesize. However, we must convert it so that its
+ // free symbols are universally quantified.
if (!abdGType.isNull())
{
Assert(abdGType.isDatatype() && abdGType.getDType().isSygus());
- // must convert all constructors to version with bound variables in "vars"
- std::vector<SygusDatatype> sdts;
- std::set<Type> unres;
-
Trace("sygus-abduct-debug") << "Process abduction type:" << std::endl;
Trace("sygus-abduct-debug") << abdGType.getDType().getName() << std::endl;
- // datatype types we need to process
- std::vector<TypeNode> dtToProcess;
- // datatype types we have processed
- std::map<TypeNode, TypeNode> dtProcessed;
- dtToProcess.push_back(abdGType);
- std::stringstream ssutn0;
- ssutn0 << abdGType.getDType().getName() << "_s";
- TypeNode abdTNew =
- nm->mkSort(ssutn0.str(), ExprManager::SORT_FLAG_PLACEHOLDER);
- unres.insert(abdTNew.toType());
- dtProcessed[abdGType] = abdTNew;
-
- // We must convert all symbols in the sygus datatype type abdGType to
- // apply the substitution { syms -> varlist }, where syms is the free
- // variables of the input problem, and varlist is the formal argument list
- // of the abduct-to-synthesize. For example, given user-provided sygus
- // grammar:
- // G -> a | +( b, G )
- // we synthesize a abduct A with two arguments x_a and x_b corresponding to
- // a and b, and reconstruct the grammar:
- // G' -> x_a | +( x_b, G' )
- // In this way, x_a and x_b are treated as bound variables and handled as
- // arguments of the abduct-to-synthesize instead of as free variables with
- // no relation to A. We additionally require that x_a, when printed, prints
- // "a", which we do with a custom sygus callback below.
+ // substitute the free symbols of the grammar with variables corresponding
+ // to the formal argument list of the new sygus datatype type.
+ TypeNode abdGTypeS = datatypes::utils::substituteAndGeneralizeSygusType(
+ abdGType, syms, varlist);
- // We are traversing over the subfield types of the datatype to convert
- // them into the form described above.
- while (!dtToProcess.empty())
- {
- std::vector<TypeNode> dtNextToProcess;
- for (const TypeNode& curr : dtToProcess)
- {
- Assert(curr.isDatatype() && curr.getDType().isSygus());
- const DType& dtc = curr.getDType();
- std::stringstream ssdtn;
- ssdtn << dtc.getName() << "_s";
- sdts.push_back(SygusDatatype(ssdtn.str()));
- Trace("sygus-abduct-debug")
- << "Process datatype " << sdts.back().getName() << "..."
- << std::endl;
- for (unsigned j = 0, ncons = dtc.getNumConstructors(); j < ncons; j++)
- {
- Node op = dtc[j].getSygusOp();
- // apply the substitution to the argument
- Node ops = op.substitute(
- syms.begin(), syms.end(), varlist.begin(), varlist.end());
- Trace("sygus-abduct-debug") << " Process constructor " << op << " / "
- << ops << "..." << std::endl;
- std::vector<TypeNode> cargs;
- for (unsigned k = 0, nargs = dtc[j].getNumArgs(); k < nargs; k++)
- {
- TypeNode argt = dtc[j].getArgType(k);
- std::map<TypeNode, TypeNode>::iterator itdp =
- dtProcessed.find(argt);
- TypeNode argtNew;
- if (itdp == dtProcessed.end())
- {
- std::stringstream ssutn;
- ssutn << argt.getDType().getName() << "_s";
- argtNew =
- nm->mkSort(ssutn.str(), ExprManager::SORT_FLAG_PLACEHOLDER);
- Trace("sygus-abduct-debug")
- << " ...unresolved type " << argtNew << " for " << argt
- << std::endl;
- unres.insert(argtNew.toType());
- dtProcessed[argt] = argtNew;
- dtNextToProcess.push_back(argt);
- }
- else
- {
- argtNew = itdp->second;
- }
- Trace("sygus-abduct-debug")
- << " Arg #" << k << ": " << argtNew << std::endl;
- cargs.push_back(argtNew);
- }
- // callback prints as the expression
- std::shared_ptr<SygusPrintCallback> spc;
- std::vector<Expr> args;
- if (op.getKind() == LAMBDA)
- {
- Node opBody = op[1];
- for (const Node& v : op[0])
- {
- args.push_back(v.toExpr());
- }
- spc = std::make_shared<printer::SygusExprPrintCallback>(
- opBody.toExpr(), args);
- }
- else if (cargs.empty())
- {
- spc = std::make_shared<printer::SygusExprPrintCallback>(op.toExpr(),
- args);
- }
- std::stringstream ss;
- ss << ops.getKind();
- Trace("sygus-abduct-debug")
- << "Add constructor : " << ops << std::endl;
- sdts.back().addConstructor(ops, ss.str(), cargs, spc);
- }
- Trace("sygus-abduct-debug")
- << "Set sygus : " << dtc.getSygusType() << " " << abvl << std::endl;
- TypeNode stn = dtc.getSygusType();
- sdts.back().initializeDatatype(
- stn, abvl, dtc.getSygusAllowConst(), dtc.getSygusAllowAll());
- }
- dtToProcess.clear();
- dtToProcess.insert(
- dtToProcess.end(), dtNextToProcess.begin(), dtNextToProcess.end());
- }
- Trace("sygus-abduct-debug")
- << "Make " << sdts.size() << " datatype types..." << std::endl;
- // extract the datatypes
- std::vector<Datatype> datatypes;
- for (unsigned i = 0, ndts = sdts.size(); i < ndts; i++)
- {
- datatypes.push_back(sdts[i].getDatatype());
- }
- // make the datatype types
- std::vector<DatatypeType> datatypeTypes =
- nm->toExprManager()->mkMutualDatatypeTypes(
- datatypes, unres, ExprManager::DATATYPE_FLAG_PLACEHOLDER);
- TypeNode abdGTypeS = TypeNode::fromType(datatypeTypes[0]);
- if (Trace.isOn("sygus-abduct-debug"))
- {
- Trace("sygus-abduct-debug") << "Made datatype types:" << std::endl;
- for (unsigned j = 0, ndts = datatypeTypes.size(); j < ndts; j++)
- {
- const DType& dtj = TypeNode::fromType(datatypeTypes[j]).getDType();
- Trace("sygus-abduct-debug") << "#" << j << ": " << dtj << std::endl;
- for (unsigned k = 0, ncons = dtj.getNumConstructors(); k < ncons; k++)
- {
- for (unsigned l = 0, nargs = dtj[k].getNumArgs(); l < nargs; l++)
- {
- if (!dtj[k].getArgType(l).isDatatype())
- {
- Trace("sygus-abduct-debug")
- << "Argument " << l << " of " << dtj[k]
- << " is not datatype : " << dtj[k].getArgType(l) << std::endl;
- AlwaysAssert(false);
- }
- }
- }
- }
- }
+ Assert(abdGTypeS.isDatatype() && abdGTypeS.getDType().isSygus());
Trace("sygus-abduct-debug")
<< "Make sygus grammar attribute..." << std::endl;
@@ -250,6 +113,19 @@ Node SygusAbduct::mkAbductionConjecture(const std::string& name,
theory::SygusSynthGrammarAttribute ssg;
abd.setAttribute(ssg, sym);
Trace("sygus-abduct-debug") << "Finished setting up grammar." << std::endl;
+
+ // use the bound variable list from the new substituted grammar type
+ const DType& agtsd = abdGTypeS.getDType();
+ abvl = agtsd.getSygusVarList();
+ Assert(!abvl.isNull() && abvl.getKind() == BOUND_VAR_LIST);
+ }
+ else
+ {
+ // the bound variable list of the abduct-to-synthesize is determined by
+ // the variable list above
+ abvl = nm->mkNode(BOUND_VAR_LIST, varlist);
+ // We do not set a grammar type for abd (SygusSynthGrammarAttribute).
+ // Its grammar will be constructed internally in the default way
}
Trace("sygus-abduct-debug") << "Make abduction predicate app..." << std::endl;
diff --git a/src/theory/strings/kinds b/src/theory/strings/kinds
index 06f05a8af..800847ffe 100644
--- a/src/theory/strings/kinds
+++ b/src/theory/strings/kinds
@@ -58,6 +58,27 @@ constant CONST_STRING \
"util/string.h" \
"a string of characters"
+# the type
+operator SEQUENCE_TYPE 1 "seuence type, takes as parameter the type of the elements"
+cardinality SEQUENCE_TYPE \
+ "::CVC4::theory::strings::SequenceProperties::computeCardinality(%TYPE%)" \
+ "theory/strings/theory_strings_type_rules.h"
+well-founded SEQUENCE_TYPE \
+ "::CVC4::theory::strings::SequenceProperties::isWellFounded(%TYPE%)" \
+ "::CVC4::theory::strings::SequenceProperties::mkGroundTerm(%TYPE%)" \
+ "theory/strings/theory_strings_type_rules.h"
+enumerator SEQUENCE_TYPE \
+ "::CVC4::theory::strings::SequenceEnumerator" \
+ "theory/strings/type_enumerator.h"
+
+constant CONST_SEQUENCE \
+ ::CVC4::ExprSequence \
+ ::CVC4::ExprSequenceHashFunction \
+ "expr/expr_sequence.h" \
+ "a sequence of characters"
+
+operator SEQ_UNIT 1 "a sequence of length one"
+
# equal equal / less than / output
operator STRING_TO_REGEXP 1 "convert string to regexp"
operator REGEXP_CONCAT 2: "regexp concat"
@@ -138,4 +159,9 @@ typerule STRING_FROM_CODE "SimpleTypeRule<RString, AInteger>"
typerule STRING_TOUPPER "SimpleTypeRule<RString, AString>"
typerule STRING_TOLOWER "SimpleTypeRule<RString, AString>"
+### sequence specific operators
+
+typerule CONST_SEQUENCE ::CVC4::theory::strings::ConstSequenceTypeRule
+typerule SEQ_UNIT ::CVC4::theory::strings::SeqUnitTypeRule
+
endtheory
diff --git a/src/theory/strings/rewrites.cpp b/src/theory/strings/rewrites.cpp
index 2953a2b3c..a4055c4f9 100644
--- a/src/theory/strings/rewrites.cpp
+++ b/src/theory/strings/rewrites.cpp
@@ -200,6 +200,7 @@ const char* toString(Rewrite r)
case Rewrite::LEN_REPL_INV: return "LEN_REPL_INV";
case Rewrite::LEN_CONV_INV: return "LEN_CONV_INV";
case Rewrite::CHARAT_ELIM: return "CHARAT_ELIM";
+ case Rewrite::SEQ_UNIT_EVAL: return "SEQ_UNIT_EVAL";
default: return "?";
}
}
diff --git a/src/theory/strings/rewrites.h b/src/theory/strings/rewrites.h
index 7a315ebd3..96a3b65fd 100644
--- a/src/theory/strings/rewrites.h
+++ b/src/theory/strings/rewrites.h
@@ -202,7 +202,8 @@ enum class Rewrite : uint32_t
LEN_CONCAT,
LEN_REPL_INV,
LEN_CONV_INV,
- CHARAT_ELIM
+ CHARAT_ELIM,
+ SEQ_UNIT_EVAL
};
/**
diff --git a/src/theory/strings/sequences_rewriter.cpp b/src/theory/strings/sequences_rewriter.cpp
index 2d2ec0af0..4f74d7c15 100644
--- a/src/theory/strings/sequences_rewriter.cpp
+++ b/src/theory/strings/sequences_rewriter.cpp
@@ -264,7 +264,7 @@ Node SequencesRewriter::rewriteStrEqualityExt(Node node)
// Add a constant string to the side with more `cn`s to restore
// the difference in number of `cn`s
std::vector<Node> vec(diff, cn);
- trimmed[j].push_back(Word::mkWord(vec));
+ trimmed[j].push_back(Word::mkWordFlatten(vec));
}
}
@@ -602,7 +602,7 @@ Node SequencesRewriter::rewriteConcat(Node node)
std::vector<Node> wvec;
wvec.push_back(preNode);
wvec.push_back(tmpNode[0]);
- preNode = Word::mkWord(wvec);
+ preNode = Word::mkWordFlatten(wvec);
node_vec.push_back(preNode);
}
else
@@ -644,7 +644,7 @@ Node SequencesRewriter::rewriteConcat(Node node)
std::vector<Node> vec;
vec.push_back(preNode);
vec.push_back(tmpNode);
- preNode = Word::mkWord(vec);
+ preNode = Word::mkWordFlatten(vec);
}
}
}
@@ -1461,6 +1461,10 @@ RewriteResponse SequencesRewriter::postRewrite(TNode node)
{
retNode = rewriteRepeatRegExp(node);
}
+ else if (nk == SEQ_UNIT)
+ {
+ retNode = rewriteSeqUnit(node);
+ }
Trace("sequences-postrewrite")
<< "Strings::SequencesRewriter::postRewrite returning " << retNode
@@ -3095,6 +3099,19 @@ Node SequencesRewriter::canonicalStrForSymbolicLength(Node len, TypeNode stype)
return res;
}
+Node SequencesRewriter::rewriteSeqUnit(Node node)
+{
+ NodeManager* nm = NodeManager::currentNM();
+ if (node[0].isConst())
+ {
+ std::vector<Expr> seq;
+ seq.push_back(node[0].toExpr());
+ TypeNode stype = nm->mkSequenceType(node[0].getType());
+ Node ret = nm->mkConst(ExprSequence(stype.toType(), seq));
+ return returnRewrite(node, ret, Rewrite::SEQ_UNIT_EVAL);
+ }
+ return node;
+}
Node SequencesRewriter::returnRewrite(Node node, Node ret, Rewrite r)
{
diff --git a/src/theory/strings/sequences_rewriter.h b/src/theory/strings/sequences_rewriter.h
index 56b74f536..490dd8b3c 100644
--- a/src/theory/strings/sequences_rewriter.h
+++ b/src/theory/strings/sequences_rewriter.h
@@ -224,6 +224,12 @@ class SequencesRewriter : public TheoryRewriter
* Returns the rewritten form of node.
*/
Node rewriteStringToCode(Node node);
+ /** rewrite seq.unit
+ * This is the entry point for post-rewriting terms n of the form
+ * seq.unit( t )
+ * Returns the rewritten form of node.
+ */
+ Node rewriteSeqUnit(Node node);
/** length preserving rewrite
*
diff --git a/src/theory/strings/term_registry.cpp b/src/theory/strings/term_registry.cpp
index ec034b0c9..6330d7c10 100644
--- a/src/theory/strings/term_registry.cpp
+++ b/src/theory/strings/term_registry.cpp
@@ -374,6 +374,13 @@ Node TermRegistry::getRegisterTermAtomicLemma(Node n,
LengthStatus s,
std::map<Node, bool>& reqPhase)
{
+ if (n.isConst())
+ {
+ // No need to send length for constant terms. This case may be triggered
+ // for cases where the skolem cache automatically replaces a skolem by
+ // a constant.
+ return Node::null();
+ }
Assert(n.getType().isStringLike());
NodeManager* nm = NodeManager::currentNM();
Node n_len = nm->mkNode(kind::STRING_LENGTH, n);
@@ -433,14 +440,6 @@ Node TermRegistry::getRegisterTermAtomicLemma(Node n,
Assert(false);
}
- // additionally add len( x ) >= 0 ?
- if (options::stringLenGeqZ())
- {
- Node n_len_geq = nm->mkNode(kind::GEQ, n_len, d_zero);
- n_len_geq = Rewriter::rewrite(n_len_geq);
- lems.push_back(n_len_geq);
- }
-
if (lems.empty())
{
return Node::null();
diff --git a/src/theory/strings/theory_strings_preprocess.cpp b/src/theory/strings/theory_strings_preprocess.cpp
index 939146a3d..50c6ede62 100644
--- a/src/theory/strings/theory_strings_preprocess.cpp
+++ b/src/theory/strings/theory_strings_preprocess.cpp
@@ -38,48 +38,45 @@ StringsPreprocess::StringsPreprocess(SkolemCache* sc,
SequencesStatistics& stats)
: d_sc(sc), d_statistics(stats)
{
- //Constants
- d_zero = NodeManager::currentNM()->mkConst(Rational(0));
- d_one = NodeManager::currentNM()->mkConst(Rational(1));
- d_neg_one = NodeManager::currentNM()->mkConst(Rational(-1));
}
StringsPreprocess::~StringsPreprocess(){
}
-Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
- unsigned prev_new_nodes = new_nodes.size();
- Trace("strings-preprocess-debug") << "StringsPreprocess::simplify: " << t << std::endl;
+Node StringsPreprocess::reduce(Node t,
+ std::vector<Node>& asserts,
+ SkolemCache* sc)
+{
+ Trace("strings-preprocess-debug")
+ << "StringsPreprocess::reduce: " << t << std::endl;
Node retNode = t;
- NodeManager *nm = NodeManager::currentNM();
+ NodeManager* nm = NodeManager::currentNM();
+ Node zero = nm->mkConst(Rational(0));
+ Node one = nm->mkConst(Rational(1));
+ Node negOne = nm->mkConst(Rational(-1));
if( t.getKind() == kind::STRING_SUBSTR ) {
// processing term: substr( s, n, m )
Node s = t[0];
Node n = t[1];
Node m = t[2];
- Node skt = d_sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "sst");
+ Node skt = sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "sst");
Node t12 = nm->mkNode(PLUS, n, m);
t12 = Rewriter::rewrite(t12);
Node lt0 = nm->mkNode(STRING_LENGTH, s);
//start point is greater than or equal zero
- Node c1 = nm->mkNode(GEQ, n, d_zero);
+ Node c1 = nm->mkNode(GEQ, n, zero);
//start point is less than end of string
Node c2 = nm->mkNode(GT, lt0, n);
//length is positive
- Node c3 = nm->mkNode(GT, m, d_zero);
+ Node c3 = nm->mkNode(GT, m, zero);
Node cond = nm->mkNode(AND, c1, c2, c3);
Node emp = Word::mkEmptyWord(t.getType());
- Node sk1 = n == d_zero ? emp
- : d_sc->mkSkolemCached(
- s, n, SkolemCache::SK_PREFIX, "sspre");
- Node sk2 = ArithEntail::check(t12, lt0)
- ? emp
- : d_sc->mkSkolemCached(
- s, t12, SkolemCache::SK_SUFFIX_REM, "sssufr");
+ Node sk1 = sc->mkSkolemCached(s, n, SkolemCache::SK_PREFIX, "sspre");
+ Node sk2 = sc->mkSkolemCached(s, t12, SkolemCache::SK_SUFFIX_REM, "sssufr");
Node b11 = s.eqNode(nm->mkNode(STRING_CONCAT, sk1, skt, sk2));
//length of first skolem is second argument
Node b12 = nm->mkNode(STRING_LENGTH, sk1).eqNode(n);
@@ -89,7 +86,7 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
Node b13 = nm->mkNode(
OR,
nm->mkNode(EQUAL, lsk2, nm->mkNode(MINUS, lt0, nm->mkNode(PLUS, n, m))),
- nm->mkNode(EQUAL, lsk2, d_zero));
+ nm->mkNode(EQUAL, lsk2, zero));
// Length of the result is at most m
Node b14 = nm->mkNode(LEQ, nm->mkNode(STRING_LENGTH, skt), m);
@@ -112,7 +109,7 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
// satisfied. If n + m is less than the length of s, then len(sk2) = 0
// cannot be satisfied because we have the constraint that len(skt) <= m,
// so sk2 must be greater than 0.
- new_nodes.push_back( lemma );
+ asserts.push_back(lemma);
// Thus, substr( s, n, m ) = skt
retNode = skt;
@@ -123,15 +120,16 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
Node x = t[0];
Node y = t[1];
Node n = t[2];
- Node skk = nm->mkSkolem("iok", nm->integerType(), "created for indexof");
+ Node skk = sc->mkTypedSkolemCached(
+ nm->integerType(), t, SkolemCache::SK_PURIFY, "iok");
Node negone = nm->mkConst(Rational(-1));
Node krange = nm->mkNode(GEQ, skk, negone);
// assert: indexof( x, y, n ) >= -1
- new_nodes.push_back( krange );
+ asserts.push_back(krange);
krange = nm->mkNode(GEQ, nm->mkNode(STRING_LENGTH, x), skk);
// assert: len( x ) >= indexof( x, y, z )
- new_nodes.push_back( krange );
+ asserts.push_back(krange);
// substr( x, n, len( x ) - n )
Node st = nm->mkNode(STRING_SUBSTR,
@@ -139,16 +137,16 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
n,
nm->mkNode(MINUS, nm->mkNode(STRING_LENGTH, x), n));
Node io2 =
- d_sc->mkSkolemCached(st, y, SkolemCache::SK_FIRST_CTN_PRE, "iopre");
+ sc->mkSkolemCached(st, y, SkolemCache::SK_FIRST_CTN_PRE, "iopre");
Node io4 =
- d_sc->mkSkolemCached(st, y, SkolemCache::SK_FIRST_CTN_POST, "iopost");
+ sc->mkSkolemCached(st, y, SkolemCache::SK_FIRST_CTN_POST, "iopost");
// ~contains( substr( x, n, len( x ) - n ), y )
Node c11 = nm->mkNode(STRING_STRCTN, st, y).negate();
// n > len( x )
Node c12 = nm->mkNode(GT, n, nm->mkNode(STRING_LENGTH, x));
// 0 > n
- Node c13 = nm->mkNode(GT, d_zero, n);
+ Node c13 = nm->mkNode(GT, zero, n);
Node cond1 = nm->mkNode(OR, c11, c12, c13);
// skk = -1
Node cc1 = skk.eqNode(negone);
@@ -171,8 +169,8 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
nm->mkNode(
STRING_SUBSTR,
y,
- d_zero,
- nm->mkNode(MINUS, nm->mkNode(STRING_LENGTH, y), d_one))),
+ zero,
+ nm->mkNode(MINUS, nm->mkNode(STRING_LENGTH, y), one))),
y)
.negate();
// skk = n + len( io2 )
@@ -189,7 +187,7 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
// skk = n + len( io2 )
// for fresh io2, io4.
Node rr = nm->mkNode(ITE, cond1, cc1, nm->mkNode(ITE, cond2, cc2, cc3));
- new_nodes.push_back( rr );
+ asserts.push_back(rr);
// Thus, indexof( x, y, n ) = skk.
retNode = skk;
@@ -198,7 +196,7 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
{
// processing term: int.to.str( n )
Node n = t[0];
- Node itost = d_sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "itost");
+ Node itost = sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "itost");
Node leni = nm->mkNode(STRING_LENGTH, itost);
std::vector<Node> conc;
@@ -206,21 +204,20 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
argTypes.push_back(nm->integerType());
Node u = nm->mkSkolem("U", nm->mkFunctionType(argTypes, nm->integerType()));
- Node lem = nm->mkNode(GEQ, leni, d_one);
+ Node lem = nm->mkNode(GEQ, leni, 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));
+ lem = zero.eqNode(nm->mkNode(APPLY_UF, u, zero));
conc.push_back(lem);
- Node x = nm->mkBoundVar(nm->integerType());
- Node xPlusOne = nm->mkNode(PLUS, x, d_one);
+ Node x = SkolemCache::mkIndexVar(t);
+ Node xPlusOne = nm->mkNode(PLUS, x, 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 sx = nm->mkNode(STRING_SUBSTR, itost, x, d_one);
+ Node g = nm->mkNode(AND, nm->mkNode(GEQ, x, zero), nm->mkNode(LT, x, leni));
+ Node sx = nm->mkNode(STRING_SUBSTR, itost, x, one);
Node ux = nm->mkNode(APPLY_UF, u, x);
Node ux1 = nm->mkNode(APPLY_UF, u, xPlusOne);
Node c0 = nm->mkNode(STRING_TO_CODE, nm->mkConst(String("0")));
@@ -229,10 +226,10 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
Node ten = nm->mkConst(Rational(10));
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));
+ nm->mkNode(AND, x.eqNode(zero), nm->mkNode(GT, leni, one));
Node cb = nm->mkNode(
AND,
- nm->mkNode(GEQ, c, nm->mkNode(ITE, leadingZeroPos, d_one, d_zero)),
+ nm->mkNode(GEQ, c, nm->mkNode(ITE, leadingZeroPos, one, zero)),
nm->mkNode(LT, c, ten));
Node ux1lem = nm->mkNode(GEQ, n, ux1);
@@ -241,11 +238,11 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
lem = nm->mkNode(FORALL, xbv, lem);
conc.push_back(lem);
- Node nonneg = nm->mkNode(GEQ, n, d_zero);
+ Node nonneg = nm->mkNode(GEQ, n, zero);
Node emp = Word::mkEmptyWord(t.getType());
lem = nm->mkNode(ITE, nonneg, nm->mkNode(AND, conc), itost.eqNode(emp));
- new_nodes.push_back(lem);
+ asserts.push_back(lem);
// assert:
// IF n>=0
// THEN:
@@ -274,26 +271,27 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
retNode = itost;
} else if( t.getKind() == kind::STRING_STOI ) {
Node s = t[0];
- Node stoit = nm->mkSkolem("stoit", nm->integerType(), "created for stoi");
+ Node stoit = sc->mkTypedSkolemCached(
+ nm->integerType(), t, SkolemCache::SK_PURIFY, "stoit");
Node lens = nm->mkNode(STRING_LENGTH, s);
std::vector<Node> conc1;
- Node lem = stoit.eqNode(d_neg_one);
+ Node lem = stoit.eqNode(negOne);
conc1.push_back(lem);
Node emp = Word::mkEmptyWord(s.getType());
Node sEmpty = s.eqNode(emp);
Node k = nm->mkSkolem("k", nm->integerType());
- Node kc1 = nm->mkNode(GEQ, k, d_zero);
+ Node kc1 = nm->mkNode(GEQ, k, zero);
Node kc2 = nm->mkNode(LT, k, lens);
Node c0 = nm->mkNode(STRING_TO_CODE, nm->mkConst(String("0")));
Node codeSk = nm->mkNode(
MINUS,
- nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, s, k, d_one)),
+ nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, s, k, one)),
c0);
Node ten = nm->mkConst(Rational(10));
Node kc3 = nm->mkNode(
- OR, nm->mkNode(LT, codeSk, d_zero), nm->mkNode(GEQ, codeSk, ten));
+ OR, nm->mkNode(LT, codeSk, zero), nm->mkNode(GEQ, codeSk, ten));
conc1.push_back(nm->mkNode(OR, sEmpty, nm->mkNode(AND, kc1, kc2, kc3)));
std::vector<Node> conc2;
@@ -304,24 +302,22 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
lem = stoit.eqNode(nm->mkNode(APPLY_UF, u, lens));
conc2.push_back(lem);
- lem = d_zero.eqNode(nm->mkNode(APPLY_UF, u, d_zero));
+ lem = zero.eqNode(nm->mkNode(APPLY_UF, u, zero));
conc2.push_back(lem);
- lem = nm->mkNode(GT, lens, d_zero);
+ lem = nm->mkNode(GT, lens, zero);
conc2.push_back(lem);
- Node x = nm->mkBoundVar(nm->integerType());
+ Node x = SkolemCache::mkIndexVar(t);
Node xbv = nm->mkNode(BOUND_VAR_LIST, x);
- Node g =
- nm->mkNode(AND, nm->mkNode(GEQ, x, d_zero), nm->mkNode(LT, x, lens));
- Node sx = nm->mkNode(STRING_SUBSTR, s, x, d_one);
+ Node g = nm->mkNode(AND, nm->mkNode(GEQ, x, zero), nm->mkNode(LT, x, lens));
+ Node sx = nm->mkNode(STRING_SUBSTR, s, x, one);
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, nm->mkNode(PLUS, x, one));
Node c = nm->mkNode(MINUS, nm->mkNode(STRING_TO_CODE, sx), c0);
Node eq = ux1.eqNode(nm->mkNode(PLUS, c, nm->mkNode(MULT, ten, ux)));
- Node cb =
- nm->mkNode(AND, nm->mkNode(GEQ, c, d_zero), nm->mkNode(LT, c, ten));
+ Node cb = nm->mkNode(AND, nm->mkNode(GEQ, c, zero), nm->mkNode(LT, c, ten));
Node ux1lem = nm->mkNode(GEQ, stoit, ux1);
@@ -329,9 +325,9 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
lem = nm->mkNode(FORALL, xbv, lem);
conc2.push_back(lem);
- Node sneg = nm->mkNode(LT, stoit, d_zero);
+ Node sneg = nm->mkNode(LT, stoit, zero);
lem = nm->mkNode(ITE, sneg, nm->mkNode(AND, conc1), nm->mkNode(AND, conc2));
- new_nodes.push_back(lem);
+ asserts.push_back(lem);
// assert:
// IF stoit < 0
@@ -362,10 +358,10 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
Node z = t[2];
TypeNode tn = t[0].getType();
Node rp1 =
- d_sc->mkSkolemCached(x, y, SkolemCache::SK_FIRST_CTN_PRE, "rfcpre");
+ sc->mkSkolemCached(x, y, SkolemCache::SK_FIRST_CTN_PRE, "rfcpre");
Node rp2 =
- d_sc->mkSkolemCached(x, y, SkolemCache::SK_FIRST_CTN_POST, "rfcpost");
- Node rpw = d_sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "rpw");
+ sc->mkSkolemCached(x, y, SkolemCache::SK_FIRST_CTN_POST, "rfcpost");
+ Node rpw = sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "rpw");
// y = ""
Node emp = Word::mkEmptyWord(tn);
@@ -387,10 +383,10 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
rp1,
nm->mkNode(kind::STRING_SUBSTR,
y,
- d_zero,
+ zero,
nm->mkNode(kind::MINUS,
nm->mkNode(kind::STRING_LENGTH, y),
- d_one))),
+ one))),
y)
.negate();
@@ -410,7 +406,7 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
cond2,
nm->mkNode(kind::AND, c21, c22, c23),
rpw.eqNode(x)));
- new_nodes.push_back( rr );
+ asserts.push_back(rr);
// Thus, replace( x, y, z ) = rpw.
retNode = rpw;
@@ -421,16 +417,16 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
Node x = t[0];
Node y = t[1];
Node z = t[2];
- Node rpaw = d_sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "rpaw");
+ Node rpaw = sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "rpaw");
- Node numOcc = d_sc->mkTypedSkolemCached(
+ Node numOcc = sc->mkTypedSkolemCached(
nm->integerType(), x, y, SkolemCache::SK_NUM_OCCUR, "numOcc");
std::vector<TypeNode> argTypes;
argTypes.push_back(nm->integerType());
Node us =
nm->mkSkolem("Us", nm->mkFunctionType(argTypes, nm->stringType()));
TypeNode ufType = nm->mkFunctionType(argTypes, nm->integerType());
- Node uf = d_sc->mkTypedSkolemCached(
+ Node uf = sc->mkTypedSkolemCached(
ufType, x, y, SkolemCache::SK_OCCUR_INDEX, "Uf");
Node ufno = nm->mkNode(APPLY_UF, uf, numOcc);
@@ -438,27 +434,27 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
Node rem = nm->mkNode(STRING_SUBSTR, x, ufno, nm->mkNode(STRING_LENGTH, x));
std::vector<Node> lem;
- lem.push_back(nm->mkNode(GEQ, numOcc, d_zero));
- lem.push_back(rpaw.eqNode(nm->mkNode(APPLY_UF, us, d_zero)));
+ lem.push_back(nm->mkNode(GEQ, numOcc, zero));
+ lem.push_back(rpaw.eqNode(nm->mkNode(APPLY_UF, us, zero)));
lem.push_back(usno.eqNode(rem));
- lem.push_back(nm->mkNode(APPLY_UF, uf, d_zero).eqNode(d_zero));
- lem.push_back(nm->mkNode(STRING_STRIDOF, x, y, ufno).eqNode(d_neg_one));
+ lem.push_back(nm->mkNode(APPLY_UF, uf, zero).eqNode(zero));
+ lem.push_back(nm->mkNode(STRING_STRIDOF, x, y, ufno).eqNode(negOne));
- Node i = nm->mkBoundVar(nm->integerType());
+ Node i = SkolemCache::mkIndexVar(t);
Node bvli = nm->mkNode(BOUND_VAR_LIST, i);
Node bound =
- nm->mkNode(AND, nm->mkNode(GEQ, i, d_zero), nm->mkNode(LT, i, numOcc));
+ nm->mkNode(AND, nm->mkNode(GEQ, i, zero), nm->mkNode(LT, i, numOcc));
Node ufi = nm->mkNode(APPLY_UF, uf, i);
- Node ufip1 = nm->mkNode(APPLY_UF, uf, nm->mkNode(PLUS, i, d_one));
+ Node ufip1 = nm->mkNode(APPLY_UF, uf, nm->mkNode(PLUS, i, one));
Node ii = nm->mkNode(STRING_STRIDOF, x, y, ufi);
Node cc = nm->mkNode(
STRING_CONCAT,
nm->mkNode(STRING_SUBSTR, x, ufi, nm->mkNode(MINUS, ii, ufi)),
z,
- nm->mkNode(APPLY_UF, us, nm->mkNode(PLUS, i, d_one)));
+ nm->mkNode(APPLY_UF, us, nm->mkNode(PLUS, i, one)));
std::vector<Node> flem;
- flem.push_back(ii.eqNode(d_neg_one).negate());
+ flem.push_back(ii.eqNode(negOne).negate());
flem.push_back(nm->mkNode(APPLY_UF, us, i).eqNode(cc));
flem.push_back(
ufip1.eqNode(nm->mkNode(PLUS, ii, nm->mkNode(STRING_LENGTH, y))));
@@ -487,7 +483,7 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
Node emp = Word::mkEmptyWord(t.getType());
Node assert =
nm->mkNode(ITE, y.eqNode(emp), rpaw.eqNode(x), nm->mkNode(AND, lem));
- new_nodes.push_back(assert);
+ asserts.push_back(assert);
// Thus, replaceall( x, y, z ) = rpaw
retNode = rpaw;
@@ -495,19 +491,17 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
else if (t.getKind() == STRING_TOLOWER || t.getKind() == STRING_TOUPPER)
{
Node x = t[0];
- Node r = d_sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "r");
+ Node r = sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "r");
Node lenx = nm->mkNode(STRING_LENGTH, x);
Node lenr = nm->mkNode(STRING_LENGTH, r);
Node eqLenA = lenx.eqNode(lenr);
- Node i = nm->mkBoundVar(nm->integerType());
+ Node i = SkolemCache::mkIndexVar(t);
Node bvi = nm->mkNode(BOUND_VAR_LIST, i);
- Node ci =
- nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, x, i, d_one));
- Node ri =
- nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, r, i, d_one));
+ Node ci = nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, x, i, one));
+ Node ri = nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, r, i, one));
Node lb = nm->mkConst(Rational(t.getKind() == STRING_TOUPPER ? 97 : 65));
Node ub = nm->mkConst(Rational(t.getKind() == STRING_TOUPPER ? 122 : 90));
@@ -521,7 +515,7 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
ci);
Node bound =
- nm->mkNode(AND, nm->mkNode(LEQ, d_zero, i), nm->mkNode(LT, i, lenr));
+ nm->mkNode(AND, nm->mkNode(LEQ, zero, i), nm->mkNode(LT, i, lenr));
Node rangeA =
nm->mkNode(FORALL, bvi, nm->mkNode(OR, bound.negate(), ri.eqNode(res)));
@@ -533,7 +527,7 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
// str.code( str.substr(r,i,1) ) = ite( 97 <= ci <= 122, ci-32, ci)
// where ci = str.code( str.substr(x,i,1) )
Node assert = nm->mkNode(AND, eqLenA, rangeA);
- new_nodes.push_back(assert);
+ asserts.push_back(assert);
// Thus, toLower( x ) = r
retNode = r;
@@ -541,22 +535,22 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
else if (t.getKind() == STRING_REV)
{
Node x = t[0];
- Node r = d_sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "r");
+ Node r = sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "r");
Node lenx = nm->mkNode(STRING_LENGTH, x);
Node lenr = nm->mkNode(STRING_LENGTH, r);
Node eqLenA = lenx.eqNode(lenr);
- Node i = nm->mkBoundVar(nm->integerType());
+ Node i = SkolemCache::mkIndexVar(t);
Node bvi = nm->mkNode(BOUND_VAR_LIST, i);
Node revi = nm->mkNode(
- MINUS, nm->mkNode(STRING_LENGTH, x), nm->mkNode(PLUS, i, d_one));
- Node ssr = nm->mkNode(STRING_SUBSTR, r, i, d_one);
- Node ssx = nm->mkNode(STRING_SUBSTR, x, revi, d_one);
+ MINUS, nm->mkNode(STRING_LENGTH, x), nm->mkNode(PLUS, i, one));
+ Node ssr = nm->mkNode(STRING_SUBSTR, r, i, one);
+ Node ssx = nm->mkNode(STRING_SUBSTR, x, revi, one);
Node bound =
- nm->mkNode(AND, nm->mkNode(LEQ, d_zero, i), nm->mkNode(LT, i, lenr));
+ nm->mkNode(AND, nm->mkNode(LEQ, zero, i), nm->mkNode(LT, i, lenr));
Node rangeA = nm->mkNode(
FORALL, bvi, nm->mkNode(OR, bound.negate(), ssr.eqNode(ssx)));
// assert:
@@ -564,7 +558,7 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
// forall i. 0 <= i < len(r) =>
// substr(r,i,1) = substr(x,len(x)-(i+1),1)
Node assert = nm->mkNode(AND, eqLenA, rangeA);
- new_nodes.push_back(assert);
+ asserts.push_back(assert);
// Thus, (str.rev x) = r
retNode = r;
@@ -576,31 +570,38 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
//negative contains reduces to existential
Node lenx = NodeManager::currentNM()->mkNode(kind::STRING_LENGTH, x);
Node lens = NodeManager::currentNM()->mkNode(kind::STRING_LENGTH, s);
- Node b1 = NodeManager::currentNM()->mkBoundVar(NodeManager::currentNM()->integerType());
+ Node b1 = SkolemCache::mkIndexVar(t);
Node b1v = NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, b1);
- Node body = NodeManager::currentNM()->mkNode( kind::AND,
- NodeManager::currentNM()->mkNode( kind::LEQ, d_zero, b1 ),
- NodeManager::currentNM()->mkNode( kind::LEQ, b1, NodeManager::currentNM()->mkNode( kind::MINUS, lenx, lens ) ),
- NodeManager::currentNM()->mkNode( kind::EQUAL, NodeManager::currentNM()->mkNode(kind::STRING_SUBSTR, x, b1, lens), s )
- );
+ Node body = NodeManager::currentNM()->mkNode(
+ kind::AND,
+ NodeManager::currentNM()->mkNode(kind::LEQ, zero, b1),
+ NodeManager::currentNM()->mkNode(
+ kind::LEQ,
+ b1,
+ NodeManager::currentNM()->mkNode(kind::MINUS, lenx, lens)),
+ NodeManager::currentNM()->mkNode(
+ kind::EQUAL,
+ NodeManager::currentNM()->mkNode(kind::STRING_SUBSTR, x, b1, lens),
+ s));
retNode = NodeManager::currentNM()->mkNode( kind::EXISTS, b1v, body );
}
else if (t.getKind() == kind::STRING_LEQ)
{
- Node ltp = nm->mkSkolem("ltp", nm->booleanType());
+ Node ltp = sc->mkTypedSkolemCached(
+ nm->booleanType(), t, SkolemCache::SK_PURIFY, "ltp");
Node k = nm->mkSkolem("k", nm->integerType());
std::vector<Node> conj;
- conj.push_back(nm->mkNode(GEQ, k, d_zero));
+ conj.push_back(nm->mkNode(GEQ, k, zero));
Node substr[2];
Node code[2];
for (unsigned r = 0; r < 2; r++)
{
Node ta = t[r];
Node tb = t[1 - r];
- substr[r] = nm->mkNode(STRING_SUBSTR, ta, d_zero, k);
+ substr[r] = nm->mkNode(STRING_SUBSTR, ta, zero, k);
code[r] =
- nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, ta, k, d_one));
+ nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, ta, k, one));
conj.push_back(nm->mkNode(LEQ, k, nm->mkNode(STRING_LENGTH, ta)));
}
conj.push_back(substr[0].eqNode(substr[1]));
@@ -632,18 +633,29 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
// ELSE: str.code(substr( x, k, 1 )) > str.code(substr( y, k, 1 ))
Node assert =
nm->mkNode(ITE, t[0].eqNode(t[1]), ltp, nm->mkNode(AND, conj));
- new_nodes.push_back(assert);
+ asserts.push_back(assert);
// Thus, str.<=( x, y ) = ltp
retNode = ltp;
}
+ return retNode;
+}
+Node StringsPreprocess::simplify(Node t, std::vector<Node>& asserts)
+{
+ size_t prev_asserts = asserts.size();
+ // call the static reduce routine
+ Node retNode = reduce(t, asserts, d_sc);
if( t!=retNode ){
Trace("strings-preprocess") << "StringsPreprocess::simplify: " << t << " -> " << retNode << std::endl;
- if(!new_nodes.empty()) {
- Trace("strings-preprocess") << " ... new nodes (" << (new_nodes.size()-prev_new_nodes) << "):" << std::endl;
- for(unsigned int i=prev_new_nodes; i<new_nodes.size(); ++i) {
- Trace("strings-preprocess") << " " << new_nodes[i] << std::endl;
+ if (!asserts.empty())
+ {
+ Trace("strings-preprocess")
+ << " ... new nodes (" << (asserts.size() - prev_asserts)
+ << "):" << std::endl;
+ for (size_t i = prev_asserts; i < asserts.size(); ++i)
+ {
+ Trace("strings-preprocess") << " " << asserts[i] << std::endl;
}
}
d_statistics.d_reductions << t.getKind();
@@ -656,14 +668,17 @@ Node StringsPreprocess::simplify( Node t, std::vector< Node > &new_nodes ) {
return retNode;
}
-Node StringsPreprocess::simplifyRec( Node t, std::vector< Node > & new_nodes, std::map< Node, Node >& visited ){
+Node StringsPreprocess::simplifyRec(Node t,
+ std::vector<Node>& asserts,
+ std::map<Node, Node>& visited)
+{
std::map< Node, Node >::iterator it = visited.find(t);
if( it!=visited.end() ){
return it->second;
}else{
Node retNode = t;
if( t.getNumChildren()==0 ){
- retNode = simplify( t, new_nodes );
+ retNode = simplify(t, asserts);
}else if( t.getKind()!=kind::FORALL ){
bool changed = false;
std::vector< Node > cc;
@@ -671,7 +686,7 @@ Node StringsPreprocess::simplifyRec( Node t, std::vector< Node > & new_nodes, st
cc.push_back( t.getOperator() );
}
for(unsigned i=0; i<t.getNumChildren(); i++) {
- Node s = simplifyRec( t[i], new_nodes, visited );
+ Node s = simplifyRec(t[i], asserts, visited);
cc.push_back( s );
if( s!=t[i] ) {
changed = true;
@@ -681,24 +696,27 @@ Node StringsPreprocess::simplifyRec( Node t, std::vector< Node > & new_nodes, st
if( changed ){
tmp = NodeManager::currentNM()->mkNode( t.getKind(), cc );
}
- retNode = simplify( tmp, new_nodes );
+ retNode = simplify(tmp, asserts);
}
visited[t] = retNode;
return retNode;
}
}
-Node StringsPreprocess::processAssertion( Node n, std::vector< Node > &new_nodes ) {
+Node StringsPreprocess::processAssertion(Node n, std::vector<Node>& asserts)
+{
std::map< Node, Node > visited;
- std::vector< Node > new_nodes_curr;
- Node ret = simplifyRec( n, new_nodes_curr, visited );
- while( !new_nodes_curr.empty() ){
- Node curr = new_nodes_curr.back();
- new_nodes_curr.pop_back();
- std::vector< Node > new_nodes_tmp;
- curr = simplifyRec( curr, new_nodes_tmp, visited );
- new_nodes_curr.insert( new_nodes_curr.end(), new_nodes_tmp.begin(), new_nodes_tmp.end() );
- new_nodes.push_back( curr );
+ std::vector<Node> asserts_curr;
+ Node ret = simplifyRec(n, asserts_curr, visited);
+ while (!asserts_curr.empty())
+ {
+ Node curr = asserts_curr.back();
+ asserts_curr.pop_back();
+ std::vector<Node> asserts_tmp;
+ curr = simplifyRec(curr, asserts_tmp, visited);
+ asserts_curr.insert(
+ asserts_curr.end(), asserts_tmp.begin(), asserts_tmp.end());
+ asserts.push_back(curr);
}
return ret;
}
@@ -708,18 +726,22 @@ void StringsPreprocess::processAssertions( std::vector< Node > &vec_node ){
for( unsigned i=0; i<vec_node.size(); i++ ){
Trace("strings-preprocess-debug") << "Preprocessing assertion " << vec_node[i] << std::endl;
//preprocess until fixed point
- std::vector< Node > new_nodes;
- std::vector< Node > new_nodes_curr;
- new_nodes_curr.push_back( vec_node[i] );
- while( !new_nodes_curr.empty() ){
- Node curr = new_nodes_curr.back();
- new_nodes_curr.pop_back();
- std::vector< Node > new_nodes_tmp;
- curr = simplifyRec( curr, new_nodes_tmp, visited );
- new_nodes_curr.insert( new_nodes_curr.end(), new_nodes_tmp.begin(), new_nodes_tmp.end() );
- new_nodes.push_back( curr );
+ std::vector<Node> asserts;
+ std::vector<Node> asserts_curr;
+ asserts_curr.push_back(vec_node[i]);
+ while (!asserts_curr.empty())
+ {
+ Node curr = asserts_curr.back();
+ asserts_curr.pop_back();
+ std::vector<Node> asserts_tmp;
+ curr = simplifyRec(curr, asserts_tmp, visited);
+ asserts_curr.insert(
+ asserts_curr.end(), asserts_tmp.begin(), asserts_tmp.end());
+ asserts.push_back(curr);
}
- Node res = new_nodes.size()==1 ? new_nodes[0] : NodeManager::currentNM()->mkNode( kind::AND, new_nodes );
+ Node res = asserts.size() == 1
+ ? asserts[0]
+ : NodeManager::currentNM()->mkNode(kind::AND, asserts);
if( res!=vec_node[i] ){
res = Rewriter::rewrite( res );
PROOF( ProofManager::currentPM()->addDependence( res, vec_node[i] ); );
diff --git a/src/theory/strings/theory_strings_preprocess.h b/src/theory/strings/theory_strings_preprocess.h
index fb6404aa6..1392b4ea1 100644
--- a/src/theory/strings/theory_strings_preprocess.h
+++ b/src/theory/strings/theory_strings_preprocess.h
@@ -44,21 +44,41 @@ class StringsPreprocess {
context::UserContext* u,
SequencesStatistics& stats);
~StringsPreprocess();
+ /** The reduce routine
+ *
+ * This is the main routine for constructing the reduction lemma for
+ * an extended function t. It returns the simplified form of t, as well
+ * as assertions for t, interpeted conjunctively. The reduction lemma
+ * for t is:
+ * asserts[0] ^ ... ^ asserts[n] ^ t = t'
+ * where t' is the term returned by this method.
+ * The argument sc defines the methods for generating new Skolem variables.
+ * The return value is t itself if it is not reduced by this class.
+ *
+ * The reduction lemma for t is a way of specifying the complete semantics
+ * of t. In other words, any model satisfying the reduction lemma of t
+ * correctly interprets t.
+ *
+ * @param t The node to reduce,
+ * @param asserts The vector for storing the assertions that correspond to
+ * the reduction of t,
+ * @param sc The skolem cache for generating new variables,
+ * @return The reduced form of t.
+ */
+ static Node reduce(Node t, std::vector<Node>& asserts, SkolemCache* sc);
/**
- * Returns a node t' such that
- * (exists k) new_nodes => t = t'
- * is valid, where k are the free skolems introduced when constructing
- * new_nodes.
+ * Calls the above method for the skolem cache owned by this class, and
+ * records statistics.
*/
- Node simplify(Node t, std::vector<Node>& new_nodes);
+ Node simplify(Node t, std::vector<Node>& asserts);
/**
* Applies simplifyRec on t until a fixed point is reached, and returns
* the resulting term t', which is such that
- * (exists k) new_nodes => t = t'
+ * (exists k) asserts => t = t'
* is valid, where k are the free skolems introduced when constructing
- * new_nodes.
+ * asserts.
*/
- Node processAssertion(Node t, std::vector<Node>& new_nodes);
+ Node processAssertion(Node t, std::vector<Node>& asserts);
/**
* Replaces all formulas t in vec_node with an equivalent formula t' that
* contains no free instances of extended functions (that is, extended
@@ -68,21 +88,17 @@ class StringsPreprocess {
void processAssertions(std::vector<Node>& vec_node);
private:
- /** commonly used constants */
- Node d_zero;
- Node d_one;
- Node d_neg_one;
/** pointer to the skolem cache used by this class */
SkolemCache* d_sc;
/** Reference to the statistics for the theory of strings/sequences. */
SequencesStatistics& d_statistics;
/**
* Applies simplify to all top-level extended function subterms of t. New
- * assertions created in this reduction are added to new_nodes. The argument
+ * assertions created in this reduction are added to asserts. The argument
* visited stores a cache of previous results.
*/
Node simplifyRec(Node t,
- std::vector<Node>& new_nodes,
+ std::vector<Node>& asserts,
std::map<Node, Node>& visited);
};
diff --git a/src/theory/strings/theory_strings_type_rules.h b/src/theory/strings/theory_strings_type_rules.h
index 93a32f26e..3229e6631 100644
--- a/src/theory/strings/theory_strings_type_rules.h
+++ b/src/theory/strings/theory_strings_type_rules.h
@@ -20,6 +20,9 @@
#ifndef CVC4__THEORY__STRINGS__THEORY_STRINGS_TYPE_RULES_H
#define CVC4__THEORY__STRINGS__THEORY_STRINGS_TYPE_RULES_H
+#include "expr/expr_sequence.h"
+#include "expr/sequence.h"
+
namespace CVC4 {
namespace theory {
namespace strings {
@@ -318,6 +321,53 @@ public:
}
};
+class ConstSequenceTypeRule
+{
+ public:
+ static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::CONST_SEQUENCE);
+ return n.getConst<ExprSequence>().getSequence().getType();
+ }
+};
+
+class SeqUnitTypeRule
+{
+ public:
+ static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ return nodeManager->mkSequenceType(n[0].getType(check));
+ }
+};
+
+/** Properties of the sequence type */
+struct SequenceProperties
+{
+ static Cardinality computeCardinality(TypeNode type)
+ {
+ Assert(type.getKind() == kind::SEQUENCE_TYPE);
+ return Cardinality::INTEGERS;
+ }
+ /** A sequence is well-founded if its element type is */
+ static bool isWellFounded(TypeNode type)
+ {
+ return type[0].isWellFounded();
+ }
+ /** Make ground term for sequence type (return the empty sequence) */
+ static Node mkGroundTerm(TypeNode type)
+ {
+ Assert(type.isSequence());
+ // empty sequence
+ std::vector<Expr> seq;
+ return NodeManager::currentNM()->mkConst(
+ ExprSequence(SequenceType(type.toType()), seq));
+ }
+}; /* struct SequenceProperties */
+
}/* CVC4::theory::strings namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/strings/type_enumerator.cpp b/src/theory/strings/type_enumerator.cpp
index d24206860..c25363e65 100644
--- a/src/theory/strings/type_enumerator.cpp
+++ b/src/theory/strings/type_enumerator.cpp
@@ -158,6 +158,67 @@ void StringEnumLen::mkCurr()
d_curr = makeStandardModelConstant(d_witer->getData(), d_cardinality);
}
+SeqEnumLen::SeqEnumLen(TypeNode tn,
+ TypeEnumeratorProperties* tep,
+ uint32_t startLength)
+ : SEnumLen(tn, startLength)
+{
+ d_elementEnumerator.reset(
+ new TypeEnumerator(d_type.getSequenceElementType(), tep));
+ mkCurr();
+}
+
+SeqEnumLen::SeqEnumLen(TypeNode tn,
+ TypeEnumeratorProperties* tep,
+ uint32_t startLength,
+ uint32_t endLength)
+ : SEnumLen(tn, startLength, endLength)
+{
+ d_elementEnumerator.reset(
+ new TypeEnumerator(d_type.getSequenceElementType(), tep));
+ mkCurr();
+}
+
+SeqEnumLen::SeqEnumLen(const SeqEnumLen& wenum)
+ : SEnumLen(wenum),
+ d_elementEnumerator(new TypeEnumerator(*wenum.d_elementEnumerator)),
+ d_elementDomain(wenum.d_elementDomain)
+{
+}
+
+bool SeqEnumLen::increment()
+{
+ if (!d_elementEnumerator->isFinished())
+ {
+ // yet to establish domain
+ Assert(d_elementEnumerator != nullptr);
+ d_elementDomain.push_back((**d_elementEnumerator).toExpr());
+ ++(*d_elementEnumerator);
+ }
+ // the current cardinality is the domain size of the element
+ if (!d_witer->increment(d_elementDomain.size()))
+ {
+ Assert(d_elementEnumerator->isFinished());
+ d_curr = Node::null();
+ return false;
+ }
+ mkCurr();
+ return true;
+}
+
+void SeqEnumLen::mkCurr()
+{
+ std::vector<Expr> seq;
+ const std::vector<unsigned>& data = d_witer->getData();
+ for (unsigned i : data)
+ {
+ seq.push_back(d_elementDomain[i]);
+ }
+ // make sequence from seq
+ d_curr =
+ NodeManager::currentNM()->mkConst(ExprSequence(d_type.toType(), seq));
+}
+
StringEnumerator::StringEnumerator(TypeNode type, TypeEnumeratorProperties* tep)
: TypeEnumeratorBase<StringEnumerator>(type),
d_wenum(0, utils::getAlphabetCardinality())
@@ -182,6 +243,28 @@ StringEnumerator& StringEnumerator::operator++()
bool StringEnumerator::isFinished() { return d_wenum.isFinished(); }
+SequenceEnumerator::SequenceEnumerator(TypeNode type,
+ TypeEnumeratorProperties* tep)
+ : TypeEnumeratorBase<SequenceEnumerator>(type), d_wenum(type, tep, 0)
+{
+}
+
+SequenceEnumerator::SequenceEnumerator(const SequenceEnumerator& enumerator)
+ : TypeEnumeratorBase<SequenceEnumerator>(enumerator.getType()),
+ d_wenum(enumerator.d_wenum)
+{
+}
+
+Node SequenceEnumerator::operator*() { return d_wenum.getCurrent(); }
+
+SequenceEnumerator& SequenceEnumerator::operator++()
+{
+ d_wenum.increment();
+ return *this;
+}
+
+bool SequenceEnumerator::isFinished() { return d_wenum.isFinished(); }
+
} // namespace strings
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/strings/type_enumerator.h b/src/theory/strings/type_enumerator.h
index b379ce5c3..c82892624 100644
--- a/src/theory/strings/type_enumerator.h
+++ b/src/theory/strings/type_enumerator.h
@@ -136,6 +136,34 @@ class StringEnumLen : public SEnumLen
void mkCurr();
};
+/**
+ * Enumerates sequence values for a given length.
+ */
+class SeqEnumLen : public SEnumLen
+{
+ public:
+ /** For sequences */
+ SeqEnumLen(TypeNode tn, TypeEnumeratorProperties* tep, uint32_t startLength);
+ SeqEnumLen(TypeNode tn,
+ TypeEnumeratorProperties* tep,
+ uint32_t startLength,
+ uint32_t endLength);
+ /** copy constructor */
+ SeqEnumLen(const SeqEnumLen& wenum);
+ /** destructor */
+ ~SeqEnumLen() {}
+ /** increment */
+ bool increment() override;
+
+ private:
+ /** an enumerator for the elements' type */
+ std::unique_ptr<TypeEnumerator> d_elementEnumerator;
+ /** The domain */
+ std::vector<Expr> d_elementDomain;
+ /** Make the current term from d_data */
+ void mkCurr();
+};
+
class StringEnumerator : public TypeEnumeratorBase<StringEnumerator>
{
public:
@@ -154,6 +182,21 @@ class StringEnumerator : public TypeEnumeratorBase<StringEnumerator>
StringEnumLen d_wenum;
}; /* class StringEnumerator */
+class SequenceEnumerator : public TypeEnumeratorBase<SequenceEnumerator>
+{
+ public:
+ SequenceEnumerator(TypeNode type, TypeEnumeratorProperties* tep = nullptr);
+ SequenceEnumerator(const SequenceEnumerator& enumerator);
+ ~SequenceEnumerator() {}
+ Node operator*() override;
+ SequenceEnumerator& operator++() override;
+ bool isFinished() override;
+
+ private:
+ /** underlying sequence enumerator */
+ SeqEnumLen d_wenum;
+}; /* class SequenceEnumerator */
+
}/* CVC4::theory::strings namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/strings/word.cpp b/src/theory/strings/word.cpp
index e9ab2652e..3f6a9de32 100644
--- a/src/theory/strings/word.cpp
+++ b/src/theory/strings/word.cpp
@@ -14,6 +14,7 @@
#include "theory/strings/word.h"
+#include "expr/sequence.h"
#include "util/string.h"
using namespace CVC4::kind;
@@ -28,23 +29,28 @@ Node Word::mkEmptyWord(TypeNode tn)
{
return mkEmptyWord(CONST_STRING);
}
+ else if (tn.isSequence())
+ {
+ std::vector<Expr> seq;
+ return NodeManager::currentNM()->mkConst(
+ ExprSequence(tn.getSequenceElementType().toType(), seq));
+ }
Unimplemented();
return Node::null();
}
Node Word::mkEmptyWord(Kind k)
{
- NodeManager* nm = NodeManager::currentNM();
if (k == CONST_STRING)
{
std::vector<unsigned> vec;
- return nm->mkConst(String(vec));
+ return NodeManager::currentNM()->mkConst(String(vec));
}
Unimplemented();
return Node::null();
}
-Node Word::mkWord(const std::vector<Node>& xs)
+Node Word::mkWordFlatten(const std::vector<Node>& xs)
{
Assert(!xs.empty());
NodeManager* nm = NodeManager::currentNM();
@@ -61,6 +67,22 @@ Node Word::mkWord(const std::vector<Node>& xs)
}
return nm->mkConst(String(vec));
}
+ else if (k == CONST_SEQUENCE)
+ {
+ std::vector<Expr> seq;
+ TypeNode tn = xs[0].getType();
+ for (TNode x : xs)
+ {
+ Assert(x.getType() == tn);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const std::vector<Node>& vecc = sx.getVec();
+ for (const Node& c : vecc)
+ {
+ seq.push_back(c.toExpr());
+ }
+ }
+ return NodeManager::currentNM()->mkConst(ExprSequence(tn.toType(), seq));
+ }
Unimplemented();
return Node::null();
}
@@ -72,6 +94,10 @@ size_t Word::getLength(TNode x)
{
return x.getConst<String>().size();
}
+ else if (k == CONST_SEQUENCE)
+ {
+ return x.getConst<ExprSequence>().getSequence().size();
+ }
Unimplemented();
return 0;
}
@@ -111,6 +137,13 @@ bool Word::strncmp(TNode x, TNode y, std::size_t n)
String sy = y.getConst<String>();
return sx.strncmp(sy, n);
}
+ else if (k == CONST_SEQUENCE)
+ {
+ Assert(y.getKind() == CONST_SEQUENCE);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const Sequence& sy = y.getConst<ExprSequence>().getSequence();
+ return sx.strncmp(sy, n);
+ }
Unimplemented();
return false;
}
@@ -125,6 +158,13 @@ bool Word::rstrncmp(TNode x, TNode y, std::size_t n)
String sy = y.getConst<String>();
return sx.rstrncmp(sy, n);
}
+ else if (k == CONST_SEQUENCE)
+ {
+ Assert(y.getKind() == CONST_SEQUENCE);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const Sequence& sy = y.getConst<ExprSequence>().getSequence();
+ return sx.rstrncmp(sy, n);
+ }
Unimplemented();
return false;
}
@@ -139,6 +179,13 @@ std::size_t Word::find(TNode x, TNode y, std::size_t start)
String sy = y.getConst<String>();
return sx.find(sy, start);
}
+ else if (k == CONST_SEQUENCE)
+ {
+ Assert(y.getKind() == CONST_SEQUENCE);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const Sequence& sy = y.getConst<ExprSequence>().getSequence();
+ return sx.find(sy, start);
+ }
Unimplemented();
return 0;
}
@@ -153,6 +200,13 @@ std::size_t Word::rfind(TNode x, TNode y, std::size_t start)
String sy = y.getConst<String>();
return sx.rfind(sy, start);
}
+ else if (k == CONST_SEQUENCE)
+ {
+ Assert(y.getKind() == CONST_SEQUENCE);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const Sequence& sy = y.getConst<ExprSequence>().getSequence();
+ return sx.rfind(sy, start);
+ }
Unimplemented();
return 0;
}
@@ -167,6 +221,13 @@ bool Word::hasPrefix(TNode x, TNode y)
String sy = y.getConst<String>();
return sx.hasPrefix(sy);
}
+ else if (k == CONST_SEQUENCE)
+ {
+ Assert(y.getKind() == CONST_SEQUENCE);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const Sequence& sy = y.getConst<ExprSequence>().getSequence();
+ return sx.hasPrefix(sy);
+ }
Unimplemented();
return false;
}
@@ -181,6 +242,13 @@ bool Word::hasSuffix(TNode x, TNode y)
String sy = y.getConst<String>();
return sx.hasSuffix(sy);
}
+ else if (k == CONST_SEQUENCE)
+ {
+ Assert(y.getKind() == CONST_SEQUENCE);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const Sequence& sy = y.getConst<ExprSequence>().getSequence();
+ return sx.hasSuffix(sy);
+ }
Unimplemented();
return false;
}
@@ -198,6 +266,16 @@ Node Word::replace(TNode x, TNode y, TNode t)
String st = t.getConst<String>();
return nm->mkConst(String(sx.replace(sy, st)));
}
+ else if (k == CONST_SEQUENCE)
+ {
+ Assert(y.getKind() == CONST_SEQUENCE);
+ Assert(t.getKind() == CONST_SEQUENCE);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const Sequence& sy = y.getConst<ExprSequence>().getSequence();
+ const Sequence& st = t.getConst<ExprSequence>().getSequence();
+ Sequence res = sx.replace(sy, st);
+ return nm->mkConst(res.toExprSequence());
+ }
Unimplemented();
return Node::null();
}
@@ -210,6 +288,12 @@ Node Word::substr(TNode x, std::size_t i)
String sx = x.getConst<String>();
return nm->mkConst(String(sx.substr(i)));
}
+ else if (k == CONST_SEQUENCE)
+ {
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ Sequence res = sx.substr(i);
+ return nm->mkConst(res.toExprSequence());
+ }
Unimplemented();
return Node::null();
}
@@ -222,6 +306,12 @@ Node Word::substr(TNode x, std::size_t i, std::size_t j)
String sx = x.getConst<String>();
return nm->mkConst(String(sx.substr(i, j)));
}
+ else if (k == CONST_SEQUENCE)
+ {
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ Sequence res = sx.substr(i, j);
+ return nm->mkConst(res.toExprSequence());
+ }
Unimplemented();
return Node::null();
}
@@ -237,6 +327,12 @@ Node Word::suffix(TNode x, std::size_t i)
String sx = x.getConst<String>();
return nm->mkConst(String(sx.suffix(i)));
}
+ else if (k == CONST_SEQUENCE)
+ {
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ Sequence res = sx.suffix(i);
+ return nm->mkConst(res.toExprSequence());
+ }
Unimplemented();
return Node::null();
}
@@ -251,6 +347,13 @@ bool Word::noOverlapWith(TNode x, TNode y)
String sy = y.getConst<String>();
return sx.noOverlapWith(sy);
}
+ else if (k == CONST_SEQUENCE)
+ {
+ Assert(y.getKind() == CONST_SEQUENCE);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const Sequence& sy = y.getConst<ExprSequence>().getSequence();
+ return sx.noOverlapWith(sy);
+ }
Unimplemented();
return false;
}
@@ -265,6 +368,13 @@ std::size_t Word::overlap(TNode x, TNode y)
String sy = y.getConst<String>();
return sx.overlap(sy);
}
+ else if (k == CONST_SEQUENCE)
+ {
+ Assert(y.getKind() == CONST_SEQUENCE);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const Sequence& sy = y.getConst<ExprSequence>().getSequence();
+ return sx.overlap(sy);
+ }
Unimplemented();
return 0;
}
@@ -279,10 +389,32 @@ std::size_t Word::roverlap(TNode x, TNode y)
String sy = y.getConst<String>();
return sx.roverlap(sy);
}
+ else if (k == CONST_SEQUENCE)
+ {
+ Assert(y.getKind() == CONST_SEQUENCE);
+ const Sequence& sx = x.getConst<ExprSequence>().getSequence();
+ const Sequence& sy = y.getConst<ExprSequence>().getSequence();
+ return sx.roverlap(sy);
+ }
Unimplemented();
return 0;
}
+bool Word::isRepeated(TNode x)
+{
+ Kind k = x.getKind();
+ if (k == CONST_STRING)
+ {
+ return x.getConst<String>().isRepeated();
+ }
+ else if (k == CONST_SEQUENCE)
+ {
+ return x.getConst<ExprSequence>().getSequence().isRepeated();
+ }
+ Unimplemented();
+ return false;
+}
+
Node Word::splitConstant(TNode x, TNode y, size_t& index, bool isRev)
{
Assert(x.isConst() && y.isConst());
diff --git a/src/theory/strings/word.h b/src/theory/strings/word.h
index b84ea6874..ad1d9bc74 100644
--- a/src/theory/strings/word.h
+++ b/src/theory/strings/word.h
@@ -37,7 +37,7 @@ class Word
static Node mkEmptyWord(Kind k);
/** make word from constants in (non-empty) vector vec */
- static Node mkWord(const std::vector<Node>& xs);
+ static Node mkWordFlatten(const std::vector<Node>& xs);
/** Return the length of word x */
static size_t getLength(TNode x);
@@ -139,6 +139,8 @@ class Word
* Notice that x.overlap(y) = y.roverlap(x)
*/
static std::size_t roverlap(TNode x, TNode y);
+ /** Return true if word x is a repetition of the same character */
+ static bool isRepeated(TNode x);
/** Split constant
*
* This returns the suffix remainder (resp. prefix remainder when isRev is
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index 2c27c6054..71c144daa 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -1931,7 +1931,14 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node,
// Lemma analysis isn't online yet; this lemma may only live for this
// user level.
- return theory::LemmaStatus(additionalLemmas[0], d_userContext->getLevel());
+ Node retLemma = additionalLemmas[0];
+ if (additionalLemmas.size() > 1)
+ {
+ // the returned lemma is the conjunction of all additional lemmas.
+ retLemma =
+ NodeManager::currentNM()->mkNode(kind::AND, additionalLemmas.ref());
+ }
+ return theory::LemmaStatus(retLemma, d_userContext->getLevel());
}
void TheoryEngine::conflict(TNode conflict, TheoryId theoryId) {
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index 9c631ca60..233047321 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -890,8 +890,6 @@ public:
theory::eq::EqualityEngine* getMasterEqualityEngine() { return d_masterEqualityEngine; }
- RemoveTermFormulas* getTermFormulaRemover() { return &d_tform_remover; }
-
SortInference* getSortInference() { return &d_sortInfer; }
/** Prints the assertions to the debug stream */
diff --git a/src/theory/uf/proof_checker.cpp b/src/theory/uf/proof_checker.cpp
new file mode 100644
index 000000000..28ae34b7b
--- /dev/null
+++ b/src/theory/uf/proof_checker.cpp
@@ -0,0 +1,172 @@
+/********************* */
+/*! \file proof_checker.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Haniel Barbosa, Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of equality proof checker
+ **/
+
+#include "theory/uf/proof_checker.h"
+
+using namespace CVC4::kind;
+
+namespace CVC4 {
+namespace theory {
+namespace uf {
+
+void UfProofRuleChecker::registerTo(ProofChecker* pc)
+{
+ // add checkers
+ pc->registerChecker(PfRule::REFL, this);
+ pc->registerChecker(PfRule::SYMM, this);
+ pc->registerChecker(PfRule::TRANS, this);
+ pc->registerChecker(PfRule::CONG, this);
+ pc->registerChecker(PfRule::TRUE_INTRO, this);
+ pc->registerChecker(PfRule::TRUE_ELIM, this);
+ pc->registerChecker(PfRule::FALSE_INTRO, this);
+ pc->registerChecker(PfRule::FALSE_ELIM, this);
+}
+
+Node UfProofRuleChecker::checkInternal(PfRule id,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args)
+{
+ // compute what was proven
+ if (id == PfRule::REFL)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ return args[0].eqNode(args[0]);
+ }
+ else if (id == PfRule::SYMM)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ bool polarity = children[0].getKind() != NOT;
+ Node eqp = polarity ? children[0] : children[0][0];
+ if (eqp.getKind() != EQUAL)
+ {
+ // not a (dis)equality
+ return Node::null();
+ }
+ Node conc = eqp[1].eqNode(eqp[0]);
+ return polarity ? conc : conc.notNode();
+ }
+ else if (id == PfRule::TRANS)
+ {
+ Assert(children.size() > 0);
+ Assert(args.empty());
+ Node first;
+ Node curr;
+ for (size_t i = 0, nchild = children.size(); i < nchild; i++)
+ {
+ Node eqp = children[i];
+ if (eqp.getKind() != EQUAL)
+ {
+ return Node::null();
+ }
+ if (first.isNull())
+ {
+ first = eqp[0];
+ }
+ else if (eqp[0] != curr)
+ {
+ return Node::null();
+ }
+ curr = eqp[1];
+ }
+ return first.eqNode(curr);
+ }
+ else if (id == PfRule::CONG)
+ {
+ Assert(children.size() > 0);
+ Assert(args.size() == 1);
+ // We do congruence over builtin kinds using operatorToKind
+ std::vector<Node> lchildren;
+ std::vector<Node> rchildren;
+ // get the expected kind for args[0]
+ Kind k = NodeManager::getKindForFunction(args[0]);
+ if (k == kind::UNDEFINED_KIND)
+ {
+ k = NodeManager::operatorToKind(args[0]);
+ }
+ if (k == kind::UNDEFINED_KIND)
+ {
+ return Node::null();
+ }
+ Trace("uf-pfcheck") << "congruence for " << args[0] << " uses kind " << k
+ << ", metakind=" << kind::metaKindOf(k) << std::endl;
+ if (kind::metaKindOf(k) == kind::metakind::PARAMETERIZED)
+ {
+ // parameterized kinds require the operator
+ lchildren.push_back(args[0]);
+ rchildren.push_back(args[0]);
+ }
+ for (size_t i = 0, nchild = children.size(); i < nchild; i++)
+ {
+ Node eqp = children[i];
+ if (eqp.getKind() != EQUAL)
+ {
+ return Node::null();
+ }
+ lchildren.push_back(eqp[0]);
+ rchildren.push_back(eqp[1]);
+ }
+ NodeManager* nm = NodeManager::currentNM();
+ Node l = nm->mkNode(k, lchildren);
+ Node r = nm->mkNode(k, rchildren);
+ return l.eqNode(r);
+ }
+ else if (id == PfRule::TRUE_INTRO)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ Node trueNode = NodeManager::currentNM()->mkConst(true);
+ return children[0].eqNode(trueNode);
+ }
+ else if (id == PfRule::TRUE_ELIM)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != EQUAL || !children[0][1].isConst()
+ || !children[0][1].getConst<bool>())
+ {
+ return Node::null();
+ }
+ return children[0][0];
+ }
+ else if (id == PfRule::FALSE_INTRO)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::NOT)
+ {
+ return Node::null();
+ }
+ Node falseNode = NodeManager::currentNM()->mkConst(false);
+ return children[0][0].eqNode(falseNode);
+ }
+ else if (id == PfRule::FALSE_ELIM)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != EQUAL || !children[0][1].isConst()
+ || children[0][1].getConst<bool>())
+ {
+ return Node::null();
+ }
+ return children[0][0].notNode();
+ }
+ // no rule
+ return Node::null();
+}
+
+} // namespace uf
+} // namespace theory
+} // namespace CVC4
diff --git a/src/theory/uf/proof_checker.h b/src/theory/uf/proof_checker.h
new file mode 100644
index 000000000..022574eab
--- /dev/null
+++ b/src/theory/uf/proof_checker.h
@@ -0,0 +1,49 @@
+/********************* */
+/*! \file proof_checker.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Haniel Barbosa, Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 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 Equality proof checker utility
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__THEORY__UF__PROOF_CHECKER_H
+#define CVC4__THEORY__UF__PROOF_CHECKER_H
+
+#include "expr/node.h"
+#include "expr/proof_checker.h"
+#include "expr/proof_node.h"
+
+namespace CVC4 {
+namespace theory {
+namespace uf {
+
+/** A checker for builtin proofs */
+class UfProofRuleChecker : public ProofRuleChecker
+{
+ public:
+ UfProofRuleChecker() {}
+ ~UfProofRuleChecker() {}
+
+ /** Register all rules owned by this rule checker into pc. */
+ void registerTo(ProofChecker* pc) override;
+
+ protected:
+ /** Return the conclusion of the given proof step, or null if it is invalid */
+ Node checkInternal(PfRule id,
+ const std::vector<Node>& children,
+ const std::vector<Node>& args) override;
+};
+
+} // namespace uf
+} // namespace theory
+} // namespace CVC4
+
+#endif /* CVC4__THEORY__UF__PROOF_CHECKER_H */
diff --git a/src/util/floatingpoint.cpp b/src/util/floatingpoint.cpp
index 3bcf2b0de..f5545f73c 100644
--- a/src/util/floatingpoint.cpp
+++ b/src/util/floatingpoint.cpp
@@ -925,7 +925,8 @@ static FloatingPointLiteral constructorHelperBitVector(
// We only have multiplyByPow(uint32_t) so we can't convert all numbers.
// As we convert Integer -> unsigned int -> uint32_t we need that
// unsigned int is not smaller than uint32_t
- static_assert(sizeof(unsigned int) >= sizeof(uint32_t));
+ static_assert(sizeof(unsigned int) >= sizeof(uint32_t),
+ "Conversion float -> real could loose data");
#ifdef CVC4_ASSERTIONS
// Note that multipling by 2^n requires n bits of space (worst case)
// so, in effect, these tests limit us to cases where the resultant
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback