diff options
author | Andrew Reynolds <andrew.j.reynolds@gmail.com> | 2020-07-01 08:46:30 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-01 08:46:30 -0500 |
commit | 12af221551c34a4bffc0282e7b3fa8dea661190c (patch) | |
tree | 40a384f74915e2c009bb2a66bd0295e62edcfc2e /src | |
parent | c62980dab74b3db795961f90a4c49c463437a8eb (diff) | |
parent | 04154c08c1af81bb751376ae9379c071a95c5a3f (diff) |
Merge branch 'master' into lfscTestslfscTests
Diffstat (limited to 'src')
1045 files changed, 18474 insertions, 9250 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e9be4dd3e..0774d60af 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -300,20 +300,24 @@ 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/operator_elim.cpp + theory/arith/operator_elim.h theory/arith/partial_model.cpp theory/arith/partial_model.h theory/arith/simplex.cpp @@ -332,8 +336,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 +357,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 +370,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 @@ -413,6 +419,8 @@ libcvc4_add_sources( theory/care_graph.h theory/datatypes/datatypes_rewriter.cpp theory/datatypes/datatypes_rewriter.h + theory/datatypes/sygus_datatype_utils.cpp + theory/datatypes/sygus_datatype_utils.h theory/datatypes/sygus_extension.cpp theory/datatypes/sygus_extension.h theory/datatypes/sygus_simple_sym.cpp @@ -428,6 +436,10 @@ libcvc4_add_sources( theory/decision_manager.h theory/decision_strategy.cpp theory/decision_strategy.h + theory/eager_proof_generator.cpp + theory/eager_proof_generator.h + theory/engine_output_channel.cpp + theory/engine_output_channel.h theory/evaluator.cpp theory/evaluator.h theory/ext_theory.cpp @@ -524,6 +536,8 @@ libcvc4_add_sources( theory/quantifiers/instantiate.h theory/quantifiers/lazy_trie.cpp theory/quantifiers/lazy_trie.h + theory/quantifiers/proof_checker.cpp + theory/quantifiers/proof_checker.h theory/quantifiers/quant_conflict_find.cpp theory/quantifiers/quant_conflict_find.h theory/quantifiers/quant_epr.cpp @@ -639,7 +653,6 @@ libcvc4_add_sources( theory/rewriter.h theory/rewriter_attributes.h theory/sep/theory_sep.cpp - theory/theory_rewriter.h theory/sep/theory_sep.h theory/sep/theory_sep_rewriter.cpp theory/sep/theory_sep_rewriter.h @@ -705,6 +718,8 @@ libcvc4_add_sources( theory/strings/skolem_cache.h theory/strings/solver_state.cpp theory/strings/solver_state.h + theory/strings/strategy.cpp + theory/strings/strategy.h theory/strings/strings_entail.cpp theory/strings/strings_entail.h theory/strings/strings_fmf.cpp @@ -740,8 +755,15 @@ libcvc4_add_sources( theory/theory_model.h theory/theory_model_builder.cpp theory/theory_model_builder.h + theory/theory_preprocessor.cpp + theory/theory_preprocessor.h + theory/theory_proof_step_buffer.cpp + theory/theory_proof_step_buffer.h + theory/theory_rewriter.h theory/theory_registrar.h theory/theory_test_utils.h + theory/trust_node.cpp + theory/trust_node.h theory/type_enumerator.h theory/type_set.cpp theory/type_set.h @@ -750,6 +772,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 @@ -977,6 +1001,7 @@ install(FILES util/divisible.h util/gmp_util.h util/hash.h + util/iand.h util/integer_cln_imp.h util/integer_gmp_imp.h util/maybe.h diff --git a/src/api/cvc4cpp.cpp b/src/api/cvc4cpp.cpp index 1ea421c4b..1e14e9b3a 100644 --- a/src/api/cvc4cpp.cpp +++ b/src/api/cvc4cpp.cpp @@ -2,9 +2,9 @@ /*! \file cvc4cpp.cpp ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Andres Noetzli + ** Aina Niemetz, Makai Mann, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -33,6 +33,9 @@ #include "api/cvc4cpp.h" +#include <cstring> +#include <sstream> + #include "base/check.h" #include "base/configuration.h" #include "expr/expr.h" @@ -49,13 +52,11 @@ #include "smt/model.h" #include "smt/smt_engine.h" #include "theory/logic_info.h" +#include "theory/theory_model.h" #include "util/random.h" #include "util/result.h" #include "util/utility.h" -#include <cstring> -#include <sstream> - namespace CVC4 { namespace api { @@ -213,7 +214,8 @@ const static std::unordered_map<Kind, CVC4::Kind, KindHashFunction> s_kinds{ /* Arrays -------------------------------------------------------------- */ {SELECT, CVC4::Kind::SELECT}, {STORE, CVC4::Kind::STORE}, - {STORE_ALL, CVC4::Kind::STORE_ALL}, + {CONST_ARRAY, CVC4::Kind::STORE_ALL}, + {EQ_RANGE, CVC4::Kind::EQ_RANGE}, /* Datatypes ----------------------------------------------------------- */ {APPLY_SELECTOR, CVC4::Kind::APPLY_SELECTOR}, {APPLY_CONSTRUCTOR, CVC4::Kind::APPLY_CONSTRUCTOR}, @@ -257,6 +259,8 @@ const static std::unordered_map<Kind, CVC4::Kind, KindHashFunction> s_kinds{ {STRING_INDEXOF, CVC4::Kind::STRING_STRIDOF}, {STRING_REPLACE, CVC4::Kind::STRING_STRREPL}, {STRING_REPLACE_ALL, CVC4::Kind::STRING_STRREPLALL}, + {STRING_REPLACE_RE, CVC4::Kind::STRING_REPLACE_RE}, + {STRING_REPLACE_RE_ALL, CVC4::Kind::STRING_REPLACE_RE_ALL}, {STRING_TOLOWER, CVC4::Kind::STRING_TOLOWER}, {STRING_TOUPPER, CVC4::Kind::STRING_TOUPPER}, {STRING_REV, CVC4::Kind::STRING_REV}, @@ -479,7 +483,7 @@ const static std::unordered_map<CVC4::Kind, Kind, CVC4::kind::KindHashFunction> /* Arrays ---------------------------------------------------------- */ {CVC4::Kind::SELECT, SELECT}, {CVC4::Kind::STORE, STORE}, - {CVC4::Kind::STORE_ALL, STORE_ALL}, + {CVC4::Kind::STORE_ALL, CONST_ARRAY}, /* Datatypes ------------------------------------------------------- */ {CVC4::Kind::APPLY_SELECTOR, APPLY_SELECTOR}, {CVC4::Kind::APPLY_CONSTRUCTOR, APPLY_CONSTRUCTOR}, @@ -526,6 +530,8 @@ const static std::unordered_map<CVC4::Kind, Kind, CVC4::kind::KindHashFunction> {CVC4::Kind::STRING_STRIDOF, STRING_INDEXOF}, {CVC4::Kind::STRING_STRREPL, STRING_REPLACE}, {CVC4::Kind::STRING_STRREPLALL, STRING_REPLACE_ALL}, + {CVC4::Kind::STRING_REPLACE_RE, STRING_REPLACE_RE}, + {CVC4::Kind::STRING_REPLACE_RE_ALL, STRING_REPLACE_RE_ALL}, {CVC4::Kind::STRING_TOLOWER, STRING_TOLOWER}, {CVC4::Kind::STRING_TOUPPER, STRING_TOUPPER}, {CVC4::Kind::STRING_REV, STRING_REV}, @@ -724,12 +730,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 +745,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 +842,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 +931,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 +945,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(); } @@ -939,42 +961,42 @@ CVC4::Type Sort::getType(void) const { return *d_type; } size_t Sort::getConstructorArity() const { - CVC4_API_CHECK(isConstructor()) << "Not a function sort."; + CVC4_API_CHECK(isConstructor()) << "Not a function sort: " << (*this); return ConstructorType(*d_type).getArity(); } std::vector<Sort> Sort::getConstructorDomainSorts() const { - CVC4_API_CHECK(isConstructor()) << "Not a function sort."; + CVC4_API_CHECK(isConstructor()) << "Not a function sort: " << (*this); 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(); + CVC4_API_CHECK(isConstructor()) << "Not a function sort: " << (*this); + return Sort(d_solver, ConstructorType(*d_type).getRangeType()); } /* Function sort ------------------------------------------------------- */ size_t Sort::getFunctionArity() const { - CVC4_API_CHECK(isFunction()) << "Not a function sort."; + CVC4_API_CHECK(isFunction()) << "Not a function sort: " << (*this); return FunctionType(*d_type).getArity(); } std::vector<Sort> Sort::getFunctionDomainSorts() const { - CVC4_API_CHECK(isFunction()) << "Not a function sort."; + CVC4_API_CHECK(isFunction()) << "Not a function sort: " << (*this); 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(); + CVC4_API_CHECK(isFunction()) << "Not a function sort" << (*this); + return Sort(d_solver, FunctionType(*d_type).getRangeType()); } /* Array sort ---------------------------------------------------------- */ @@ -982,13 +1004,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 +1018,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 +1039,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 +1084,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 +1105,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); } /* --------------------------------------------------------------------- */ @@ -1103,11 +1125,15 @@ size_t SortHashFunction::operator()(const Sort& s) const /* Op */ /* -------------------------------------------------------------------------- */ -Op::Op() : d_kind(NULL_EXPR), d_expr(new CVC4::Expr()) {} +Op::Op() : d_solver(nullptr), 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 +1349,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 +1398,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 +1421,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 +1433,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 +1451,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 +1475,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())); } } @@ -1470,14 +1498,23 @@ bool Term::isConst() const return d_expr->isConst(); } +Term Term::getConstArrayBase() const +{ + CVC4_API_CHECK_NOT_NULL; + // CONST_ARRAY kind maps to STORE_ALL internal kind + CVC4_API_CHECK(d_expr->getKind() == CVC4::Kind::STORE_ALL) + << "Expecting a CONST_ARRAY Term when calling getConstArrayBase()"; + return Term(d_solver, d_expr->getConst<ArrayStoreAll>().getExpr()); +} + 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 +1528,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 +1544,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 +1560,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 +1576,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 +1592,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 +1609,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,19 +1621,24 @@ 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) { } Term::const_iterator::const_iterator(const const_iterator& it) - : d_orig_expr(nullptr) + : d_solver(nullptr), d_orig_expr(nullptr) { 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 +1646,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 +1658,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 +1691,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 +1702,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 +1725,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 +1785,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 +1839,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 +1873,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) @@ -1873,10 +1926,11 @@ std::ostream& operator<<(std::ostream& out, const DatatypeDecl& dtdecl) /* DatatypeSelector --------------------------------------------------------- */ -DatatypeSelector::DatatypeSelector() { d_stor = nullptr; } +DatatypeSelector::DatatypeSelector() : d_solver(nullptr), 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 +1941,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 +1973,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 +1991,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 +2008,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 +2029,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 +2138,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 +2149,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 @@ -2136,17 +2197,21 @@ bool Datatype::isRecord() const { return d_dtype->isRecord(); } bool Datatype::isFinite() const { return d_dtype->isFinite(); } bool Datatype::isWellFounded() const { return d_dtype->isWellFounded(); } +bool Datatype::hasNestedRecursion() const +{ + return d_dtype->hasNestedRecursion(); +} 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 +2234,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 +2305,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 +2396,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 +2407,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 +2419,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 +2428,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 +2448,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 +2479,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 +2501,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 +2512,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 +2522,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 @@ -2523,6 +2601,7 @@ Solver::Solver(Options* opts) Options* o = opts == nullptr ? new Options() : opts; d_exprMgr.reset(new ExprManager(*o)); d_smtEngine.reset(new SmtEngine(d_exprMgr.get())); + d_smtEngine->setSolver(this); d_rng.reset(new Random((*o)[options::seed])); if (opts == nullptr) delete o; } @@ -2538,9 +2617,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 +2702,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 +2714,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 +2726,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 +2738,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 +2783,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 +2795,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 +2835,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 +2847,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 +2881,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 +2936,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 +2950,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 +2961,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 +2969,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 +2997,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 +3022,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 +3044,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 +3060,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 +3084,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 +3101,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 +3111,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 +3121,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 +3135,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 +3154,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 +3176,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 +3261,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 +3273,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 +3286,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 +3298,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 +3354,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 +3407,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 +3491,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 +3507,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 +3518,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 +3535,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 +3553,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 +3570,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 +3625,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 +3640,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 +3666,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 +3688,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 +3703,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 +3712,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 +3730,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 +3759,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 +3768,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 +3791,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 +3806,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 +3834,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 +3848,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 +3859,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 +3879,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 +3968,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 +4035,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 +4055,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 +4073,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 +4092,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 +4104,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 +4120,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 +4137,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 +4161,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 +4185,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 +4205,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 +4214,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; } /** @@ -4004,28 +4226,31 @@ Sort Solver::declareSort(const std::string& symbol, uint32_t arity) const Term Solver::defineFun(const std::string& symbol, const std::vector<Term>& bound_vars, 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 + Term term, + bool global) const +{ + 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 << "'"; @@ -4036,44 +4261,59 @@ 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; + d_smtEngine->defineFunction(fun, ebound_vars, *term.d_expr, global); + 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_ARG_CHECK_EXPECTED(fun.getSort().isFunction(), fun) << "function"; - std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts(); - size_t size = bound_vars.size(); - CVC4_API_ARG_SIZE_CHECK_EXPECTED(size == domain_sorts.size(), bound_vars) - << "'" << domain_sorts.size() << "'"; - for (size_t i = 0; i < size; ++i) + Term term, + bool global) const +{ + CVC4_API_SOLVER_TRY_CATCH_BEGIN; + + if (fun.getSort().isFunction()) { - CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED( - domain_sorts[i] == bound_vars[i].getSort(), - "sort of parameter", - bound_vars[i], - i) - << "'" << domain_sorts[i] << "'"; + std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts(); + size_t size = bound_vars.size(); + CVC4_API_ARG_SIZE_CHECK_EXPECTED(size == domain_sorts.size(), bound_vars) + << "'" << domain_sorts.size() << "'"; + 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] << "'"; + } + Sort codomain = fun.getSort().getFunctionCodomainSort(); + CVC4_API_CHECK(codomain == term.getSort()) + << "Invalid sort of function body '" << term << "', expected '" + << codomain << "'"; } - Sort codomain = fun.getSort().getFunctionCodomainSort(); - CVC4_API_CHECK(codomain == term.getSort()) - << "Invalid sort of function body '" << term << "', expected '" - << codomain << "'"; + else + { + CVC4_API_ARG_CHECK_EXPECTED(bound_vars.size() == 0, fun) + << "function or nullary symbol"; + } + + CVC4_API_SOLVER_CHECK_TERM(term); - // 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); + d_smtEngine->defineFunction(*fun.d_expr, ebound_vars, *term.d_expr, global); return fun; + CVC4_API_SOLVER_TRY_CATCH_END; } /** @@ -4082,31 +4322,44 @@ Term Solver::defineFun(Term fun, Term Solver::defineFunRec(const std::string& symbol, const std::vector<Term>& bound_vars, 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()) + Term term, + bool global) const +{ + CVC4_API_SOLVER_TRY_CATCH_BEGIN; + + CVC4_API_CHECK(d_smtEngine->getUserLogicInfo().isQuantified()) + << "recursive function definitions require a logic with quantifiers"; + CVC4_API_CHECK( + d_smtEngine->getUserLogicInfo().isTheoryEnabled(theory::THEORY_UF)) + << "recursive function definitions require a logic with uninterpreted " + "functions"; + 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()) { @@ -4114,43 +4367,66 @@ 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; + d_smtEngine->defineFunctionRec(fun, ebound_vars, *term.d_expr, global); + 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_ARG_CHECK_EXPECTED(fun.getSort().isFunction(), fun) << "function"; - std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts(); - size_t size = bound_vars.size(); - CVC4_API_ARG_SIZE_CHECK_EXPECTED(size == domain_sorts.size(), bound_vars) - << "'" << domain_sorts.size() << "'"; - for (size_t i = 0; i < size; ++i) + Term term, + bool global) const +{ + CVC4_API_SOLVER_TRY_CATCH_BEGIN; + + CVC4_API_CHECK(d_smtEngine->getUserLogicInfo().isQuantified()) + << "recursive function definitions require a logic with quantifiers"; + CVC4_API_CHECK( + d_smtEngine->getUserLogicInfo().isTheoryEnabled(theory::THEORY_UF)) + << "recursive function definitions require a logic with uninterpreted " + "functions"; + + if (fun.getSort().isFunction()) { - CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED( - domain_sorts[i] == bound_vars[i].getSort(), - "sort of parameter", - bound_vars[i], - i) - << "'" << domain_sorts[i] << "'"; - } - 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<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts(); + size_t size = bound_vars.size(); + CVC4_API_ARG_SIZE_CHECK_EXPECTED(size == domain_sorts.size(), bound_vars) + << "'" << domain_sorts.size() << "'"; + 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] << "'"; + } + Sort codomain = fun.getSort().getFunctionCodomainSort(); + CVC4_API_CHECK(codomain == term.getSort()) + << "Invalid sort of function body '" << term << "', expected '" + << codomain << "'"; + } + else + { + CVC4_API_ARG_CHECK_EXPECTED(bound_vars.size() == 0, fun) + << "function or nullary symbol"; + } + + CVC4_API_SOLVER_CHECK_TERM(term); std::vector<Expr> ebound_vars = termVectorToExprs(bound_vars); - d_smtEngine->defineFunctionRec(*fun.d_expr, ebound_vars, *term.d_expr); + d_smtEngine->defineFunctionRec( + *fun.d_expr, ebound_vars, *term.d_expr, global); return fun; + CVC4_API_SOLVER_TRY_CATCH_END; } /** @@ -4158,17 +4434,18 @@ Term Solver::defineFunRec(Term fun, */ 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()) + const std::vector<Term>& terms, + bool global) const +{ + CVC4_API_SOLVER_TRY_CATCH_BEGIN; + + CVC4_API_CHECK(d_smtEngine->getUserLogicInfo().isQuantified()) + << "recursive function definitions require a logic with quantifiers"; + CVC4_API_CHECK( + d_smtEngine->getUserLogicInfo().isTheoryEnabled(theory::THEORY_UF)) + << "recursive function definitions require a logic with uninterpreted " + "functions"; + size_t funs_size = funs.size(); CVC4_API_ARG_SIZE_CHECK_EXPECTED(funs_size == bound_vars.size(), bound_vars) << "'" << funs_size << "'"; @@ -4178,27 +4455,50 @@ void Solver::defineFunsRec(const std::vector<Term>& funs, const std::vector<Term>& bvars = bound_vars[j]; const Term& term = terms[j]; - CVC4_API_ARG_CHECK_EXPECTED(fun.getSort().isFunction(), fun) << "function"; - 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) + CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED( + this == fun.d_solver, "function", fun, j) + << "function associated to this solver object"; + CVC4_API_SOLVER_CHECK_TERM(term); + + if (fun.getSort().isFunction()) { + 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", + bvars[i], + i) + << "'" << domain_sorts[i] << "' in parameter bound_vars[" << j + << "]"; + } + Sort codomain = fun.getSort().getFunctionCodomainSort(); CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED( - domain_sorts[i] == bvars[i].getSort(), - "sort of parameter", - bvars[i], - i) - << "'" << domain_sorts[i] << "' in parameter bound_vars[" << j << "]"; + codomain == term.getSort(), "sort of function body", term, j) + << "'" << codomain << "'"; + } + else + { + CVC4_API_ARG_CHECK_EXPECTED(bvars.size() == 0, fun) + << "function or nullary symbol"; } - Sort codomain = fun.getSort().getFunctionCodomainSort(); - CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED( - 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) @@ -4206,7 +4506,8 @@ void Solver::defineFunsRec(const std::vector<Term>& funs, ebound_vars.push_back(termVectorToExprs(v)); } std::vector<Expr> exprs = termVectorToExprs(terms); - d_smtEngine->defineFunctionsRec(efuns, ebound_vars, exprs); + d_smtEngine->defineFunctionsRec(efuns, ebound_vars, exprs, global); + CVC4_API_SOLVER_TRY_CATCH_END; } /** @@ -4222,6 +4523,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 +4531,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 +4542,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 +4562,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 +4575,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 +4586,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 +4605,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 +4616,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 +4631,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 +4642,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 +4653,75 @@ 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; +} + +Term Solver::getSeparationHeap() const +{ + CVC4_API_SOLVER_TRY_CATCH_BEGIN; + CVC4_API_CHECK( + d_smtEngine->getLogicInfo().isTheoryEnabled(theory::THEORY_SEP)) + << "Cannot obtain separation logic expressions if not using the " + "separation logic theory."; + CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get())); + CVC4_API_CHECK(CVC4::options::produceModels()) + << "Cannot get separation heap term unless model generation is enabled " + "(try --produce-models)"; + CVC4_API_CHECK(d_smtEngine->getSmtMode() + != SmtEngine::SmtMode::SMT_MODE_UNSAT) + << "Cannot get separtion heap term when in unsat mode."; + + theory::TheoryModel* m = + d_smtEngine->getAvailableModel("get separation logic heap and nil"); + Expr heap, nil; + bool hasHeapModel = m->getHeapModel(heap, nil); + CVC4_API_CHECK(hasHeapModel) + << "Failed to obtain heap term from theory model."; + return Term(this, d_smtEngine->getSepHeapExpr()); + CVC4_API_SOLVER_TRY_CATCH_END; +} + +Term Solver::getSeparationNilTerm() const +{ + CVC4_API_SOLVER_TRY_CATCH_BEGIN; + CVC4_API_CHECK( + d_smtEngine->getLogicInfo().isTheoryEnabled(theory::THEORY_SEP)) + << "Cannot obtain separation logic expressions if not using the " + "separation logic theory."; + CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get())); + CVC4_API_CHECK(CVC4::options::produceModels()) + << "Cannot get separation nil term unless model generation is enabled " + "(try --produce-models)"; + CVC4_API_CHECK(d_smtEngine->getSmtMode() + != SmtEngine::SmtMode::SMT_MODE_UNSAT) + << "Cannot get separtion nil term when in unsat mode."; + + theory::TheoryModel* m = + d_smtEngine->getAvailableModel("get separation logic heap and nil"); + Expr heap, nil; + bool hasHeapModel = m->getHeapModel(heap, nil); + CVC4_API_CHECK(hasHeapModel) + << "Failed to obtain nil term from theory model."; + return Term(this, nil); + CVC4_API_SOLVER_TRY_CATCH_END; } /** @@ -4356,10 +4744,43 @@ void Solver::pop(uint32_t nscopes) const CVC4_API_SOLVER_TRY_CATCH_END; } +bool Solver::getInterpolant(Term conj, Term& output) const +{ + CVC4_API_SOLVER_TRY_CATCH_BEGIN; + Expr result; + bool success = d_smtEngine->getInterpol(*conj.d_expr, result); + if (success) { + output = Term(output.d_solver, result); + } + return success; + CVC4_API_SOLVER_TRY_CATCH_END; +} + +bool Solver::getInterpolant(Term conj, const Type& gtype, Term& output) const +{ + CVC4_API_SOLVER_TRY_CATCH_BEGIN; + Expr result; + bool success = d_smtEngine->getInterpol(*conj.d_expr, gtype, result); + if (success) + { + output = Term(output.d_solver, result); + } + return success; + CVC4_API_SOLVER_TRY_CATCH_END; +} + 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 +4804,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 +4816,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 +4836,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 +4858,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 +4886,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 +4899,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 +4914,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 +4937,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 +4972,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 +5000,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 +5035,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 +5058,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 +5101,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 +5126,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 +5162,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 +5222,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..76306d443 100644 --- a/src/api/cvc4cpp.h +++ b/src/api/cvc4cpp.h @@ -2,9 +2,9 @@ /*! \file cvc4cpp.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Andres Noetzli + ** Aina Niemetz, Andrew Reynolds, Abdalrhman Mohamed ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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. @@ -884,6 +900,13 @@ class CVC4_PUBLIC Term bool isConst() const; /** + * Return the base (element stored at all indices) of a constant array + * throws an exception if the kind is not CONST_ARRAY + * @return the base value + */ + Term getConstArrayBase() const; + + /** * Boolean negation. * @return the Boolean negation of this term */ @@ -955,10 +978,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 +1031,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 +1055,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 +1174,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 +1205,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 +1238,7 @@ class CVC4_PUBLIC DatatypeDecl public: /** - * Nullary constructor for Cython + * Nullary constructor for Cython. */ DatatypeDecl(); @@ -1211,6 +1259,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 +1279,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 +1304,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 +1351,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 +1385,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 +1418,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 +1531,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 +1577,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 +1607,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(); @@ -1591,6 +1673,17 @@ class CVC4_PUBLIC Datatype bool isWellFounded() const; /** + * Does this datatype have nested recursion? This method returns false if a + * value of this datatype includes a subterm of its type that is nested + * beneath a non-datatype type constructor. For example, a datatype + * T containing a constructor having a selector with range type (Set T) has + * nested recursion. + * + * @return true if this datatype has nested recursion + */ + bool hasNestedRecursion() const; + + /** * @return a string representation of this datatype */ std::string toString() const; @@ -1654,16 +1747,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 +1791,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 +1901,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 +1971,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 +2721,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 */ /* .................................................................... */ @@ -2746,12 +2860,15 @@ class CVC4_PUBLIC Solver * @param bound_vars the parameters to this function * @param sort the sort of the return value of this function * @param term the function body + * @param global determines whether this definition is global (i.e. persists + * when popping the context) * @return the function */ Term defineFun(const std::string& symbol, const std::vector<Term>& bound_vars, Sort sort, - Term term) const; + Term term, + bool global = false) const; /** * Define n-ary function. * SMT-LIB: ( define-fun <function_def> ) @@ -2759,11 +2876,14 @@ class CVC4_PUBLIC Solver * @param fun the sorted function * @param bound_vars the parameters to this function * @param term the function body + * @param global determines whether this definition is global (i.e. persists + * when popping the context) * @return the function */ Term defineFun(Term fun, const std::vector<Term>& bound_vars, - Term term) const; + Term term, + bool global = false) const; /** * Define recursive function. @@ -2772,12 +2892,15 @@ class CVC4_PUBLIC Solver * @param bound_vars the parameters to this function * @param sort the sort of the return value of this function * @param term the function body + * @param global determines whether this definition is global (i.e. persists + * when popping the context) * @return the function */ Term defineFunRec(const std::string& symbol, const std::vector<Term>& bound_vars, Sort sort, - Term term) const; + Term term, + bool global = false) const; /** * Define recursive function. @@ -2786,11 +2909,14 @@ class CVC4_PUBLIC Solver * @param fun the sorted function * @param bound_vars the parameters to this function * @param term the function body + * @param global determines whether this definition is global (i.e. persists + * when popping the context) * @return the function */ Term defineFunRec(Term fun, const std::vector<Term>& bound_vars, - Term term) const; + Term term, + bool global = false) const; /** * Define recursive functions. @@ -2799,11 +2925,14 @@ class CVC4_PUBLIC Solver * @param funs the sorted functions * @param bound_vars the list of parameters to the functions * @param term the list of function bodies of the functions + * @param global determines whether this definition is global (i.e. persists + * when popping the context) * @return the function */ void defineFunsRec(const std::vector<Term>& funs, const std::vector<std::vector<Term>>& bound_vars, - const std::vector<Term>& terms) const; + const std::vector<Term>& terms, + bool global = false) const; /** * Echo a given string to the given output stream. @@ -2875,6 +3004,18 @@ class CVC4_PUBLIC Solver std::vector<Term> getValue(const std::vector<Term>& terms) const; /** + * When using separation logic, obtain the term for the heap. + * @return The term for the heap + */ + Term getSeparationHeap() const; + + /** + * When using separation logic, obtain the term for nil. + * @return The term for nil + */ + Term getSeparationNilTerm() const; + + /** * Pop (a) level(s) from the assertion stack. * SMT-LIB: ( pop <numeral> ) * @param nscopes the number of levels to pop @@ -2882,6 +3023,29 @@ class CVC4_PUBLIC Solver void pop(uint32_t nscopes = 1) const; /** + * Get an interpolant + * SMT-LIB: ( get-interpol <term> ) + * Requires to enable option 'produce-interpols'. + * @param conj the conjecture term + * @param output a Term I such that A->I and I->B are valid, where A is the + * current set of assertions and B is given in the input by conj. + * @return true if it gets I successfully, false otherwise. + */ + bool getInterpolant(Term conj, Term& output) const; + + /** + * Get an interpolant + * SMT-LIB: ( get-interpol <term> ) + * Requires to enable option 'produce-interpols'. + * @param conj the conjecture term + * @param gtype the grammar for the interpolant I + * @param output a Term I such that A->I and I->B are valid, where A is the + * current set of assertions and B is given in the input by conj. + * @return true if it gets I successfully, false otherwise. + */ + bool getInterpolant(Term conj, const Type& gtype, Term& output) const; + + /** * Print the model of a satisfiable query to the given output stream. * Requires to enable option 'produce-models'. * @param out the output stream @@ -3142,9 +3306,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/cvc4cppkind.h b/src/api/cvc4cppkind.h index e084daf1e..cf9074129 100644 --- a/src/api/cvc4cppkind.h +++ b/src/api/cvc4cppkind.h @@ -2,9 +2,9 @@ /*! \file cvc4cppkind.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz + ** Aina Niemetz, Andrew Reynolds, Makai Mann ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -1504,7 +1504,24 @@ enum CVC4_PUBLIC Kind : int32_t * conditions when there is a chain of equalities connecting two constant * arrays, the solver doesn't know what to do and aborts (Issue #1667). */ - STORE_ALL, + CONST_ARRAY, + /** + * Equality over arrays a and b over a given range [i,j], i.e., + * \forall k . i <= k <= j --> a[k] = b[k] + * + * Parameters: 4 + * -[1]: First array + * -[2]: Second array + * -[3]: Lower bound of range (inclusive) + * -[4]: Uppper bound of range (inclusive) + * Create with: + * mkTerm(Op op, const std::vector<Term>& children) + * + * Note: We currently support the creation of array equalities over index + * types bit-vector, floating-point, integer and real. Option --arrays-exp is + * required to support this operator. + */ + EQ_RANGE, #if 0 /* array table function (internal-only symbol) */ ARR_TABLE_FUN, @@ -2003,6 +2020,33 @@ enum CVC4_PUBLIC Kind : int32_t */ STRING_REPLACE_ALL, /** + * String replace regular expression match. + * Replaces the first match of a regular expression r in string s1 with + * string s2. If r does not match a substring of s1, s1 is returned + * unmodified. + * Parameters: 3 + * -[1]: Term of sort String (string s1) + * -[2]: Term of sort Regexp (regexp r) + * -[3]: Term of sort String (string s2) + * Create with: + * mkTerm(Kind kind, Term child1, Term child2, Term child3) + * mkTerm(Kind kind, const std::vector<Term>& children) + */ + STRING_REPLACE_RE, + /** + * String replace all regular expression matches. + * Replaces all matches of a regular expression r in string s1 with string + * s2. If r does not match a substring of s1, s1 is returned unmodified. + * Parameters: 3 + * -[1]: Term of sort String (string s1) + * -[2]: Term of sort Regexp (regexp r) + * -[3]: Term of sort String (string s2) + * Create with: + * mkTerm(Kind kind, Term child1, Term child2, Term child3) + * mkTerm(Kind kind, const std::vector<Term>& children) + */ + STRING_REPLACE_RE_ALL, + /** * String to lower case. * Parameters: 1 * -[1]: Term of String sort diff --git a/src/api/python/cvc4.pxd b/src/api/python/cvc4.pxd index d81d0c0bf..940922052 100644 --- a/src/api/python/cvc4.pxd +++ b/src/api/python/cvc4.pxd @@ -21,6 +21,7 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4": cdef extern from "api/cvc4cpp.h" namespace "CVC4::api": cdef cppclass Datatype: Datatype() except + + DatatypeConstructor operator[](size_t idx) except + DatatypeConstructor operator[](const string& name) except + DatatypeConstructor getConstructor(const string& name) except + Term getConstructorTerm(const string& name) except + @@ -39,7 +40,12 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api": cdef cppclass DatatypeConstructor: DatatypeConstructor() except + + DatatypeSelector operator[](size_t idx) except + DatatypeSelector operator[](const string& name) except + + string getName() except + + Term getConstructorTerm() except + + Term getTesterTerm() except + + size_t getNumSelectors() except + DatatypeSelector getSelector(const string& name) except + Term getSelectorTerm(const string& name) except + string toString() except + @@ -54,7 +60,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 + @@ -62,12 +67,16 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api": cdef cppclass DatatypeDecl: void addConstructor(const DatatypeConstructorDecl& ctor) except + + size_t getNumConstructors() except + bint isParametric() except + string toString() except + cdef cppclass DatatypeSelector: DatatypeSelector() except + + string getName() except + + Term getSelectorTerm() except + + Sort getRangeSort() except + string toString() except + @@ -81,15 +90,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 +172,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 + @@ -174,14 +191,14 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api": Term declareFun(const string& symbol, const vector[Sort]& sorts, Sort sort) except + Sort declareSort(const string& symbol, uint32_t arity) except + Term defineFun(const string& symbol, const vector[Term]& bound_vars, - Sort sort, Term term) except + - Term defineFun(Term fun, const vector[Term]& bound_vars, Term term) except + + Sort sort, Term term, bint glbl) except + + Term defineFun(Term fun, const vector[Term]& bound_vars, Term term, bint glbl) except + Term defineFunRec(const string& symbol, const vector[Term]& bound_vars, - Sort sort, Term term) except + + Sort sort, Term term, bint glbl) except + Term defineFunRec(Term fun, const vector[Term]& bound_vars, - Term term) except + + Term term, bint glbl) except + Term defineFunsRec(vector[Term]& funs, vector[vector[Term]]& bound_vars, - vector[Term]& terms) except + + vector[Term]& terms, bint glbl) except + vector[Term] getAssertions() except + vector[pair[Term, Term]] getAssignment() except + string getInfo(const string& flag) except + @@ -190,6 +207,8 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api": vector[Term] getUnsatCore() except + Term getValue(Term term) except + vector[Term] getValue(const vector[Term]& terms) except + + Term getSeparationHeap() except + + Term getSeparationNilTerm() except + void pop(uint32_t nscopes) except + void printModel(ostream& out) void push(uint32_t nscopes) except + @@ -204,6 +223,10 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api": Sort() except + bint operator==(const Sort&) except + bint operator!=(const Sort&) except + + bint operator<(const Sort&) except + + bint operator>(const Sort&) except + + bint operator<=(const Sort&) except + + bint operator>=(const Sort&) except + bint isBoolean() except + bint isInteger() except + bint isReal() except + @@ -214,6 +237,9 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api": bint isFloatingPoint() except + bint isDatatype() except + bint isParametricDatatype() except + + bint isConstructor() except + + bint isSelector() except + + bint isTester() except + bint isFunction() except + bint isPredicate() except + bint isTuple() except + @@ -224,20 +250,49 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api": bint isSortConstructor() except + bint isFirstClass() except + bint isFunctionLike() except + + bint isSubsortOf(Sort s) except + + bint isComparableTo(Sort s) except + Datatype getDatatype() except + Sort instantiate(const vector[Sort]& params) except + + size_t getConstructorArity() except + + vector[Sort] getConstructorDomainSorts() except + + Sort getConstructorCodomainSort() except + + size_t getFunctionArity() except + + vector[Sort] getFunctionDomainSorts() except + + Sort getFunctionCodomainSort() except + + Sort getArrayIndexSort() except + + Sort getArrayElementSort() except + + Sort getSetElementSort() except + + string getUninterpretedSortName() except + bint isUninterpretedSortParameterized() except + + vector[Sort] getUninterpretedSortParamSorts() except + + string getSortConstructorName() except + + size_t getSortConstructorArity() except + + uint32_t getBVSize() except + + uint32_t getFPExponentSize() except + + uint32_t getFPSignificandSize() except + + vector[Sort] getDatatypeParamSorts() except + + size_t getDatatypeArity() except + + size_t getTupleLength() except + + vector[Sort] getTupleSorts() 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 + + bint isConst() except + + Term getConstArrayBase() except + Term notTerm() except + Term andTerm(const Term& t) except + Term orTerm(const Term& t) except + @@ -255,6 +310,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..01660e206 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: @@ -57,9 +65,14 @@ cdef class Datatype: def __cinit__(self): pass - def __getitem__(self, str name): + def __getitem__(self, index): cdef DatatypeConstructor dc = DatatypeConstructor() - dc.cdc = self.cd[name.encode()] + if isinstance(index, int) and index >= 0: + dc.cdc = self.cd[(<int?> index)] + elif isinstance(index, str): + dc.cdc = self.cd[(<const string &> name.encode())] + else: + raise ValueError("Expecting a non-negative integer or string") return dc def getConstructor(self, str name): @@ -96,11 +109,32 @@ cdef class DatatypeConstructor: def __cinit__(self): self.cdc = c_DatatypeConstructor() - def __getitem__(self, str name): + def __getitem__(self, index): cdef DatatypeSelector ds = DatatypeSelector() - ds.cds = self.cdc[name.encode()] + if isinstance(index, int) and index >= 0: + ds.cds = self.cdc[(<int?> index)] + elif isinstance(index, str): + ds.cds = self.cdc[(<const string &> name.encode())] + else: + raise ValueError("Expecting a non-negative integer or string") return ds + def getName(self): + return self.cdc.getName().decode() + + def getConstructorTerm(self): + cdef Term term = Term() + term.cterm = self.cdc.getConstructorTerm() + return term + + def getTesterTerm(self): + cdef Term term = Term() + term.cterm = self.cdc.getTesterTerm() + return term + + def getNumSelectors(self): + return self.cdc.getNumSelectors() + def getSelector(self, str name): cdef DatatypeSelector ds = DatatypeSelector() ds.cds = self.cdc.getSelector(name.encode()) @@ -125,12 +159,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 +183,10 @@ cdef class DatatypeDecl: pass def addConstructor(self, DatatypeConstructorDecl ctor): - self.cdd.addConstructor(ctor.cddc[0]) + self.cdd.addConstructor(ctor.cddc) + + def getNumConstructors(self): + return self.cdd.getNumConstructors() def isParametric(self): return self.cdd.isParametric() @@ -164,6 +203,19 @@ cdef class DatatypeSelector: def __cinit__(self): self.cds = c_DatatypeSelector() + def getName(self): + return self.cds.getName().decode() + + def getSelectorTerm(self): + cdef Term term = Term() + term.cterm = self.cds.getSelectorTerm() + return term + + def getRangeSort(self): + cdef Sort sort = Sort() + sort.csort = self.cds.getRangeSort() + return sort + def __str__(self): return self.cds.toString().decode() @@ -188,6 +240,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 +272,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 + + def getUnknownExplanation(self): + return self.cr.getUnknownExplanation().decode() + + def __str__(self): + return self.cr.toString().decode() - @property - def explanation(self): - return self._explanation + def __repr__(self): + return self.cr.toString().decode() cdef class RoundingMode: @@ -663,6 +711,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 +769,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 +782,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 +799,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 +820,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 @@ -797,13 +839,13 @@ cdef class Solver: sort.csort = self.csolver.declareSort(symbol.encode(), arity) return sort - def defineFun(self, sym_or_fun, bound_vars, sort_or_term, t=None): + def defineFun(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False): ''' Supports two uses: Term defineFun(str symbol, List[Term] bound_vars, - Sort sort, Term term) + Sort sort, Term term, bool glbl) Term defineFun(Term fun, List[Term] bound_vars, - Term term) + Term term, bool glbl) ''' cdef Term term = Term() cdef vector[c_Term] v @@ -814,21 +856,23 @@ cdef class Solver: term.cterm = self.csolver.defineFun((<str?> sym_or_fun).encode(), <const vector[c_Term] &> v, (<Sort?> sort_or_term).csort, - (<Term?> t).cterm) + (<Term?> t).cterm, + <bint> glbl) else: term.cterm = self.csolver.defineFun((<Term?> sym_or_fun).cterm, <const vector[c_Term]&> v, - (<Term?> sort_or_term).cterm) + (<Term?> sort_or_term).cterm, + <bint> glbl) return term - def defineFunRec(self, sym_or_fun, bound_vars, sort_or_term, t=None): + def defineFunRec(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False): ''' Supports two uses: Term defineFunRec(str symbol, List[Term] bound_vars, - Sort sort, Term term) + Sort sort, Term term, bool glbl) Term defineFunRec(Term fun, List[Term] bound_vars, - Term term) + Term term, bool glbl) ''' cdef Term term = Term() cdef vector[c_Term] v @@ -839,11 +883,13 @@ cdef class Solver: term.cterm = self.csolver.defineFunRec((<str?> sym_or_fun).encode(), <const vector[c_Term] &> v, (<Sort?> sort_or_term).csort, - (<Term?> t).cterm) + (<Term?> t).cterm, + <bint> glbl) else: term.cterm = self.csolver.defineFunRec((<Term?> sym_or_fun).cterm, <const vector[c_Term]&> v, - (<Term?> sort_or_term).cterm) + (<Term?> sort_or_term).cterm, + <bint> glbl) return term @@ -913,6 +959,16 @@ cdef class Solver: term.cterm = self.csolver.getValue(t.cterm) return term + def getSeparationHeap(self): + cdef Term term = Term() + term.cterm = self.csolver.getSeparationHeap() + return term + + def getSeparationNilTerm(self): + cdef Term term = Term() + term.cterm = self.csolver.getSeparationNilTerm() + return term + def pop(self, nscopes=1): self.csolver.pop(nscopes) @@ -947,12 +1003,27 @@ cdef class Sort: def __ne__(self, Sort other): return self.csort != other.csort + def __lt__(self, Sort other): + return self.csort < other.csort + + def __gt__(self, Sort other): + return self.csort > other.csort + + def __le__(self, Sort other): + return self.csort <= other.csort + + def __ge__(self, Sort other): + return self.csort >= other.csort + def __str__(self): return self.csort.toString().decode() def __repr__(self): return self.csort.toString().decode() + def __hash__(self): + return csorthash(self.csort) + def isBoolean(self): return self.csort.isBoolean() @@ -983,6 +1054,15 @@ cdef class Sort: def isParametricDatatype(self): return self.csort.isParametricDatatype() + def isConstructor(self): + return self.csort.isConstructor() + + def isSelector(self): + return self.csort.isSelector() + + def isTester(self): + return self.csort.isTester() + def isFunction(self): return self.csort.isFunction() @@ -1013,6 +1093,12 @@ cdef class Sort: def isFunctionLike(self): return self.csort.isFunctionLike() + def isSubsortOf(self, Sort sort): + return self.csort.isSubsortOf(sort.csort) + + def isComparableTo(self, Sort sort): + return self.csort.isComparableTo(sort.csort) + def getDatatype(self): cdef Datatype d = Datatype() d.cd = self.csort.getDatatype() @@ -1026,9 +1112,104 @@ cdef class Sort: sort.csort = self.csort.instantiate(v) return sort + def getConstructorArity(self): + return self.csort.getConstructorArity() + + def getConstructorDomainSorts(self): + domain_sorts = [] + for s in self.csort.getConstructorDomainSorts(): + sort = Sort() + sort.csort = s + domain_sorts.append(sort) + return domain_sorts + + def getConstructorCodomainSort(self): + cdef Sort sort = Sort() + sort.csort = self.csort.getConstructorCodomainSort() + return sort + + def getFunctionArity(self): + return self.csort.getFunctionArity() + + def getFunctionDomainSorts(self): + domain_sorts = [] + for s in self.csort.getFunctionDomainSorts(): + sort = Sort() + sort.csort = s + domain_sorts.append(sort) + return domain_sorts + + def getFunctionCodomainSort(self): + cdef Sort sort = Sort() + sort.csort = self.csort.getFunctionCodomainSort() + return sort + + def getArrayIndexSort(self): + cdef Sort sort = Sort() + sort.csort = self.csort.getArrayIndexSort() + return sort + + def getArrayElementSort(self): + cdef Sort sort = Sort() + sort.csort = self.csort.getArrayElementSort() + return sort + + def getSetElementSort(self): + cdef Sort sort = Sort() + sort.csort = self.csort.getSetElementSort() + return sort + + def getUninterpretedSortName(self): + return self.csort.getUninterpretedSortName().decode() + def isUninterpretedSortParameterized(self): return self.csort.isUninterpretedSortParameterized() + def getUninterpretedSortParamSorts(self): + param_sorts = [] + for s in self.csort.getUninterpretedSortParamSorts(): + sort = Sort() + sort.csort = s + param_sorts.append(sort) + return param_sorts + + def getSortConstructorName(self): + return self.csort.getSortConstructorName().decode() + + def getSortConstructorArity(self): + return self.csort.getSortConstructorArity() + + def getBVSize(self): + return self.csort.getBVSize() + + def getFPExponentSize(self): + return self.csort.getFPExponentSize() + + def getFPSignificandSize(self): + return self.csort.getFPSignificandSize() + + def getDatatypeParamSorts(self): + param_sorts = [] + for s in self.csort.getDatatypeParamSorts(): + sort = Sort() + sort.csort = s + param_sorts.append(sort) + return param_sorts + + def getDatatypeArity(self): + return self.csort.getDatatypeArity() + + def getTupleLength(self): + return self.csort.getTupleLength() + + def getTupleSorts(self): + tuple_sorts = [] + for s in self.csort.getTupleSorts(): + sort = Sort() + sort.csort = s + tuple_sorts.append(sort) + return tuple_sorts + cdef class Term: cdef c_Term cterm @@ -1054,6 +1235,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 +1246,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() @@ -1073,6 +1274,14 @@ cdef class Term: def isNull(self): return self.cterm.isNull() + def isConst(self): + return self.cterm.isConst() + + def getConstArrayBase(self): + cdef Term term = Term() + term.cterm = self.cterm.getConstArrayBase() + return term + def notTerm(self): cdef Term term = Term() term.cterm = self.cterm.notTerm() diff --git a/src/api/python/genkinds.py b/src/api/python/genkinds.py index 4fe7347e6..77b168dea 100755 --- a/src/api/python/genkinds.py +++ b/src/api/python/genkinds.py @@ -69,11 +69,21 @@ from cvc4kinds cimport * import sys from types import ModuleType +from libcpp.string cimport string +from libcpp.unordered_map cimport unordered_map + +# these maps are used for creating a kind +# it is needed for dynamically making a kind +# e.g. for getKind() +cdef unordered_map[int, Kind] int2kind +cdef unordered_map[int, string] int2name + cdef class kind: cdef Kind k cdef str name - def __cinit__(self, str name): - self.name = name + def __cinit__(self, int kindint): + self.k = int2kind[kindint] + self.name = str(int2name[kindint]) def __eq__(self, kind other): return (<int> self.k) == (<int> other.k) @@ -100,8 +110,9 @@ kinds.__file__ = kinds.__name__ + ".py" KINDS_ATTR_TEMPLATE = \ r""" -cdef kind {name} = kind("{name}") -{name}.k = {kind} +int2kind[<int> {kind}] = {kind} +int2name[<int> {kind}] = b"{name}" +cdef kind {name} = kind(<int> {kind}) setattr(kinds, "{name}", {name}) """ diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 000aa331c..96b188238 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -4,8 +4,17 @@ find_package(Git) configure_file(GitInfo.cmake.in GitInfo.cmake @ONLY) +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/git_versioninfo.cpp + COMMAND ${CMAKE_COMMAND} -DGIT_FOUND=${GIT_FOUND} -P GitInfo.cmake +) +set_source_files_properties( + ${CMAKE_CURRENT_BINARY_DIR}/git_versioninfo.cpp + PROPERTIES GENERATED TRUE +) add_custom_target(gen-gitinfo - COMMAND ${CMAKE_COMMAND} -DGIT_FOUND=${GIT_FOUND} -P GitInfo.cmake) + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/git_versioninfo.cpp +) #-----------------------------------------------------------------------------# @@ -40,47 +49,42 @@ file(GLOB_RECURSE source_files ${PROJECT_SOURCE_DIR}/src/*.g) string(REPLACE ";" " " source_files_list "${source_files}") -# Note: gen-tags-{debug,trace} are targets since we always want to generate -# the temporary tag files {Debug,Trace}_tags.tmp in order to check if tags -# were added/modified/deleted. -add_custom_target( - gen-tags-debug +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags.tmp COMMAND ${gentmptags_script} ${CMAKE_CURRENT_LIST_DIR} Debug ${source_files_list} - DEPENDS mktags - BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags.tmp + DEPENDS mktags ${gentmptags_script} ${source_files} ) -add_custom_target( - gen-tags-trace +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Trace_tags.tmp COMMAND ${gentmptags_script} ${CMAKE_CURRENT_LIST_DIR} Trace ${source_files_list} - DEPENDS mktags - BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/Trace_tags.tmp + DEPENDS mktags ${gentmptags_script} ${source_files} ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags COMMAND ${gentags_script} Debug - DEPENDS gen-tags-debug ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags.tmp + DEPENDS ${gentags_script} ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags.tmp ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Trace_tags COMMAND ${gentags_script} Trace - DEPENDS gen-tags-trace ${CMAKE_CURRENT_BINARY_DIR}/Trace_tags.tmp + DEPENDS ${gentags_script} ${CMAKE_CURRENT_BINARY_DIR}/Trace_tags.tmp ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags.h COMMAND ${genheader_script} ${CMAKE_CURRENT_LIST_DIR} Debug - DEPENDS mktagheaders ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags + DEPENDS mktagheaders ${genheader_script} ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Trace_tags.h COMMAND ${genheader_script} ${CMAKE_CURRENT_LIST_DIR} Trace - DEPENDS mktagheaders ${CMAKE_CURRENT_BINARY_DIR}/Trace_tags + DEPENDS mktagheaders ${genheader_script} ${CMAKE_CURRENT_BINARY_DIR}/Trace_tags ) add_custom_target(gen-tags @@ -88,3 +92,9 @@ add_custom_target(gen-tags ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags.h ${CMAKE_CURRENT_BINARY_DIR}/Trace_tags.h ) + +set_source_files_properties( + ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags.h + ${CMAKE_CURRENT_BINARY_DIR}/Trace_tags.h + PROPERTIES GENERATED TRUE +) diff --git a/src/base/check.cpp b/src/base/check.cpp index 10ecad191..b81e7b457 100644 --- a/src/base/check.cpp +++ b/src/base/check.cpp @@ -2,9 +2,9 @@ /*! \file check.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Mathias Preiner, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/check.h b/src/base/check.h index 93ad71100..614a844fd 100644 --- a/src/base/check.h +++ b/src/base/check.h @@ -2,9 +2,9 @@ /*! \file check.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Mathias Preiner, Tim King, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/configuration.cpp b/src/base/configuration.cpp index 5df579b86..5fcc5170b 100644 --- a/src/base/configuration.cpp +++ b/src/base/configuration.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/configuration.h b/src/base/configuration.h index 7de4a337b..de060fa00 100644 --- a/src/base/configuration.h +++ b/src/base/configuration.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Francois Bobot, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/configuration_private.h b/src/base/configuration_private.h index e77752420..9c58e7898 100644 --- a/src/base/configuration_private.h +++ b/src/base/configuration_private.h @@ -2,9 +2,9 @@ /*! \file configuration_private.h ** \verbatim ** Top contributors (to current version): - ** Christopher L. Conway, Morgan Deters, Mathias Preiner + ** Christopher L. Conway, Andres Noetzli, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/exception.cpp b/src/base/exception.cpp index cd10f9eb8..5e9135021 100644 --- a/src/base/exception.cpp +++ b/src/base/exception.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/exception.h b/src/base/exception.h index 0d1abd9e0..afd5731e9 100644 --- a/src/base/exception.h +++ b/src/base/exception.h @@ -2,9 +2,9 @@ /*! \file exception.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Andres Noetzli + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/exception.i b/src/base/exception.i index 429d13a63..5098dbc6e 100644 --- a/src/base/exception.i +++ b/src/base/exception.i @@ -6,6 +6,10 @@ %ignore CVC4::Exception::Exception(const char*); %typemap(javabase) CVC4::Exception "java.lang.RuntimeException"; +// Make sure that the CVC4.Exception class of the Python API inherits from +// BaseException and can be caught +%exceptionclass CVC4::Exception; + %rename(CVC4IllegalArgumentException) CVC4::IllegalArgumentException; %include "base/exception.h" diff --git a/src/base/git_versioninfo.cpp.in b/src/base/git_versioninfo.cpp.in index 5c18d4e2b..478ea1f9c 100644 --- a/src/base/git_versioninfo.cpp.in +++ b/src/base/git_versioninfo.cpp.in @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/listener.cpp b/src/base/listener.cpp index 4a59058e6..63617f978 100644 --- a/src/base/listener.cpp +++ b/src/base/listener.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/listener.h b/src/base/listener.h index 842567646..e131d0420 100644 --- a/src/base/listener.h +++ b/src/base/listener.h @@ -2,9 +2,9 @@ /*! \file listener.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Andres Noetzli + ** Tim King, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/map_util.h b/src/base/map_util.h index 67f369ce7..5c2bd5820 100644 --- a/src/base/map_util.h +++ b/src/base/map_util.h @@ -2,9 +2,9 @@ /*! \file map_util.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/modal_exception.h b/src/base/modal_exception.h index 4fa9349fb..76fe5c841 100644 --- a/src/base/modal_exception.h +++ b/src/base/modal_exception.h @@ -2,9 +2,9 @@ /*! \file modal_exception.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli + ** Morgan Deters, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/output.cpp b/src/base/output.cpp index fee8b1d8d..d6a45a3b2 100644 --- a/src/base/output.cpp +++ b/src/base/output.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/base/output.h b/src/base/output.h index c3a073580..c1e2dafad 100644 --- a/src/base/output.h +++ b/src/base/output.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andres Noetzli, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/bindings/java/CMakeLists.txt b/src/bindings/java/CMakeLists.txt index 2cecf15e9..8159b8ee0 100644 --- a/src/bindings/java/CMakeLists.txt +++ b/src/bindings/java/CMakeLists.txt @@ -81,6 +81,7 @@ set(gen_java_files ${CMAKE_CURRENT_BINARY_DIR}/FloatingPointType.java ${CMAKE_CURRENT_BINARY_DIR}/FunctionType.java ${CMAKE_CURRENT_BINARY_DIR}/InputLanguage.java + ${CMAKE_CURRENT_BINARY_DIR}/IntAnd.java ${CMAKE_CURRENT_BINARY_DIR}/IntToBitVector.java ${CMAKE_CURRENT_BINARY_DIR}/Integer.java ${CMAKE_CURRENT_BINARY_DIR}/IntegerHashFunction.java @@ -97,7 +98,6 @@ set(gen_java_files ${CMAKE_CURRENT_BINARY_DIR}/LastExceptionBuffer.java ${CMAKE_CURRENT_BINARY_DIR}/LogicException.java ${CMAKE_CURRENT_BINARY_DIR}/LogicInfo.java - ${CMAKE_CURRENT_BINARY_DIR}/Map_ExprExpr.java ${CMAKE_CURRENT_BINARY_DIR}/ModalException.java ${CMAKE_CURRENT_BINARY_DIR}/OptionException.java ${CMAKE_CURRENT_BINARY_DIR}/Options.java @@ -107,10 +107,6 @@ set(gen_java_files ${CMAKE_CURRENT_BINARY_DIR}/Rational.java ${CMAKE_CURRENT_BINARY_DIR}/RationalHashFunction.java ${CMAKE_CURRENT_BINARY_DIR}/RealType.java - ${CMAKE_CURRENT_BINARY_DIR}/Record.java - ${CMAKE_CURRENT_BINARY_DIR}/RecordHashFunction.java - ${CMAKE_CURRENT_BINARY_DIR}/RecordUpdate.java - ${CMAKE_CURRENT_BINARY_DIR}/RecordUpdateHashFunction.java ${CMAKE_CURRENT_BINARY_DIR}/RecoverableModalException.java ${CMAKE_CURRENT_BINARY_DIR}/RegExpLoop.java ${CMAKE_CURRENT_BINARY_DIR}/RegExpRepeat.java @@ -122,22 +118,18 @@ set(gen_java_files ${CMAKE_CURRENT_BINARY_DIR}/SExprKeyword.java ${CMAKE_CURRENT_BINARY_DIR}/SExprType.java ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_CVC4__Model.java - ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_CVC4__Printer.java ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_CVC4__options__InstFormatMode.java - ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_Listener.java - ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_ListenerCollection__Registration.java ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_MaybeT_CVC4__Rational_t.java ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_Type.java ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_std__istream.java ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_std__ostream.java ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_std__shared_ptrT_CVC4__SygusPrintCallback_t.java ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_std__string.java - ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_std__unordered_mapT_CVC4__Expr_CVC4__ProofLetCount_CVC4__ExprHashFunction_t.java ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_std__vectorT_CVC4__DatatypeConstructorArg_t.java - ${CMAKE_CURRENT_BINARY_DIR}/SWIGTYPE_p_std__vectorT_CVC4__DatatypeConstructor_t.java ${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 @@ -146,7 +138,6 @@ set(gen_java_files ${CMAKE_CURRENT_BINARY_DIR}/Statistics.java ${CMAKE_CURRENT_BINARY_DIR}/StatisticsBase.java ${CMAKE_CURRENT_BINARY_DIR}/StringType.java - ${CMAKE_CURRENT_BINARY_DIR}/SygusPrintCallback.java ${CMAKE_CURRENT_BINARY_DIR}/TesterType.java ${CMAKE_CURRENT_BINARY_DIR}/TheoryId.java ${CMAKE_CURRENT_BINARY_DIR}/TupleUpdate.java @@ -162,13 +153,10 @@ set(gen_java_files ${CMAKE_CURRENT_BINARY_DIR}/UnsafeInterruptException.java ${CMAKE_CURRENT_BINARY_DIR}/UnsatCore.java ${CMAKE_CURRENT_BINARY_DIR}/VariableTypeMap.java - ${CMAKE_CURRENT_BINARY_DIR}/hashmapExpr.java - ${CMAKE_CURRENT_BINARY_DIR}/pairStringType.java ${CMAKE_CURRENT_BINARY_DIR}/setOfType.java ${CMAKE_CURRENT_BINARY_DIR}/vectorDatatype.java ${CMAKE_CURRENT_BINARY_DIR}/vectorDatatypeType.java ${CMAKE_CURRENT_BINARY_DIR}/vectorExpr.java - ${CMAKE_CURRENT_BINARY_DIR}/vectorPairStringType.java ${CMAKE_CURRENT_BINARY_DIR}/vectorSExpr.java ${CMAKE_CURRENT_BINARY_DIR}/vectorString.java ${CMAKE_CURRENT_BINARY_DIR}/vectorType.java diff --git a/src/bindings/java/cvc4_std_vector.i b/src/bindings/java/cvc4_std_vector.i new file mode 100644 index 000000000..e032426a0 --- /dev/null +++ b/src/bindings/java/cvc4_std_vector.i @@ -0,0 +1,206 @@ +/** + * The following file is based on + * https://github.com/swig/swig/blob/master/Lib/java/std_vector.i + * + * Note: The SWIG library is under a different license than SWIG itself. See + * https://github.com/swig/swig/blob/master/LICENSE for details. + * + * This file defines the macro SWIG_STD_VECTOR_EM to wrap a C++ std::vector for + * Java, similar to the SWIG library. The core difference is that the utilities + * in this file add a reference to an ExprManager to keep it alive as long as + * the vector lives. + */ + +%include <std_common.i> + +%{ +#include <vector> +#include <stdexcept> +%} + +%fragment("SWIG_VectorSize", "header", fragment="SWIG_JavaIntFromSize_t") { +SWIGINTERN jint SWIG_VectorSize(size_t size) { + static const jint JINT_MAX = 0x7FFFFFFF; + if (size > static_cast<size_t>(JINT_MAX)) + { + throw std::out_of_range("vector size is too large to fit into a Java int"); + } + return static_cast<jint>(size); +} +} + +%define SWIG_STD_VECTOR_EM(CTYPE, CONST_REFERENCE) + +namespace std { + template<> class vector<CTYPE> { + +%typemap(javabase) std::vector< CTYPE > "java.util.AbstractList<$typemap(jstype, CTYPE)>" +%typemap(javainterfaces) std::vector< CTYPE > "java.util.RandomAccess" + +%typemap(javabody) std::vector< CTYPE > %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; + } + + public $javaclassname(ExprManager em) { + this(); + this.em = em; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javaconstruct) std::vector<CTYPE> { + this(null, $imcall, true); +} + +%javamethodmodifiers vector() "private"; + +%proxycode %{ + public $javaclassname(ExprManager em, $typemap(jstype, CTYPE)[] initialElements) { + this(em); + reserve(initialElements.length); + + for ($typemap(jstype, CTYPE) element : initialElements) { + add(element); + } + } + + public $javaclassname(ExprManager em, Iterable<$typemap(jstype, CTYPE)> initialElements) { + this(em); + for ($typemap(jstype, CTYPE) element : initialElements) { + add(element); + } + } + + public $typemap(jstype, CTYPE) get(int index) { + return doGet(index); + } + + public $typemap(jstype, CTYPE) set(int index, $typemap(jstype, CTYPE) e) { + return doSet(index, e); + } + + public boolean add($typemap(jstype, CTYPE) e) { + modCount++; + doAdd(e); + return true; + } + + public void add(int index, $typemap(jstype, CTYPE) e) { + modCount++; + doAdd(index, e); + } + + public $typemap(jstype, CTYPE) remove(int index) { + modCount++; + return doRemove(index); + } + + protected void removeRange(int fromIndex, int toIndex) { + modCount++; + doRemoveRange(fromIndex, toIndex); + } + + public int size() { + return doSize(); + } +%} + + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef CTYPE value_type; + typedef CTYPE *pointer; + typedef CTYPE const *const_pointer; + typedef CTYPE &reference; + typedef CONST_REFERENCE const_reference; + + vector(); + size_type capacity() const; + void reserve(size_type n) throw (std::length_error); + %rename(isEmpty) empty; + bool empty() const; + void clear(); + %extend { + %fragment("SWIG_VectorSize"); + + vector(jint count, const CTYPE &value) throw (std::out_of_range) { + if (count < 0) + throw std::out_of_range("vector count must be positive"); + return new std::vector< CTYPE >(static_cast<std::vector< CTYPE >::size_type>(count), value); + } + + jint doSize() const throw (std::out_of_range) { + return SWIG_VectorSize(self->size()); + } + + void doAdd(const value_type& x) { + self->push_back(x); + } + + void doAdd(jint index, const value_type& x) throw (std::out_of_range) { + jint size = static_cast<jint>(self->size()); + if (0 <= index && index <= size) { + self->insert(self->begin() + index, x); + } else { + throw std::out_of_range("vector index out of range"); + } + } + + value_type doRemove(jint index) throw (std::out_of_range) { + jint size = static_cast<jint>(self->size()); + if (0 <= index && index < size) { + CTYPE const old_value = (*self)[index]; + self->erase(self->begin() + index); + return old_value; + } else { + throw std::out_of_range("vector index out of range"); + } + } + + CONST_REFERENCE doGet(jint index) throw (std::out_of_range) { + jint size = static_cast<jint>(self->size()); + if (index >= 0 && index < size) + return (*self)[index]; + else + throw std::out_of_range("vector index out of range"); + } + + value_type doSet(jint index, const value_type& val) throw (std::out_of_range) { + jint size = static_cast<jint>(self->size()); + if (index >= 0 && index < size) { + CTYPE const old_value = (*self)[index]; + (*self)[index] = val; + return old_value; + } + else + throw std::out_of_range("vector index out of range"); + } + + void doRemoveRange(jint fromIndex, jint toIndex) throw (std::out_of_range) { + jint size = static_cast<jint>(self->size()); + if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) { + self->erase(self->begin() + fromIndex, self->begin() + toIndex); + } else { + throw std::out_of_range("vector index out of range"); + } + } + } + }; +} + +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea +%typemap(javaconstruct) vector<CTYPE> { + this(null, $imcall, true); +} + +%enddef diff --git a/src/bindings/java_iterator_adapter.h b/src/bindings/java_iterator_adapter.h index 270fe7baa..864619004 100644 --- a/src/bindings/java_iterator_adapter.h +++ b/src/bindings/java_iterator_adapter.h @@ -2,9 +2,9 @@ /*! \file java_iterator_adapter.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Andres Noetzli, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -46,6 +46,8 @@ class JavaIteratorAdapter "value_type must be convertible from T::const_iterator::value_type"); } + JavaIteratorAdapter() = delete; + bool hasNext() { return d_it != d_t.end(); } value_type getNext() diff --git a/src/bindings/java_iterator_adapter.i b/src/bindings/java_iterator_adapter.i new file mode 100644 index 000000000..5f814edd7 --- /dev/null +++ b/src/bindings/java_iterator_adapter.i @@ -0,0 +1,75 @@ +%{ +#include "bindings/java_iterator_adapter.h" +%} + +#ifdef SWIGJAVA + +%define SWIG_JAVA_ITERATOR_ADAPTER(TTYPE, VTYPE) + +%typemap(javabody) CVC4::JavaIteratorAdapter %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; + } + + public $javaclassname(ExprManager em, $typemap(jstype, TTYPE) t) { + this(t); + this.em = em; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea +%typemap(javaconstruct) JavaIteratorAdapter<TTYPE, VTYPE> { + this(null, $imcall, true); +} + +%typemap(javaconstruct) CVC4::JavaIteratorAdapter<TTYPE, VTYPE> { + this(null, $imcall, true); +} + +%feature("valuewrapper") CVC4::JavaIteratorAdapter<TTYPE, VTYPE>; + +// the JavaIteratorAdapter should not be public, and implements Iterator +%typemap(javaclassmodifiers) CVC4::JavaIteratorAdapter<TTYPE, VTYPE> "class"; +%typemap(javainterfaces) CVC4::JavaIteratorAdapter< TTYPE, VTYPE > "java.util.Iterator<$typemap(jstype, VTYPE)>"; + +// add some functions to the Java side (do it here because there's no way to do these in C++) +%typemap(javacode) CVC4::JavaIteratorAdapter<TTYPE, VTYPE> " + public void remove() { + throw new java.lang.UnsupportedOperationException(); + } + + public $typemap(jstype, VTYPE) next() { + if(hasNext()) { + return getNext(); + } else { + throw new java.util.NoSuchElementException(); + } + } +" + +// getNext() just allows C++ iterator access from Java-side next(), make it private +%javamethodmodifiers CVC4::JavaIteratorAdapter<TTYPE, VTYPE>::getNext() "private"; + +%javamethodmodifiers CVC4::JavaIteratorAdapter<TTYPE, VTYPE>::JavaIteratorAdapter(const TTYPE& t) "private"; + +%enddef + +%include "bindings/java_iterator_adapter.h" + +namespace CVC4 { + template<class T, class V> class JavaIteratorAdapter { + SWIG_JAVA_ITERATOR_ADAPTER(T, V) + }; +} + +#endif diff --git a/src/bindings/java_stream_adapters.h b/src/bindings/java_stream_adapters.h index f2e89c004..2f3c8093f 100644 --- a/src/bindings/java_stream_adapters.h +++ b/src/bindings/java_stream_adapters.h @@ -2,9 +2,9 @@ /*! \file java_stream_adapters.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/bindings/swig.h b/src/bindings/swig.h index 81f197d5f..ed401ad18 100644 --- a/src/bindings/swig.h +++ b/src/bindings/swig.h @@ -2,9 +2,9 @@ /*! \file swig.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli + ** Morgan Deters, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/backtrackable.h b/src/context/backtrackable.h index 85281e7fa..78d73106d 100644 --- a/src/context/backtrackable.h +++ b/src/context/backtrackable.h @@ -2,9 +2,9 @@ /*! \file backtrackable.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cddense_set.h b/src/context/cddense_set.h index 4d48bf5d9..d9e52c29b 100644 --- a/src/context/cddense_set.h +++ b/src/context/cddense_set.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdhashmap.h b/src/context/cdhashmap.h index fc42c0e85..c98b0f7f0 100644 --- a/src/context/cdhashmap.h +++ b/src/context/cdhashmap.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdhashmap_forward.h b/src/context/cdhashmap_forward.h index 667e71990..6a30c3f3e 100644 --- a/src/context/cdhashmap_forward.h +++ b/src/context/cdhashmap_forward.h @@ -2,9 +2,9 @@ /*! \file cdhashmap_forward.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Dejan Jovanovic + ** Mathias Preiner, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdhashset.h b/src/context/cdhashset.h index 57cd101a9..9259eb388 100644 --- a/src/context/cdhashset.h +++ b/src/context/cdhashset.h @@ -2,9 +2,9 @@ /*! \file cdhashset.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Kshitij Bansal + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdhashset_forward.h b/src/context/cdhashset_forward.h index dbe8ff052..d7a43d459 100644 --- a/src/context/cdhashset_forward.h +++ b/src/context/cdhashset_forward.h @@ -2,9 +2,9 @@ /*! \file cdhashset_forward.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Dejan Jovanovic + ** Mathias Preiner, Tim King, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdinsert_hashmap.h b/src/context/cdinsert_hashmap.h index 0b3c713d2..2e55f53d1 100644 --- a/src/context/cdinsert_hashmap.h +++ b/src/context/cdinsert_hashmap.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdinsert_hashmap_forward.h b/src/context/cdinsert_hashmap_forward.h index a1559a078..fca2b5234 100644 --- a/src/context/cdinsert_hashmap_forward.h +++ b/src/context/cdinsert_hashmap_forward.h @@ -2,9 +2,9 @@ /*! \file cdinsert_hashmap_forward.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdlist.h b/src/context/cdlist.h index 95501df8e..e6b822dfd 100644 --- a/src/context/cdlist.h +++ b/src/context/cdlist.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdlist_forward.h b/src/context/cdlist_forward.h index 1cdbab7cb..febf9c839 100644 --- a/src/context/cdlist_forward.h +++ b/src/context/cdlist_forward.h @@ -2,9 +2,9 @@ /*! \file cdlist_forward.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdmaybe.h b/src/context/cdmaybe.h index 19827aabd..6b516e84d 100644 --- a/src/context/cdmaybe.h +++ b/src/context/cdmaybe.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdo.h b/src/context/cdo.h index b7d32d856..a3241c7e5 100644 --- a/src/context/cdo.h +++ b/src/context/cdo.h @@ -2,9 +2,9 @@ /*! \file cdo.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Clark Barrett, Tim King + ** Morgan Deters, Clark Barrett, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdqueue.h b/src/context/cdqueue.h index 079d2265c..54e553120 100644 --- a/src/context/cdqueue.h +++ b/src/context/cdqueue.h @@ -2,9 +2,9 @@ /*! \file cdqueue.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Francois Bobot, Morgan Deters + ** Tim King, Francois Bobot, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/cdtrail_queue.h b/src/context/cdtrail_queue.h index 4042c4223..bc8ff8da0 100644 --- a/src/context/cdtrail_queue.h +++ b/src/context/cdtrail_queue.h @@ -2,9 +2,9 @@ /*! \file cdtrail_queue.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/context.cpp b/src/context/context.cpp index e1de944fe..3c60316a7 100644 --- a/src/context/context.cpp +++ b/src/context/context.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Clark Barrett, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/context.h b/src/context/context.h index 2bfc83a43..a5c96c44e 100644 --- a/src/context/context.h +++ b/src/context/context.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Clark Barrett, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/context_mm.cpp b/src/context/context_mm.cpp index a9186f5f9..62c6a876d 100644 --- a/src/context/context_mm.cpp +++ b/src/context/context_mm.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Clark Barrett, Andres Noetzli, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/context/context_mm.h b/src/context/context_mm.h index 51726f36e..f450ed94e 100644 --- a/src/context/context_mm.h +++ b/src/context/context_mm.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Clark Barrett, Andres Noetzli, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/cvc4.i b/src/cvc4.i index 6b3598a2f..9fc8ed60e 100644 --- a/src/cvc4.i +++ b/src/cvc4.i @@ -1,3 +1,8 @@ +// Declare that all functions in the interface can throw exceptions of type +// CVC4::Exception and exceptions in general. SWIG catches those exceptions and +// turns them into target language exceptions via "throws" typemaps. +%catches(CVC4::Exception,...); + %import "bindings/swig.h" %include "stdint.i" @@ -35,6 +40,7 @@ using namespace CVC4; #include "smt/command.h" #include "util/bitvector.h" #include "util/floatingpoint.h" +#include "util/iand.h" #include "util/integer.h" #include "util/sexpr.h" #include "util/unsafe_interrupt_exception.h" @@ -47,23 +53,17 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters; #ifdef SWIGPYTHON %pythonappend CVC4::SmtEngine::SmtEngine %{ - # Hold a reference to the ExprManager to make sure that Python keeps the - # ExprManager alive as long as the SmtEngine exists - self.em = em + self.thisown = 0 +%} +%pythonappend CVC4::ExprManager::ExprManager %{ + self.thisown = 0 %} #endif /* SWIGPYTHON */ -%template(vectorType) std::vector< CVC4::Type >; -%template(vectorExpr) std::vector< CVC4::Expr >; %template(vectorUnsignedInt) std::vector< unsigned int >; -%template(vectorVectorExpr) std::vector< std::vector< CVC4::Expr > >; -%template(vectorDatatypeType) std::vector< CVC4::DatatypeType >; %template(vectorSExpr) std::vector< CVC4::SExpr >; %template(vectorString) std::vector< std::string >; -%template(vectorPairStringType) std::vector< std::pair< std::string, CVC4::Type > >; -%template(pairStringType) std::pair< std::string, CVC4::Type >; %template(setOfType) std::set< CVC4::Type >; -%template(hashmapExpr) std::unordered_map< CVC4::Expr, CVC4::Expr, CVC4::ExprHashFunction >; // This is unfortunate, but seems to be necessary; if we leave NULL // defined, swig will expand it to "(void*) 0", and some of swig's @@ -72,81 +72,19 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters; #ifdef SWIGJAVA -#include "bindings/java_iterator_adapter.h" -#include "bindings/java_stream_adapters.h" - -%exception %{ - try { - $action - } catch(CVC4::Exception& e) { - std::stringstream ss; - ss << e.what() << ": " << e.getMessage(); - std::string explanation = ss.str(); - SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, explanation.c_str()); - } -%} - -// Create a mapping from C++ Exceptions to Java Exceptions. -// This is in a couple of throws typemaps, simply because it's sensitive to SWIG's concept of which namespace we're in. -%typemap(throws) Exception %{ - std::string name = "edu/stanford/CVC4/$1_type"; - /* - size_t i = name.find("::"); - if(i != std::string::npos) { - size_t j = name.rfind("::"); - assert(i <= j); - name.replace(i, j - i + 2, "/"); - } - */ - jclass clazz = jenv->FindClass(name.c_str()); - assert(clazz != NULL && jenv->ExceptionOccurred() == NULL); - jmethodID method = jenv->GetMethodID(clazz, "<init>", "(JZ)V"); - assert(method != NULL && jenv->ExceptionOccurred() == NULL); - jthrowable t = static_cast<jthrowable>(jenv->NewObject(clazz, method, reinterpret_cast<uintptr_t>(new $1_type($1)), true)); - assert(t != NULL && jenv->ExceptionOccurred() == NULL); - int status = jenv->Throw(t); - assert(status == 0); -%} -%typemap(throws) CVC4::Exception %{ - std::string name = "edu/stanford/$1_type"; - size_t i = name.find("::"); - if(i != std::string::npos) { - size_t j = name.rfind("::"); - assert(i <= j); - name.replace(i, j - i + 2, "/"); - } - jclass clazz = jenv->FindClass(name.c_str()); - assert(clazz != NULL && jenv->ExceptionOccurred() == NULL); - jmethodID method = jenv->GetMethodID(clazz, "<init>", "(JZ)V"); - assert(method != NULL && jenv->ExceptionOccurred() == NULL); - jthrowable t = static_cast<jthrowable>(jenv->NewObject(clazz, method, reinterpret_cast<uintptr_t>(new $1_type($1)), true)); - assert(t != NULL && jenv->ExceptionOccurred() == NULL); - int status = jenv->Throw(t); - assert(status == 0); -%} - -%typemap(throws) CVC4::ModalException = CVC4::Exception; -%typemap(throws) CVC4::LogicException = CVC4::Exception; -%typemap(throws) CVC4::OptionException = CVC4::Exception; -%typemap(throws) CVC4::IllegalArgumentException = CVC4::Exception; -%typemap(throws) CVC4::AssertionException = CVC4::Exception; - -%typemap(throws) CVC4::TypeCheckingException = CVC4::Exception; -%typemap(throws) CVC4::ScopeException = CVC4::Exception; -%typemap(throws) CVC4::IllegalArgumentException = CVC4::Exception; -%typemap(throws) IllegalArgumentException = Exception; -%typemap(throws) CVC4::AssertionException = CVC4::Exception; - -// TIM: Really unclear why both of these are required -%typemap(throws) CVC4::UnsafeInterruptException = CVC4::Exception; -%typemap(throws) UnsafeInterruptException = CVC4::Exception; -%typemap(throws) CVC4::parser::InputStreamException = CVC4::Exception; - -// Generate an error if the mapping from C++ CVC4 Exception to Java CVC4 Exception doesn't exist above -%typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE *, SWIGTYPE [], SWIGTYPE [ANY] %{ -#error "exception $1_type doesn't map to Java correctly---please edit src/cvc4.i and add it" -%} +// Map C++ exceptions of type CVC4::Exception to Java exceptions of type +// edu.stanford.CVC4.Exception +// +// As suggested in: +// http://www.swig.org/Doc3.0/SWIGDocumentation.html#Java_exception_typemap +%typemap(throws, throws="edu.stanford.CVC4.Exception") CVC4::Exception { + jclass excep = jenv->FindClass("edu/stanford/CVC4/Exception"); + if (excep) + jenv->ThrowNew(excep, $1.what()); + return $null; +} +%include "bindings/java_iterator_adapter.i" %include "java/typemaps.i" // primitive pointers and references %include "java/std_string.i" // map std::string to java.lang.String %include "java/arrays_java.i" // C arrays to Java arrays @@ -252,6 +190,8 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters; JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0); } +%include "bindings/java_stream_adapters.h" + #endif /* SWIGJAVA */ // TIM: @@ -267,6 +207,7 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters; %include "util/integer.i" %include "util/rational.i" %include "util/bitvector.i" +%include "util/iand.i" %include "util/floatingpoint.i" // Tim: The remainder of util/. @@ -287,8 +228,6 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters; %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" // TIM: @@ -300,6 +239,7 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters; // TIM: // The remainder of the includes: +%include "expr/datatype.i" %include "expr/expr.i" %include "expr/expr_manager.i" %include "expr/variable_type_map.i" @@ -309,5 +249,7 @@ std::set<JavaInputStreamAdapter*> CVC4::JavaInputStreamAdapter::s_adapters; %include "theory/logic_info.i" %include "theory/theory_id.i" +%include "expr/array_store_all.i" + // Tim: This should come after "theory/logic_info.i". %include "smt/smt_engine.i" diff --git a/src/decision/decision_attributes.h b/src/decision/decision_attributes.h index bdcc722ec..86939e3ce 100644 --- a/src/decision/decision_attributes.h +++ b/src/decision/decision_attributes.h @@ -2,9 +2,9 @@ /*! \file decision_attributes.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Kshitij Bansal + ** Mathias Preiner, Tim King, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/decision/decision_engine.cpp b/src/decision/decision_engine.cpp index 4ae900e85..2d150998a 100644 --- a/src/decision/decision_engine.cpp +++ b/src/decision/decision_engine.cpp @@ -2,9 +2,9 @@ /*! \file decision_engine.cpp ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal, Tim King, Andres Noetzli + ** Kshitij Bansal, Aina Niemetz, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/decision/decision_engine.h b/src/decision/decision_engine.h index 65ead8d4c..ec2c5ff63 100644 --- a/src/decision/decision_engine.h +++ b/src/decision/decision_engine.h @@ -2,9 +2,9 @@ /*! \file decision_engine.h ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal, Morgan Deters, Tim King + ** Kshitij Bansal, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/decision/decision_strategy.h b/src/decision/decision_strategy.h index f408515de..258bf860c 100644 --- a/src/decision/decision_strategy.h +++ b/src/decision/decision_strategy.h @@ -2,9 +2,9 @@ /*! \file decision_strategy.h ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal, Morgan Deters, Andres Noetzli + ** Kshitij Bansal, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/decision/justification_heuristic.cpp b/src/decision/justification_heuristic.cpp index ce79d6ca0..9787e8b00 100644 --- a/src/decision/justification_heuristic.cpp +++ b/src/decision/justification_heuristic.cpp @@ -2,9 +2,9 @@ /*! \file justification_heuristic.cpp ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal, Aina Niemetz, Tim King + ** Kshitij Bansal, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -40,10 +40,10 @@ JustificationHeuristic::JustificationHeuristic(CVC4::DecisionEngine* de, d_giveup("decision::jh::giveup", 0), d_timestat("decision::jh::time"), d_assertions(uc), - d_iteAssertions(uc), - d_iteCache(uc), + d_skolemAssertions(uc), + d_skolemCache(uc), d_visited(), - d_visitedComputeITE(), + d_visitedComputeSkolems(), d_curDecision(), d_curThreshold(0), d_childCache(uc), @@ -175,10 +175,26 @@ void JustificationHeuristic::addAssertions( << " assertionsEnd = " << assertionsEnd << std::endl; - // Save the 'real' assertions locally - for (size_t i = 0; i < assertionsEnd; i++) + // Save all assertions locally, including the assertions generated by term + // removal. We have to make sure that we assign a value to all the Boolean + // term variables. To illustrate why this is, consider the case where we have + // a single assertion + // + // (or (f a) (f b)) + // + // where `f` is a function `Bool -> Bool`. Given an assignment: + // + // (f a) -> true + // (f b) -> false + // a -> false + // + // UF will not complain and the justification heuristic considers the + // assertion to be satisifed. However, we also have to make sure that we pick + // a value for `b` that is not in conflict with the other assignments (we can + // only choose `b` to be `true` otherwise the model is incorrect). + for (const Node& assertion : assertions) { - d_assertions.push_back(assertions[i]); + d_assertions.push_back(assertion); } // Save mapping between ite skolems and ite assertions @@ -188,7 +204,7 @@ void JustificationHeuristic::addAssertions( << assertions[(i.second)] << std::endl; Assert(i.second >= assertionsEnd && i.second < assertions.size()); - d_iteAssertions[i.first] = assertions[i.second]; + d_skolemAssertions[i.first] = assertions[i.second]; } // Automatic weight computation @@ -363,36 +379,39 @@ SatValue JustificationHeuristic::tryGetSatValue(Node n) }//end of else } -JustificationHeuristic::IteList -JustificationHeuristic::getITEs(TNode n) +JustificationHeuristic::SkolemList JustificationHeuristic::getSkolems(TNode n) { - IteCache::iterator it = d_iteCache.find(n); - if(it != d_iteCache.end()) { + SkolemCache::iterator it = d_skolemCache.find(n); + if (it != d_skolemCache.end()) + { return (*it).second; - } else { - // Compute the list of ITEs - // TODO: optimize by avoiding multiple lookup for d_iteCache[n] - d_visitedComputeITE.clear(); - IteList ilist; - computeITEs(n, ilist); - d_iteCache.insert(n, ilist); + } + else + { + // Compute the list of Skolems + // TODO: optimize by avoiding multiple lookup for d_skolemCache[n] + d_visitedComputeSkolems.clear(); + SkolemList ilist; + computeSkolems(n, ilist); + d_skolemCache.insert(n, ilist); return ilist; } } -void JustificationHeuristic::computeITEs(TNode n, IteList &l) +void JustificationHeuristic::computeSkolems(TNode n, SkolemList& l) { - Trace("decision::jh::ite") << " computeITEs( " << n << ", &l)\n"; - d_visitedComputeITE.insert(n); + Trace("decision::jh::skolems") << " computeSkolems( " << n << ", &l)\n"; + d_visitedComputeSkolems.insert(n); for(unsigned i=0; i<n.getNumChildren(); ++i) { - SkolemMap::iterator it2 = d_iteAssertions.find(n[i]); - if(it2 != d_iteAssertions.end()) { + SkolemMap::iterator it2 = d_skolemAssertions.find(n[i]); + if (it2 != d_skolemAssertions.end()) + { l.push_back(make_pair(n[i], (*it2).second)); Assert(n[i].getNumChildren() == 0); } - if(d_visitedComputeITE.find(n[i]) == - d_visitedComputeITE.end()) { - computeITEs(n[i], l); + if (d_visitedComputeSkolems.find(n[i]) == d_visitedComputeSkolems.end()) + { + computeSkolems(n[i], l); } } } @@ -470,9 +489,8 @@ JustificationHeuristic::findSplitterRec(TNode node, SatValue desiredVal) * If not in theory of booleans, check if this is something to split-on. */ if(isAtom) { - // if node has embedded ites, resolve that first - if(handleEmbeddedITEs(node) == FOUND_SPLITTER) - return FOUND_SPLITTER; + // if node has embedded skolems due to term removal, resolve that first + if (handleEmbeddedSkolems(node) == FOUND_SPLITTER) return FOUND_SPLITTER; if(litVal != SAT_VALUE_UNKNOWN) { Assert(litVal == desiredVal); @@ -700,13 +718,15 @@ JustificationHeuristic::SearchResult JustificationHeuristic::handleITE(TNode nod }// else (...ifVal...) } -JustificationHeuristic::SearchResult JustificationHeuristic::handleEmbeddedITEs(TNode node) +JustificationHeuristic::SearchResult +JustificationHeuristic::handleEmbeddedSkolems(TNode node) { - const IteList l = getITEs(node); - Trace("decision::jh::ite") << " ite size = " << l.size() << std::endl; + const SkolemList l = getSkolems(node); + Trace("decision::jh::skolems") << " skolems size = " << l.size() << std::endl; bool noSplitter = true; - for(IteList::const_iterator i = l.begin(); i != l.end(); ++i) { + for (SkolemList::const_iterator i = l.begin(); i != l.end(); ++i) + { if(d_visited.find((*i).first) == d_visited.end()) { d_visited.insert((*i).first); SearchResult ret = findSplitterRec((*i).second, SAT_VALUE_TRUE); diff --git a/src/decision/justification_heuristic.h b/src/decision/justification_heuristic.h index bb426ad1e..e45dd2bef 100644 --- a/src/decision/justification_heuristic.h +++ b/src/decision/justification_heuristic.h @@ -2,9 +2,9 @@ /*! \file justification_heuristic.h ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal, Tim King, Morgan Deters + ** Kshitij Bansal, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -42,8 +42,8 @@ class JustificationHeuristic : public ITEDecisionStrategy { // TRUE FALSE MEH enum SearchResult {FOUND_SPLITTER, NO_SPLITTER, DONT_KNOW}; - typedef std::vector<pair<TNode,TNode> > IteList; - typedef context::CDHashMap<TNode,IteList,TNodeHashFunction> IteCache; + typedef std::vector<pair<TNode, TNode> > SkolemList; + typedef context::CDHashMap<TNode, SkolemList, TNodeHashFunction> SkolemCache; typedef std::vector<TNode> ChildList; typedef context::CDHashMap<TNode,pair<ChildList,ChildList>,TNodeHashFunction> ChildCache; typedef context::CDHashMap<TNode,TNode,TNodeHashFunction> SkolemMap; @@ -63,18 +63,19 @@ class JustificationHeuristic : public ITEDecisionStrategy { /** * A copy of the assertions that need to be justified - * directly. Doesn't have ones introduced during during ITE-removal. + * directly. Doesn't have ones introduced during during term removal. */ context::CDList<TNode> d_assertions; //TNode is fine since decisionEngine has them too - /** map from ite-rewrite skolem to a boolean-ite assertion */ - SkolemMap d_iteAssertions; + /** map from skolems introduced in term removal to the corresponding assertion + */ + SkolemMap d_skolemAssertions; // 'key' being TNode is fine since if a skolem didn't exist anywhere, // we won't look it up. as for 'value', same reason as d_assertions - /** Cache for ITE skolems present in a atomic formula */ - IteCache d_iteCache; + /** Cache for skolems present in a atomic formula */ + SkolemCache d_skolemCache; /** * This is used to prevent infinite loop when trying to find a @@ -84,10 +85,10 @@ class JustificationHeuristic : public ITEDecisionStrategy { std::unordered_set<TNode,TNodeHashFunction> d_visited; /** - * Set to track visited nodes in a dfs search done in computeITE + * Set to track visited nodes in a dfs search done in computeSkolems * function */ - std::unordered_set<TNode,TNodeHashFunction> d_visitedComputeITE; + std::unordered_set<TNode, TNodeHashFunction> d_visitedComputeSkolems; /** current decision for the recursive call */ SatLiteral d_curDecision; @@ -153,8 +154,7 @@ public: SatValue tryGetSatValue(Node n); /* Get list of all term-ITEs for the atomic formula v */ - JustificationHeuristic::IteList getITEs(TNode n); - + JustificationHeuristic::SkolemList getSkolems(TNode n); /** * For big and/or nodes, a cache to save starting index into children @@ -165,8 +165,8 @@ public: int getStartIndex(TNode node); void saveStartIndex(TNode node, int val); - /* Compute all term-ITEs in a node recursively */ - void computeITEs(TNode n, IteList &l); + /* Compute all term-removal skolems in a node recursively */ + void computeSkolems(TNode n, SkolemList& l); SearchResult handleAndOrEasy(TNode node, SatValue desiredVal); SearchResult handleAndOrHard(TNode node, SatValue desiredVal); @@ -175,7 +175,7 @@ public: SearchResult handleBinaryHard(TNode node1, SatValue desiredVal1, TNode node2, SatValue desiredVal2); SearchResult handleITE(TNode node, SatValue desiredVal); - SearchResult handleEmbeddedITEs(TNode node); + SearchResult handleEmbeddedSkolems(TNode node); };/* class JustificationHeuristic */ }/* namespace decision */ diff --git a/src/expr/CMakeLists.txt b/src/expr/CMakeLists.txt index 413041213..5173c076d 100644 --- a/src/expr/CMakeLists.txt +++ b/src/expr/CMakeLists.txt @@ -15,6 +15,8 @@ libcvc4_add_sources( expr_sequence.cpp expr_sequence.h kind_map.h + lazy_proof.cpp + lazy_proof.h match_trie.cpp match_trie.h node.cpp @@ -41,20 +43,28 @@ libcvc4_add_sources( proof.h proof_checker.cpp proof_checker.h + proof_generator.cpp + proof_generator.h proof_node.cpp proof_node.h + proof_node_algorithm.cpp + proof_node_algorithm.h proof_node_to_sexpr.cpp proof_node_to_sexpr.h proof_node_manager.cpp proof_node_manager.h proof_rule.cpp proof_rule.h - proof_skolem_cache.cpp - proof_skolem_cache.h + proof_step_buffer.cpp + proof_step_buffer.h + skolem_manager.cpp + skolem_manager.h symbol_table.cpp symbol_table.h term_canonize.cpp term_canonize.h + term_conversion_proof_generator.cpp + term_conversion_proof_generator.h type.cpp type.h type_checker.h diff --git a/src/expr/array.h b/src/expr/array.h index a53ac3cd2..5bfd39844 100644 --- a/src/expr/array.h +++ b/src/expr/array.h @@ -2,9 +2,9 @@ /*! \file array.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/array_store_all.cpp b/src/expr/array_store_all.cpp index f2d9a35a9..6655c7b61 100644 --- a/src/expr/array_store_all.cpp +++ b/src/expr/array_store_all.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/array_store_all.h b/src/expr/array_store_all.h index 0adcfde36..2d251257c 100644 --- a/src/expr/array_store_all.h +++ b/src/expr/array_store_all.h @@ -2,9 +2,9 @@ /*! \file array_store_all.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/array_store_all.i b/src/expr/array_store_all.i index b66e4a178..5158a21d9 100644 --- a/src/expr/array_store_all.i +++ b/src/expr/array_store_all.i @@ -2,15 +2,63 @@ #include "expr/array_store_all.h" %} +#ifdef SWIGJAVA + +%typemap(javabody) CVC4::ArrayStoreAll %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + public $javaclassname(ExprManager em, ArrayType type, Expr expr) { + this(type, expr); + this.em = em; + } +%} + +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea +%typemap(javaconstruct) ArrayStoreAll { + this(null, $imcall, true); +} + +%typemap(javaconstruct) CVC4::ArrayStoreAll { + this(null, $imcall, true); +} + +%typemap(javaout) const CVC4::Expr& { + return new Expr(this.em, $jnicall, false); +} + +%typemap(javaout) const CVC4::ArrayType& { + return new ArrayType(this.em, $jnicall, false); +} + +%typemap(javaout) const CVC4::ArrayStoreAll& { + return new ArrayStoreAll(this.em, $jnicall, false); +} + +%javamethodmodifiers CVC4::ArrayStoreAll::ArrayStoreAll(const ArrayType& type, const Expr& expr) "private"; + +#endif /* SWIGJAVA */ + +%ignore CVC4::ArrayStoreAll::ArrayStoreAll(const ArrayStoreAll& other); %rename(equals) CVC4::ArrayStoreAll::operator==(const ArrayStoreAll&) const; %ignore CVC4::ArrayStoreAll::operator!=(const ArrayStoreAll&) const; +%ignore CVC4::ArrayStoreAll::operator=(const ArrayStoreAll&); %rename(less) CVC4::ArrayStoreAll::operator<(const ArrayStoreAll&) const; %rename(lessEqual) CVC4::ArrayStoreAll::operator<=(const ArrayStoreAll&) const; %rename(greater) CVC4::ArrayStoreAll::operator>(const ArrayStoreAll&) const; %rename(greaterEqual) CVC4::ArrayStoreAll::operator>=(const ArrayStoreAll&) const; - %rename(apply) CVC4::ArrayStoreAllHashFunction::operator()(const ArrayStoreAll&) const; - %ignore CVC4::operator<<(std::ostream&, const ArrayStoreAll&); %include "expr/type.i" diff --git a/src/expr/ascription_type.h b/src/expr/ascription_type.h index 94258896a..743d779ef 100644 --- a/src/expr/ascription_type.h +++ b/src/expr/ascription_type.h @@ -2,9 +2,9 @@ /*! \file ascription_type.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/ascription_type.i b/src/expr/ascription_type.i index 57d8f97fe..c2499c00e 100644 --- a/src/expr/ascription_type.i +++ b/src/expr/ascription_type.i @@ -2,6 +2,42 @@ #include "expr/ascription_type.h" %} +#ifdef SWIGJAVA + +%typemap(javabody) CVC4::AscriptionType %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; // keep ref to em in SWIG proxy class + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + public $javaclassname(ExprManager em, Type t) { + this(t); + this.em = em; + } +%} + +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea +%typemap(javaconstruct) AscriptionType { + this(null, $imcall, true); +} + +%typemap(javaconstruct) CVC4::AscriptionType { + this(null, $imcall, true); +} + +%javamethodmodifiers CVC4::AscriptionType::AscriptionType(Type t) "private"; + +#endif + %rename(equals) CVC4::AscriptionType::operator==(const AscriptionType&) const; %ignore CVC4::AscriptionType::operator!=(const AscriptionType&) const; diff --git a/src/expr/attribute.cpp b/src/expr/attribute.cpp index 553c19f6e..db05dc7e9 100644 --- a/src/expr/attribute.cpp +++ b/src/expr/attribute.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Dejan Jovanovic, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/attribute.h b/src/expr/attribute.h index 44bf7aae5..9fa4b8a84 100644 --- a/src/expr/attribute.h +++ b/src/expr/attribute.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/attribute_internals.h b/src/expr/attribute_internals.h index 94d51b188..c2441d539 100644 --- a/src/expr/attribute_internals.h +++ b/src/expr/attribute_internals.h @@ -2,9 +2,9 @@ /*! \file attribute_internals.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Dejan Jovanovic + ** Morgan Deters, Tim King, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/attribute_unique_id.h b/src/expr/attribute_unique_id.h index 88ecc90a8..7cd93c1f3 100644 --- a/src/expr/attribute_unique_id.h +++ b/src/expr/attribute_unique_id.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/datatype.cpp b/src/expr/datatype.cpp index 3925e1434..5a48a0220 100644 --- a/src/expr/datatype.cpp +++ b/src/expr/datatype.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -406,6 +406,12 @@ bool Datatype::isWellFounded() const return d_internal->isWellFounded(); } +bool Datatype::hasNestedRecursion() const +{ + ExprManagerScope ems(d_self); + return d_internal->hasNestedRecursion(); +} + Expr Datatype::mkGroundTerm(Type t) const { PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved"); diff --git a/src/expr/datatype.h b/src/expr/datatype.h index 0f99499ce..0da4c9f51 100644 --- a/src/expr/datatype.h +++ b/src/expr/datatype.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -705,6 +705,12 @@ class CVC4_PUBLIC Datatype { * This datatype must be resolved or an exception is thrown. */ bool isWellFounded() const; + /** has nested recursion + * + * Return true iff this datatype has nested recursion. + * This datatype must be resolved or an exception is thrown. + */ + bool hasNestedRecursion() const; /** is recursive singleton * diff --git a/src/expr/datatype.i b/src/expr/datatype.i index 1ac89efcb..56dd6dad4 100644 --- a/src/expr/datatype.i +++ b/src/expr/datatype.i @@ -1,93 +1,183 @@ %{ #include "expr/datatype.h" - -#ifdef SWIGJAVA - -#include "bindings/java_iterator_adapter.h" -#include "bindings/java_stream_adapters.h" - -#endif /* SWIGJAVA */ %} -%include "expr/kind.i" - -%extend std::vector< CVC4::Datatype > { - %ignore vector(size_type);// java/python/perl/others? - %ignore resize(size_type);// java/python/perl/others? - %ignore set(int i, const CVC4::Datatype& x); - %ignore to_array(); -}; -%template(vectorDatatype) std::vector< CVC4::Datatype >; - -%extend std::vector< CVC4::DatatypeConstructor > { - %ignore vector(size_type);// java/python/perl/others? - %ignore resize(size_type);// java/python/perl/others? - %ignore set(int i, const CVC4::Datatype::Constructor& x); - %ignore to_array(); -}; -//%template(vectorDatatypeConstructor) std::vector< CVC4::DatatypeConstructor >; - -%rename(equals) CVC4::Datatype::operator==(const Datatype&) const; +%ignore CVC4::Datatype::setRecord(); +%ignore CVC4::Datatype::isRecord() const; +%ignore CVC4::Datatype::getRecord() const; %ignore CVC4::Datatype::operator!=(const Datatype&) const; - %ignore CVC4::Datatype::begin(); %ignore CVC4::Datatype::end(); %ignore CVC4::Datatype::begin() const; %ignore CVC4::Datatype::end() const; - +%ignore CVC4::Datatype::getConstructors() const; +%rename(equals) CVC4::Datatype::operator==(const Datatype&) const; %rename(get) CVC4::Datatype::operator[](size_t) const; %rename(get) CVC4::Datatype::operator[](std::string) const; +%ignore CVC4::SygusPrintCallback; + %rename(apply) CVC4::DatatypeHashFunction::operator()(const Datatype&) const; %ignore CVC4::DatatypeHashFunction::operator()(const Datatype*) const; %rename(apply) CVC4::DatatypeHashFunction::operator()(const DatatypeConstructor&) const; %ignore CVC4::DatatypeHashFunction::operator()(const DatatypeConstructor*) const; +%ignore CVC4::DatatypeConstructor::DatatypeConstructor(); %ignore CVC4::DatatypeConstructor::begin(); %ignore CVC4::DatatypeConstructor::end(); %ignore CVC4::DatatypeConstructor::begin() const; %ignore CVC4::DatatypeConstructor::end() const; - %rename(get) CVC4::DatatypeConstructor::operator[](size_t) const; %rename(get) CVC4::DatatypeConstructor::operator[](std::string) const; %ignore CVC4::operator<<(std::ostream&, const Datatype&); %ignore CVC4::operator<<(std::ostream&, const DatatypeConstructor&); %ignore CVC4::operator<<(std::ostream&, const DatatypeConstructorArg&); +%ignore CVC4::operator<<(std::ostream& out, const DatatypeIndexConstant& es); %ignore CVC4::DatatypeConstructorIterator; %ignore CVC4::DatatypeConstructorArgIterator; -%feature("valuewrapper") CVC4::DatatypeUnresolvedType; -%feature("valuewrapper") CVC4::DatatypeConstructor; - - -%rename(equals) CVC4::DatatypeIndexConstant::operator==(const DatatypeIndexConstant&) const; %ignore CVC4::DatatypeIndexConstant::operator!=(const DatatypeIndexConstant&) const; - +%rename(equals) CVC4::DatatypeIndexConstant::operator==(const DatatypeIndexConstant&) const; %rename(less) CVC4::DatatypeIndexConstant::operator<(const DatatypeIndexConstant&) const; %rename(lessEqual) CVC4::DatatypeIndexConstant::operator<=(const DatatypeIndexConstant&) const; %rename(greater) CVC4::DatatypeIndexConstant::operator>(const DatatypeIndexConstant&) const; %rename(greaterEqual) CVC4::DatatypeIndexConstant::operator>=(const DatatypeIndexConstant&) const; - %rename(apply) CVC4::DatatypeIndexConstantFunction::operator()(const DatatypeIndexConstant&) const; -%ignore CVC4::operator<<(std::ostream& out, const DatatypeIndexConstant& es); +#ifdef SWIGJAVA +%typemap(javaout) CVC4::Expr { + return new Expr(this.em, $jnicall, true); +} -#ifdef SWIGJAVA +%typemap(javaout) CVC4::DatatypeType { + return new DatatypeType(this.em, $jnicall, true); +} + +%typemap(javabody) CVC4::Datatype %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + public static $javaclassname datatypeOf(Expr item) throws edu.stanford.CVC4.Exception { + $javaclassname result = datatypeOfInternal(item); + result.em = item.getExprManager(); + return result; + } + + public JavaIteratorAdapter_Datatype iterator() { + return new JavaIteratorAdapter_Datatype(this.em, this); + } +%} + +%javamethodmodifiers CVC4::Datatype::datatypeOf(Expr item) "private"; +%rename(datatypeOfInternal) CVC4::Datatype::datatypeOf(Expr item); + +%include "bindings/java/cvc4_std_vector.i" + +SWIG_STD_VECTOR_EM(CVC4::Datatype, const CVC4::Datatype&) -// Instead of Datatype::begin() and end(), create an -// iterator() method on the Java side that returns a Java-style -// Iterator. %extend CVC4::Datatype { - CVC4::JavaIteratorAdapter<CVC4::Datatype, CVC4::DatatypeConstructor> - iterator() - { - return CVC4::JavaIteratorAdapter<CVC4::Datatype, CVC4::DatatypeConstructor>( - *$self); +%typemap(javaout) const CVC4::Datatype& { + return new Datatype(null, $jnicall, false); +} +} + +%typemap(javaout) CVC4::Datatype { + return new Datatype(this.em, $jnicall, true); +} +%typemap(javaout) const CVC4::Datatype& { + return new Datatype(this.em, $jnicall, false); +} +%template(vectorDatatype) std::vector<CVC4::Datatype>; + +%typemap(javaout) typeVector { + return new typeVector(this.em, $jnicall, true); +} + +%typemap(javaout) const CVC4::DatatypeConstructor& { + return new DatatypeConstructor(this.em, $jnicall, false); +} + +%typemap(javabody) CVC4::DatatypeConstructor %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + public DatatypeConstructor(ExprManager em, String name) { + this(name); + this.em = em; + } + + public DatatypeConstructor(ExprManager em, String name, long weight) { + this(name, weight); + this.em = em; + } + + public JavaIteratorAdapter_DatatypeConstructor iterator() { + return new JavaIteratorAdapter_DatatypeConstructor(this.em, this); + } +%} + +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea +%typemap(javaconstruct) DatatypeConstructor { + this(null, $imcall, true); +} + +%typemap(javaconstruct) CVC4::DatatypeConstructor { + this(null, $imcall, true); +} + +%javamethodmodifiers CVC4::DatatypeConstructor::DatatypeConstructor(std::string) "private"; +%javamethodmodifiers CVC4::DatatypeConstructor::DatatypeConstructor(std::string, unsigned weight) "private"; + +%typemap(javaout) const CVC4::DatatypeConstructorArg& { + return new DatatypeConstructorArg(this.em, $jnicall, false); +} + +%typemap(javabody) CVC4::DatatypeConstructorArg %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; } + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javaout) CVC4::SelectorType { + return new SelectorType(this.em, $jnicall, true); +} + +%extend CVC4::Datatype { std::string toString() const { std::stringstream ss; ss << *$self; @@ -95,14 +185,6 @@ } } %extend CVC4::DatatypeConstructor { - CVC4::JavaIteratorAdapter<CVC4::DatatypeConstructor, - CVC4::DatatypeConstructorArg> - iterator() - { - return CVC4::JavaIteratorAdapter<CVC4::DatatypeConstructor, - CVC4::DatatypeConstructorArg>(*$self); - } - std::string toString() const { std::stringstream ss; ss << *$self; @@ -117,56 +199,28 @@ } } -// Datatype is "iterable" on the Java side -%typemap(javainterfaces) CVC4::Datatype "java.lang.Iterable<DatatypeConstructor>"; -%typemap(javainterfaces) CVC4::DatatypeConstructor "java.lang.Iterable<DatatypeConstructorArg>"; - -// the JavaIteratorAdapter should not be public, and implements Iterator -%typemap(javaclassmodifiers) CVC4::JavaIteratorAdapter<CVC4::Datatype, CVC4::DatatypeConstructor> "class"; -%typemap(javaclassmodifiers) CVC4::JavaIteratorAdapter<CVC4::DatatypeConstructor, CVC4::DatatypeConstructorArg> "class"; -%typemap(javainterfaces) CVC4::JavaIteratorAdapter<CVC4::Datatype, CVC4::DatatypeConstructor> "java.util.Iterator<DatatypeConstructor>"; -%typemap(javainterfaces) CVC4::JavaIteratorAdapter<CVC4::DatatypeConstructor, CVC4::DatatypeConstructorArg> "java.util.Iterator<DatatypeConstructorArg>"; -// add some functions to the Java side (do it here because there's no way to do these in C++) -%typemap(javacode) CVC4::JavaIteratorAdapter<CVC4::Datatype, CVC4::DatatypeConstructor> " - public void remove() { - throw new java.lang.UnsupportedOperationException(); - } - - public DatatypeConstructor next() { - if(hasNext()) { - return getNext(); - } else { - throw new java.util.NoSuchElementException(); - } - } -" -%typemap(javacode) CVC4::JavaIteratorAdapter<CVC4::DatatypeConstructor, CVC4::DatatypeConstructorArg> " - public void remove() { - throw new java.lang.UnsupportedOperationException(); - } - - public DatatypeConstructorArg next() { - if(hasNext()) { - return getNext(); - } else { - throw new java.util.NoSuchElementException(); - } - } -" -// getNext() just allows C++ iterator access from Java-side next(), make it private -%javamethodmodifiers CVC4::JavaIteratorAdapter<CVC4::Datatype, CVC4::DatatypeConstructor>::getNext() "private"; -%javamethodmodifiers CVC4::JavaIteratorAdapter<CVC4::DatatypeConstructor, CVC4::DatatypeConstructorArg>::getNext() "private"; - -#endif /* SWIGJAVA */ +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea +%typemap(javaconstruct) Datatype { + this(null, $imcall, true); +} -%include "expr/datatype.h" +%typemap(javaconstruct) CVC4::Datatype { + this(em, $imcall, true); +} -#ifdef SWIGJAVA +%typemap(javaout) CVC4::DatatypeConstructor { + return new DatatypeConstructor(this.em, $jnicall, true); +} -%include "bindings/java_iterator_adapter.h" -%include "bindings/java_stream_adapters.h" +%typemap(javaout) CVC4::DatatypeConstructorArg { + return new DatatypeConstructorArg(this.em, $jnicall, true); +} +SWIG_JAVA_ITERATOR_ADAPTER(CVC4::Datatype, CVC4::DatatypeConstructor) %template(JavaIteratorAdapter_Datatype) CVC4::JavaIteratorAdapter<CVC4::Datatype, CVC4::DatatypeConstructor>; +SWIG_JAVA_ITERATOR_ADAPTER(CVC4::DatatypeConstructor, CVC4::DatatypeConstructorArg) %template(JavaIteratorAdapter_DatatypeConstructor) CVC4::JavaIteratorAdapter<CVC4::DatatypeConstructor, CVC4::DatatypeConstructorArg>; #endif /* SWIGJAVA */ + +%include "expr/datatype.h" diff --git a/src/expr/dtype.cpp b/src/expr/dtype.cpp index f16b193ce..220e12c42 100644 --- a/src/expr/dtype.cpp +++ b/src/expr/dtype.cpp @@ -2,9 +2,9 @@ /*! \file dtype.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -14,6 +14,7 @@ #include "expr/dtype.h" #include "expr/node_algorithm.h" +#include "expr/type_matcher.h" using namespace CVC4::kind; @@ -32,7 +33,8 @@ DType::DType(std::string name, bool isCo) d_sygusAllowConst(false), d_sygusAllowAll(false), d_card(CardinalityUnknown()), - d_wellFounded(0) + d_wellFounded(0), + d_nestedRecursion(0) { } @@ -49,7 +51,8 @@ DType::DType(std::string name, const std::vector<TypeNode>& params, bool isCo) d_sygusAllowConst(false), d_sygusAllowAll(false), d_card(CardinalityUnknown()), - d_wellFounded(0) + d_wellFounded(0), + d_nestedRecursion(0) { } @@ -471,21 +474,26 @@ bool DType::isInterpretedFinite() const bool DType::isWellFounded() const { - Trace("datatypes-init") << "DType::isWellFounded " << std::endl; Assert(isResolved()); - if (d_wellFounded == 0) + if (d_wellFounded != 0) { - std::vector<TypeNode> processing; - if (computeWellFounded(processing)) - { - d_wellFounded = 1; - } - else - { - d_wellFounded = -1; - } + // already computed + return d_wellFounded == 1; } - return d_wellFounded == 1; + Trace("datatypes-init") << "DType::isWellFounded " << getName() << std::endl; + std::vector<TypeNode> processing; + if (!computeWellFounded(processing)) + { + // not well-founded since no ground term can be constructed + Trace("datatypes-init") << "DType::isWellFounded: false for " << getName() + << " due to no ground terms." << std::endl; + d_wellFounded = -1; + return false; + } + Trace("datatypes-init") << "DType::isWellFounded: true for " << getName() + << std::endl; + d_wellFounded = 1; + return true; } bool DType::computeWellFounded(std::vector<TypeNode>& processing) const @@ -557,6 +565,137 @@ Node DType::mkGroundTermInternal(TypeNode t, bool isValue) const return groundTerm; } +void DType::getAlienSubfieldTypes( + std::unordered_set<TypeNode, TypeNodeHashFunction>& types, + std::map<TypeNode, bool>& processed, + bool isAlienPos) const +{ + std::map<TypeNode, bool>::iterator it = processed.find(d_self); + if (it != processed.end()) + { + if (it->second || (!isAlienPos && !it->second)) + { + // already processed as an alien subfield type, or already processed + // as a non-alien subfield type and isAlienPos is false. + return; + } + } + processed[d_self] = isAlienPos; + for (std::shared_ptr<DTypeConstructor> ctor : d_constructors) + { + for (unsigned j = 0, nargs = ctor->getNumArgs(); j < nargs; ++j) + { + TypeNode tn = ctor->getArgType(j); + if (tn.isDatatype()) + { + // special case for datatypes, we must recurse to collect subfield types + if (!isAlienPos) + { + // since we aren't adding it to types below, we add its alien + // subfield types here. + const DType& dt = tn.getDType(); + dt.getAlienSubfieldTypes(types, processed, false); + } + if (tn.isParametricDatatype() && !isAlienPos) + { + // (instantiated) parametric datatypes have an AST structure: + // (PARAMETRIC_DATATYPE D T1 ... Tn) + // where D is the uninstantiated datatype type. We should not view D + // as an alien subfield type of tn. Thus, we need a special case here + // which ignores the first child, when isAlienPos is false. + for (unsigned i = 1, nchild = tn.getNumChildren(); i < nchild; i++) + { + expr::getComponentTypes(tn[i], types); + } + continue; + } + } + // we are in a case where tn is not a datatype, we add all (alien) + // component types to types below. + bool hasTn = types.find(tn) != types.end(); + Trace("datatypes-init") + << "Collect subfield types " << tn << ", hasTn=" << hasTn + << ", isAlienPos=" << isAlienPos << std::endl; + expr::getComponentTypes(tn, types); + if (!isAlienPos && !hasTn) + { + // the top-level type is added by getComponentTypes, so remove it if it + // was not already listed in types + Assert(types.find(tn) != types.end()); + types.erase(tn); + } + } + } + // Now, go back and add all alien subfield types from datatypes if + // not done so already. This is because getComponentTypes does not + // recurse into subfield types of datatypes. + for (const TypeNode& sstn : types) + { + if (sstn.isDatatype()) + { + const DType& dt = sstn.getDType(); + dt.getAlienSubfieldTypes(types, processed, true); + } + } +} + +bool DType::hasNestedRecursion() const +{ + if (d_nestedRecursion != 0) + { + return d_nestedRecursion == 1; + } + Trace("datatypes-init") << "Compute simply recursive for " << getName() + << std::endl; + // get the alien subfield types of this datatype + std::unordered_set<TypeNode, TypeNodeHashFunction> types; + std::map<TypeNode, bool> processed; + getAlienSubfieldTypes(types, processed, false); + if (Trace.isOn("datatypes-init")) + { + Trace("datatypes-init") << "Alien subfield types: " << std::endl; + for (const TypeNode& t : types) + { + Trace("datatypes-init") << "- " << t << std::endl; + } + } + // does types contain self? + if (types.find(d_self) != types.end()) + { + Trace("datatypes-init") + << "DType::hasNestedRecursion: true for " << getName() + << " due to alien subfield type" << std::endl; + // has nested recursion since it has itself as an alien subfield type. + d_nestedRecursion = 1; + return true; + } + // If it is parametric, this type may match with an alien subfield type (e.g. + // we may have a field (T Int) for parametric datatype (T x) where x + // is a type parameter). Thus, we check whether the self type matches any + // alien subfield type using the TypeMatcher utility. + if (isParametric()) + { + for (const TypeNode& t : types) + { + TypeMatcher m(d_self); + Trace("datatypes-init") << " " << t << std::endl; + if (m.doMatching(d_self, t)) + { + Trace("datatypes-init") + << "DType::hasNestedRecursion: true for " << getName() + << " due to parametric strict component type, " << d_self + << " matching " << t << std::endl; + d_nestedRecursion = 1; + return true; + } + } + } + Trace("datatypes-init") << "DType::hasNestedRecursion: false for " + << getName() << std::endl; + d_nestedRecursion = -1; + return false; +} + Node getSubtermWithType(Node e, TypeNode t, bool isTop) { if (!isTop && e.getType() == t) diff --git a/src/expr/dtype.h b/src/expr/dtype.h index 08fe9965b..fea51cd36 100644 --- a/src/expr/dtype.h +++ b/src/expr/dtype.h @@ -2,9 +2,9 @@ /*! \file dtype.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -287,6 +287,16 @@ class DType * violated. */ bool isWellFounded() const; + /** + * Does this datatype have nested recursion? This is true if this datatype + * definition contains itself as an alien subfield type, or a variant + * of itself as an alien subfield type (if this datatype is parametric). + * For details see getAlienSubfieldTypes below. + * + * Notice that a type having no nested recursion may have a subfield type that + * has nested recursion. + */ + bool hasNestedRecursion() const; /** is recursive singleton * @@ -489,6 +499,51 @@ class DType * Helper for mkGroundTerm and mkGroundValue above. */ Node mkGroundTermInternal(TypeNode t, bool isValue) const; + /** + * This method is used to get alien subfield types of this datatype. + * + * A subfield type T of a datatype type D is a type such that a value of + * type T may appear as a subterm of a value of type D. + * + * An *alien* subfield type T of a datatype type D is a type such that a + * value v of type T may appear as a subterm of a value of D, and moreover + * v occurs as a strict subterm of a non-datatype term in that value. + * + * For example, the alien subfield types of T in: + * T -> Emp | Container(s : (Set List)) + * List -> nil | cons( head : Int, tail: List) + * are { List, Int }. Notice that Int is an alien subfield type since it + * appears as a subfield type of List, and List is an alien subfield type + * of T. In other words, Int is an alien subfield type due to the above + * definition due to the term (Container (singleton (cons 0 nil))), where + * 0 occurs as a subterm of (singleton (cons 0 nil)). The non-strict + * subfield types of T in this example are { (Set List) }. + * + * For example, the alien subfield types of T in: + * T -> Emp | Container(s : List) + * List -> nil | cons( head : (Set T), tail: List) + * are { T, List, (Set T) }. Notice that T is an alien subfield type of itself + * since List is a subfield type of T and T is an alien subfield type of List. + * Furthermore, List and (Set T) are also alien subfield types of T since + * List is a subfield type of T and T is an alien subfield type of itself. + * + * For example, the alien subfield types of T in: + * T -> Emp | Container(s : (Array Int T)) + * are { T, Int }, where we assume that values of (Array U1 U2) are + * constructed from values of U1 and U2, for all types U1, U2. The non-strict + * subfield types of T in this example are { (Array Int T) }. + * + * @param types The set of types to append the alien subfield types to, + * @param processed The datatypes (cached using d_self) we have processed. If + * the range of this map is true, we have processed the datatype with + * isAlienPos = true. + * @param isAlienPos Whether we are in an alien subfield type position. This + * flag is true if we have traversed beneath a non-datatype type constructor. + */ + void getAlienSubfieldTypes( + std::unordered_set<TypeNode, TypeNodeHashFunction>& types, + std::map<TypeNode, bool>& processed, + bool isAlienPos) const; /** name of this datatype */ std::string d_name; /** the type parameters of this datatype (if this is a parametric datatype) @@ -543,6 +598,12 @@ class DType * not. */ mutable int d_wellFounded; + /** + * Cache of whether this datatype has nested recursion, where 0 means we have + * not computed this information, 1 means it has nested recursion, -1 means it + * does not. + */ + mutable int d_nestedRecursion; /** cache of ground term for this datatype */ mutable std::map<TypeNode, Node> d_groundTerm; /** cache of ground values for this datatype */ diff --git a/src/expr/dtype_cons.cpp b/src/expr/dtype_cons.cpp index 8923667b1..b2e3fbd43 100644 --- a/src/expr/dtype_cons.cpp +++ b/src/expr/dtype_cons.cpp @@ -2,9 +2,9 @@ /*! \file dtype_cons.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/dtype_cons.h b/src/expr/dtype_cons.h index ca4806316..d89ed6af7 100644 --- a/src/expr/dtype_cons.h +++ b/src/expr/dtype_cons.h @@ -2,9 +2,9 @@ /*! \file dtype_cons.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/dtype_selector.cpp b/src/expr/dtype_selector.cpp index 960bbeb4d..302e6c51f 100644 --- a/src/expr/dtype_selector.cpp +++ b/src/expr/dtype_selector.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/dtype_selector.h b/src/expr/dtype_selector.h index 71b035d8c..bd0271d90 100644 --- a/src/expr/dtype_selector.h +++ b/src/expr/dtype_selector.h @@ -2,9 +2,9 @@ /*! \file dtype_selector.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/emptyset.cpp b/src/expr/emptyset.cpp index 789eaf20e..1c8950b55 100644 --- a/src/expr/emptyset.cpp +++ b/src/expr/emptyset.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/emptyset.h b/src/expr/emptyset.h index a9487e9a7..55e07747e 100644 --- a/src/expr/emptyset.h +++ b/src/expr/emptyset.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Kshitij Bansal, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/emptyset.i b/src/expr/emptyset.i index ada3dd583..bcd3a0a92 100644 --- a/src/expr/emptyset.i +++ b/src/expr/emptyset.i @@ -2,6 +2,48 @@ #include "expr/emptyset.h" %} +#ifdef SWIGJAVA + +%typemap(javabody) CVC4::EmptySet %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; // keep ref to em in SWIG proxy class + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + public $javaclassname(ExprManager em, SetType t) { + this(t); + this.em = em; + } +%} + +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea +%typemap(javaconstruct) EmptySet { + this(null, $imcall, true); +} + +%typemap(javaconstruct) CVC4::EmptySet { + this(null, $imcall, true); +} + +%javamethodmodifiers CVC4::EmptySet::EmptySet(Type t) "private"; + +%typemap(javaout) const CVC4::SetType& { + return new SetType(this.em, $jnicall, false); +} + +#endif + +%ignore CVC4::EmptySet::EmptySet(const CVC4::EmptySet& other); + %rename(equals) CVC4::EmptySet::operator==(const EmptySet&) const; %ignore CVC4::EmptySet::operator!=(const EmptySet&) const; diff --git a/src/expr/expr.i b/src/expr/expr.i index 14228d7c5..7e79d4c1d 100644 --- a/src/expr/expr.i +++ b/src/expr/expr.i @@ -1,102 +1,108 @@ %{ #include "expr/expr.h" +%} -#ifdef SWIGJAVA +%ignore CVC4::Expr::Expr(const Expr&); +// This is currently the only function that would require bindings for +// `std::unordered_map<Expr, Expr, ExprHashFunction>` and is better implemented +// at the Java/Python level if needed. Thus, we ignore it here. +%ignore CVC4::Expr::substitute(const std::unordered_map<Expr, Expr, ExprHashFunction> map) const; +%ignore CVC4::operator<<(std::ostream&, const Expr&); +%ignore CVC4::operator<<(std::ostream&, const TypeCheckingException&); +// Ignore because we would not know which ExprManager the Expr belongs to +%ignore CVC4::TypeCheckingException::getExpression() const; +%ignore CVC4::expr::operator<<(std::ostream&, ExprSetDepth); +%ignore CVC4::expr::operator<<(std::ostream&, ExprPrintTypes); +%ignore CVC4::expr::operator<<(std::ostream&, ExprDag); +%ignore CVC4::expr::operator<<(std::ostream&, ExprSetLanguage); +%ignore CVC4::Expr::operator=(const Expr&); +%ignore CVC4::Expr::operator!=(const Expr&) const; +%ignore CVC4::Expr::operator bool() const;// can just use isNull() -#include "bindings/java_iterator_adapter.h" -#include "bindings/java_stream_adapters.h" +%rename(equals) CVC4::Expr::operator==(const Expr&) const; +%rename(less) CVC4::Expr::operator<(const Expr&) const; +%rename(lessEqual) CVC4::Expr::operator<=(const Expr&) const; +%rename(greater) CVC4::Expr::operator>(const Expr&) const; +%rename(greaterEqual) CVC4::Expr::operator>=(const Expr&) const; -#endif /* SWIGJAVA */ -%} +%rename(getChild) CVC4::Expr::operator[](unsigned i) const; -#ifdef SWIGPYTHON -%rename(doApply) CVC4::ExprHashFunction::operator()(CVC4::Expr) const; -#else /* SWIGPYTHON */ +#ifdef SWIGJAVA + +// For the Java bindings, we implement `getExprManager()` at the Java level +// because we can't map back the C++ point to the Java object +%ignore CVC4::Expr::getExprManager() const; %rename(apply) CVC4::ExprHashFunction::operator()(CVC4::Expr) const; -#endif /* SWIGPYTHON */ -#ifdef SWIGJAVA %typemap(javabody) CVC4::Expr %{ private long swigCPtr; protected boolean swigCMemOwn; + private ExprManager em; - protected $javaclassname(long cPtr, boolean cMemoryOwn) { + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { swigCMemOwn = cMemoryOwn; swigCPtr = cPtr; - this.em = SmtEngine.mkRef(getExprManager()); // keep ref to em in SWIG proxy class + this.em = em; // keep ref to em in SWIG proxy class } protected static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } -%} -%javamethodmodifiers CVC4::Expr::operator=(const Expr&) "protected"; -%typemap(javacode) CVC4::Expr %{ - // a ref is kept here to keep Java GC from collecting the ExprManager - // before the Expr - private Object em; - - public Expr assign(Expr e) { - Expr r = assignInternal(e); - this.em = SmtEngine.mkRef(getExprManager()); // keep ref to em in SWIG proxy class - return r; + + public ExprManager getExprManager() throws edu.stanford.CVC4.Exception { + return this.em; + } + + public JavaIteratorAdapter_Expr iterator() { + return new JavaIteratorAdapter_Expr(this.em, this); } %} + +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea %typemap(javaconstruct) Expr { - this($imcall, true); - this.em = SmtEngine.mkRef(getExprManager()); // keep ref to em in SWIG proxy class - } -%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") CVC4::Expr { - SmtEngine.dlRef(em); - em = null; - if (swigCPtr != 0) { - if (swigCMemOwn) { - swigCMemOwn = false; - CVC4JNI.delete_Expr(swigCPtr); - } - swigCPtr = 0; - } - } -#endif /* SWIGJAVA */ + this(null, $imcall, true); +} -%ignore CVC4::operator<<(std::ostream&, const Expr&); -%ignore CVC4::operator<<(std::ostream&, const TypeCheckingException&); +%typemap(javaconstruct) CVC4::Expr { + this(null, $imcall, true); +} -%ignore CVC4::expr::operator<<(std::ostream&, ExprSetDepth); -%ignore CVC4::expr::operator<<(std::ostream&, ExprPrintTypes); -%ignore CVC4::expr::operator<<(std::ostream&, ExprDag); -%ignore CVC4::expr::operator<<(std::ostream&, ExprSetLanguage); +%typemap(javaout) CVC4::Expr { + return new Expr(this.em, $jnicall, true); +} -%rename(assignInternal) CVC4::Expr::operator=(const Expr&); -%rename(equals) CVC4::Expr::operator==(const Expr&) const; -%ignore CVC4::Expr::operator!=(const Expr&) const; -%rename(less) CVC4::Expr::operator<(const Expr&) const; -%rename(lessEqual) CVC4::Expr::operator<=(const Expr&) const; -%rename(greater) CVC4::Expr::operator>(const Expr&) const; -%rename(greaterEqual) CVC4::Expr::operator>=(const Expr&) const; +SWIG_STD_VECTOR_EM(CVC4::Expr, const CVC4::Expr&) +SWIG_STD_VECTOR_EM(std::vector<CVC4::Expr>, const std::vector<CVC4::Expr>&) -%rename(getChild) CVC4::Expr::operator[](unsigned i) const; -%ignore CVC4::Expr::operator bool() const;// can just use isNull() +%template(vectorExpr) std::vector<CVC4::Expr>; +%typemap(javaout) std::vector<CVC4::Expr> { + return new vectorExpr(this.em, $jnicall, true); +} +%typemap(javaout) const std::vector<CVC4::Expr>& { + return new vectorExpr(this.em, $jnicall, false); +} +%template(vectorVectorExpr) std::vector<std::vector<CVC4::Expr>>; -namespace CVC4 { - namespace expr { - %ignore exportInternal; - }/* CVC4::expr namespace */ -}/* CVC4 namespace */ +%javamethodmodifiers CVC4::Expr::operator=(const Expr&) "protected"; -#ifdef SWIGJAVA +%typemap(javaout) const CVC4::AscriptionType& { + return new AscriptionType(this.em, $jnicall, $owner); +} + +%typemap(javaout) const CVC4::EmptySet& { + return new EmptySet(this.em, $jnicall, $owner); +} + +%typemap(javaout) const CVC4::ExprSequence& { + return new ExprSequence(this.em, $jnicall, $owner); +} // Instead of Expr::begin() and end(), create an // iterator() method on the Java side that returns a Java-style // Iterator. %ignore CVC4::Expr::begin() const; %ignore CVC4::Expr::end() const; -%extend CVC4::Expr { - CVC4::JavaIteratorAdapter<CVC4::Expr, CVC4::Expr> iterator() - { - return CVC4::JavaIteratorAdapter<CVC4::Expr, CVC4::Expr>(*$self); - } -} +%ignore CVC4::Expr::const_iterator; // Expr is "iterable" on the Java side %typemap(javainterfaces) CVC4::Expr "java.lang.Iterable<edu.stanford.CVC4.Expr>"; @@ -123,6 +129,10 @@ namespace CVC4 { #endif /* SWIGJAVA */ +#ifdef SWIGPYTHON +%rename(doApply) CVC4::ExprHashFunction::operator()(CVC4::Expr) const; +#endif /* SWIGPYTHON */ + %include "expr/expr.h" #ifdef SWIGPYTHON @@ -156,11 +166,7 @@ namespace CVC4 { #ifdef SWIGJAVA -%include "bindings/java_iterator_adapter.h" -%include "bindings/java_stream_adapters.h" - +SWIG_JAVA_ITERATOR_ADAPTER(CVC4::Expr, CVC4::Expr) %template(JavaIteratorAdapter_Expr) CVC4::JavaIteratorAdapter<CVC4::Expr, CVC4::Expr>; #endif /* SWIGJAVA */ - -%include "expr/expr.h" diff --git a/src/expr/expr_iomanip.cpp b/src/expr/expr_iomanip.cpp index 22600d79d..1ea1ca6aa 100644 --- a/src/expr/expr_iomanip.cpp +++ b/src/expr/expr_iomanip.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/expr_iomanip.h b/src/expr/expr_iomanip.h index 9a582f8c8..f8464392a 100644 --- a/src/expr/expr_iomanip.h +++ b/src/expr/expr_iomanip.h @@ -2,9 +2,9 @@ /*! \file expr_iomanip.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/expr_manager.i b/src/expr/expr_manager.i index 5a5e7a9d4..d8ed7f6a6 100644 --- a/src/expr/expr_manager.i +++ b/src/expr/expr_manager.i @@ -2,29 +2,105 @@ #include "expr/expr_manager.h" %} -%typemap(javacode) CVC4::ExprManager %{ - // a ref is kept here to keep Java GC from collecting the Options - // before the ExprManager - private Object options; -%} -%typemap(javaconstruct) ExprManager { - this($imcall, true); - this.options = SmtEngine.mkRef(options); // keep ref to options in SWIG proxy class - } -%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") CVC4::ExprManager { - SmtEngine.dlRef(options); - options = null; - if (swigCPtr != 0) { - if (swigCMemOwn) { - swigCMemOwn = false; - CVC4JNI.delete_ExprManager(swigCPtr); - } - swigCPtr = 0; - } - } - +%ignore CVC4::ExprManager::exportType(const Type& t, ExprManager* em, ExprManagerMapCollection& vmap); %ignore CVC4::stats::getStatisticsRegistry(ExprManager*); %ignore CVC4::ExprManager::getResourceManager(); +%ignore CVC4::ExprManager::mkRecordType(const Record& rec); +%ignore CVC4::ExprManager::safeFlushStatistics(int fd) const; + +#ifdef SWIGJAVA + +%typemap(javaout) CVC4::Expr { + return new Expr(this, $jnicall, true); +} + +%typemap(javaout) CVC4::Type { + return new Type(this, $jnicall, true); +} + +%typemap(javaout) CVC4::ArrayType { + return new ArrayType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::BitVectorType { + return new BitVectorType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::BooleanType { + return new BooleanType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::ConstructorType { + return new ConstructorType(this, $jnicall, true); +} + +%typemap(javaout) const CVC4::Datatype& { + return new Datatype(this, $jnicall, false); +} + +%typemap(javaout) CVC4::DatatypeType { + return new DatatypeType(this, $jnicall, true); +} + +%typemap(javaout) std::vector<CVC4::DatatypeType> { + return new vectorDatatypeType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::FloatingPointType { + return new FloatingPointType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::FunctionType { + return new FunctionType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::SelectorType { + return new SelectorType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::StringType { + return new StringType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::RegExpType { + return new RegExpType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::RealType { + return new RealType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::SetType { + return new SetType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::SExprType { + return new SExprType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::SortType { + return new SortType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::SortConstructorType { + return new SortConstructorType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::TesterType { + return new TesterType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::IntegerType { + return new IntegerType(this, $jnicall, true); +} + +%typemap(javaout) CVC4::RoundingModeType { + return new RoundingModeType(this, $jnicall, true); +} + +%javamethodmodifiers CVC4::ExprManager::exportType(const Type& t, ExprManager* em, ExprManagerMapCollection& vmap) "public"; + +#endif /* SWIGJAVA */ %include "expr/expr_manager.h" @@ -53,7 +129,6 @@ %template(mkConst) CVC4::ExprManager::mkConst<CVC4::kind::Kind_t>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::DatatypeIndexConstant>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::TupleUpdate>; -%template(mkConst) CVC4::ExprManager::mkConst<CVC4::RecordUpdate>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::Rational>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::BitVector>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::EmptySet>; @@ -74,5 +149,3 @@ %template(mkConst) CVC4::ExprManager::mkConst<bool>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::RoundingMode>; #endif - -%include "expr/expr_manager.h" diff --git a/src/expr/expr_manager_scope.h b/src/expr/expr_manager_scope.h index b494796a1..12d47c89b 100644 --- a/src/expr/expr_manager_scope.h +++ b/src/expr/expr_manager_scope.h @@ -2,9 +2,9 @@ /*! \file expr_manager_scope.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Christopher L. Conway + ** Morgan Deters, Christopher L. Conway, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/expr_manager_template.cpp b/src/expr/expr_manager_template.cpp index 21d7ff0ea..d499b8bb7 100644 --- a/src/expr/expr_manager_template.cpp +++ b/src/expr/expr_manager_template.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Christopher L. Conway, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/expr_manager_template.h b/src/expr/expr_manager_template.h index 16d66cf6a..3a4498ab7 100644 --- a/src/expr/expr_manager_template.h +++ b/src/expr/expr_manager_template.h @@ -2,9 +2,9 @@ /*! \file expr_manager_template.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Andrew Reynolds + ** Morgan Deters, Andrew Reynolds, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -36,6 +36,10 @@ ${includes} namespace CVC4 { +namespace api { +class Solver; +} + class Expr; class SmtEngine; class NodeManager; @@ -45,7 +49,8 @@ struct ExprManagerMapCollection; class ResourceManager; class CVC4_PUBLIC ExprManager { -private: + private: + friend api::Solver; /** The internal node manager */ NodeManager* d_nodeManager; @@ -83,7 +88,6 @@ private: /** A list of datatypes owned by this expr manager. */ std::vector<std::unique_ptr<Datatype> > d_ownedDatatypes; - public: /** * Creates an expression manager with default options. */ @@ -97,6 +101,7 @@ private: */ explicit ExprManager(const Options& options); + public: /** * Destroys the expression manager. No will be deallocated at this point, so * any expression references that used to be managed by this expression diff --git a/src/expr/expr_sequence.cpp b/src/expr/expr_sequence.cpp index 4f761c8f7..aa58bba32 100644 --- a/src/expr/expr_sequence.cpp +++ b/src/expr/expr_sequence.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/expr_sequence.h b/src/expr/expr_sequence.h index 9515a9244..90a140fc2 100644 --- a/src/expr/expr_sequence.h +++ b/src/expr/expr_sequence.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/expr_sequence.i b/src/expr/expr_sequence.i index 42e130466..294937024 100644 --- a/src/expr/expr_sequence.i +++ b/src/expr/expr_sequence.i @@ -2,6 +2,42 @@ #include "expr/expr_sequence.h" %} +#ifdef SWIGJAVA + +%typemap(javabody) CVC4::ExprSequence %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; // keep ref to em in SWIG proxy class + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + public $javaclassname(ExprManager em, Type type, vectorExpr seq) { + this(type, seq); + this.em = em; + } +%} + +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea +%typemap(javaconstruct) ExprSequence { + this(null, $imcall, true); +} + +%typemap(javaconstruct) CVC4::ExprSequence { + this(null, $imcall, true); +} + +%javamethodmodifiers CVC4::ExprSequence::ExprSequence(Type type, vectorExpr seq) "private"; + +#endif + %rename(equals) CVC4::ExprSequence::operator==(const ExprSequence&) const; %ignore CVC4::ExprSequence::operator!=(const ExprSequence&) const; %ignore CVC4::ExprSequence::getSequence() const; diff --git a/src/expr/expr_template.cpp b/src/expr/expr_template.cpp index 3ed72e03e..50884f715 100644 --- a/src/expr/expr_template.cpp +++ b/src/expr/expr_template.cpp @@ -2,9 +2,9 @@ /*! \file expr_template.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Tim King + ** Morgan Deters, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/expr_template.h b/src/expr/expr_template.h index 546a0d00e..34374d354 100644 --- a/src/expr/expr_template.h +++ b/src/expr/expr_template.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Dejan Jovanovic, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/kind_map.h b/src/expr/kind_map.h index 3b49ad51a..10f475911 100644 --- a/src/expr/kind_map.h +++ b/src/expr/kind_map.h @@ -2,9 +2,9 @@ /*! \file kind_map.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic + ** Dejan Jovanovic, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/kind_template.cpp b/src/expr/kind_template.cpp index d3af9a836..0d7f5f4e4 100644 --- a/src/expr/kind_template.cpp +++ b/src/expr/kind_template.cpp @@ -2,9 +2,9 @@ /*! \file kind_template.cpp ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli, Morgan Deters, Dejan Jovanovic + ** Andres Noetzli, Christopher L. Conway, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/kind_template.h b/src/expr/kind_template.h index 50e2f372c..d34179252 100644 --- a/src/expr/kind_template.h +++ b/src/expr/kind_template.h @@ -2,9 +2,9 @@ /*! \file kind_template.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Andres Noetzli + ** Andres Noetzli, Morgan Deters, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/lazy_proof.cpp b/src/expr/lazy_proof.cpp new file mode 100644 index 000000000..3980a3cb3 --- /dev/null +++ b/src/expr/lazy_proof.cpp @@ -0,0 +1,181 @@ +/********************* */ +/*! \file lazy_proof.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 lazy proof utility + **/ + +#include "expr/lazy_proof.h" + +using namespace CVC4::kind; + +namespace CVC4 { + +LazyCDProof::LazyCDProof(ProofNodeManager* pnm, + ProofGenerator* dpg, + context::Context* c) + : CDProof(pnm, c), d_gens(c ? c : &d_context), d_defaultGen(dpg) +{ +} + +LazyCDProof::~LazyCDProof() {} + +std::shared_ptr<ProofNode> LazyCDProof::getProofFor(Node fact) +{ + Trace("lazy-cdproof") << "LazyCDProof::mkLazyProof " << fact << std::endl; + // make the proof, which should always be non-null, since we construct an + // assumption in the worst case. + std::shared_ptr<ProofNode> opf = CDProof::getProofFor(fact); + Assert(opf != nullptr); + if (!hasGenerators()) + { + Trace("lazy-cdproof") << "...no generators, finished" << std::endl; + // optimization: no generators, we are done + return opf; + } + // otherwise, we traverse the proof opf and fill in the ASSUME leafs that + // have generators + std::unordered_set<ProofNode*> visited; + std::unordered_set<ProofNode*>::iterator it; + std::vector<ProofNode*> visit; + ProofNode* cur; + visit.push_back(opf.get()); + do + { + cur = visit.back(); + visit.pop_back(); + it = visited.find(cur); + + if (it == visited.end()) + { + visited.insert(cur); + if (cur->getRule() == PfRule::ASSUME) + { + Node afact = cur->getResult(); + bool isSym = false; + ProofGenerator* pg = getGeneratorFor(afact, isSym); + if (pg != nullptr) + { + Trace("lazy-cdproof") << "LazyCDProof: Call generator for assumption " + << afact << std::endl; + Node afactGen = isSym ? CDProof::getSymmFact(afact) : afact; + Assert(!afactGen.isNull()); + // use the addProofTo interface + if (!pg->addProofTo(afactGen, this)) + { + Trace("lazy-cdproof") << "LazyCDProof: Failed added fact for " + << afactGen << std::endl; + Assert(false) << "Proof generator " << pg->identify() + << " could not add proof for fact " << afactGen + << std::endl; + } + else + { + Trace("lazy-cdproof") << "LazyCDProof: Successfully added fact for " + << afactGen << std::endl; + } + } + else + { + Trace("lazy-cdproof") + << "LazyCDProof: No generator for " << afact << std::endl; + } + // Notice that we do not traverse the proofs that have been generated + // lazily by the proof generators here. In other words, we assume that + // the proofs from provided proof generators are final and need + // no further modification by this class. + } + else + { + const std::vector<std::shared_ptr<ProofNode>>& cc = cur->getChildren(); + for (const std::shared_ptr<ProofNode>& cp : cc) + { + visit.push_back(cp.get()); + } + } + } + } while (!visit.empty()); + // we have now updated the ASSUME leafs of opf, return it + Trace("lazy-cdproof") << "...finished" << std::endl; + return opf; +} + +void LazyCDProof::addLazyStep(Node expected, + ProofGenerator* pg, + bool forceOverwrite) +{ + Assert(pg != nullptr); + if (!forceOverwrite) + { + NodeProofGeneratorMap::const_iterator it = d_gens.find(expected); + if (it != d_gens.end()) + { + // don't overwrite something that is already there + return; + } + } + // just store now + d_gens.insert(expected, pg); +} + +ProofGenerator* LazyCDProof::getGeneratorFor(Node fact, + bool& isSym) +{ + isSym = false; + NodeProofGeneratorMap::const_iterator it = d_gens.find(fact); + if (it != d_gens.end()) + { + return (*it).second; + } + Node factSym = CDProof::getSymmFact(fact); + // could be symmetry + if (factSym.isNull()) + { + // can't be symmetry, return the default generator + return d_defaultGen; + } + it = d_gens.find(factSym); + if (it != d_gens.end()) + { + isSym = true; + return (*it).second; + } + // return the default generator + return d_defaultGen; +} + +bool LazyCDProof::hasGenerators() const +{ + return !d_gens.empty() || d_defaultGen != nullptr; +} + +bool LazyCDProof::hasGenerator(Node fact) const +{ + if (d_defaultGen != nullptr) + { + return true; + } + NodeProofGeneratorMap::const_iterator it = d_gens.find(fact); + if (it != d_gens.end()) + { + return true; + } + // maybe there is a symmetric fact? + Node factSym = CDProof::getSymmFact(fact); + if (!factSym.isNull()) + { + it = d_gens.find(factSym); + } + return it != d_gens.end(); +} + +std::string LazyCDProof::identify() const { return "LazyCDProof"; } + +} // namespace CVC4 diff --git a/src/expr/lazy_proof.h b/src/expr/lazy_proof.h new file mode 100644 index 000000000..c802de39e --- /dev/null +++ b/src/expr/lazy_proof.h @@ -0,0 +1,103 @@ +/********************* */ +/*! \file lazy_proof.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 Lazy proof utility + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__EXPR__LAZY_PROOF_H +#define CVC4__EXPR__LAZY_PROOF_H + +#include <unordered_map> +#include <vector> + +#include "expr/proof.h" +#include "expr/proof_generator.h" +#include "expr/proof_node_manager.h" + +namespace CVC4 { + +/** + * A (context-dependent) lazy proof. This class is an extension of CDProof + * that additionally maps facts to proof generators in a context-dependent + * manner. It extends CDProof with an additional method, addLazyStep for adding + * steps to a proof via a given proof generator. + */ +class LazyCDProof : public CDProof +{ + public: + /** Constructor + * + * @param pnm The proof node manager for constructing ProofNode objects. + * @param dpg The (optional) default proof generator, which is called + * for facts that have no explicitly provided generator. + * @param c The context that this class depends on. If none is provided, + * this class is context-independent. + */ + LazyCDProof(ProofNodeManager* pnm, + ProofGenerator* dpg = nullptr, + context::Context* c = nullptr); + ~LazyCDProof(); + /** + * Get lazy proof for fact, or nullptr if it does not exist. This may + * additionally call proof generators to generate proofs for ASSUME nodes that + * don't yet have a concrete proof. + */ + std::shared_ptr<ProofNode> getProofFor(Node fact) override; + /** Add step by generator + * + * This method stores that expected can be proven by proof generator pg if + * it is required to do so. This mapping is maintained in the remainder of + * the current context (according to the context c provided to this class). + * + * It is important to note that pg is asked to provide a proof for expected + * only when no other call for the fact expected is provided via the addStep + * method of this class. In particular, pg is asked to prove expected when it + * appears as the conclusion of an ASSUME leaf within CDProof::getProofFor. + * + * @param expected The fact that can be proven. + * @param pg The generator that can proof expected. + * @param forceOverwrite If this flag is true, then this call overwrites + * an existing proof generator provided for expected, if one was provided + * via a previous call to addLazyStep in the current context. + */ + void addLazyStep(Node expected, + ProofGenerator* pg, + bool forceOverwrite = false); + /** + * Does this have any proof generators? This method always returns true + * if the default is non-null. + */ + bool hasGenerators() const; + /** Does the given fact have an explicitly provided generator? */ + bool hasGenerator(Node fact) const; + /** identify */ + std::string identify() const override; + + protected: + typedef context::CDHashMap<Node, ProofGenerator*, NodeHashFunction> + NodeProofGeneratorMap; + /** Maps facts that can be proven to generators */ + NodeProofGeneratorMap d_gens; + /** The default proof generator */ + ProofGenerator* d_defaultGen; + /** + * Get generator for fact, or nullptr if it doesnt exist. This method is + * robust to symmetry of (dis)equality. It updates isSym to true if a + * proof generator for the symmetric form of fact was provided. + */ + ProofGenerator* getGeneratorFor(Node fact, bool& isSym); +}; + +} // namespace CVC4 + +#endif /* CVC4__EXPR__LAZY_PROOF_H */ diff --git a/src/expr/match_trie.cpp b/src/expr/match_trie.cpp index 363c78c9e..a7a1a1839 100644 --- a/src/expr/match_trie.cpp +++ b/src/expr/match_trie.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/match_trie.h b/src/expr/match_trie.h index ea8be44d9..7d330ee0d 100644 --- a/src/expr/match_trie.h +++ b/src/expr/match_trie.h @@ -2,9 +2,9 @@ /*! \file match_trie.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli + ** Andrew Reynolds, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/metakind_template.cpp b/src/expr/metakind_template.cpp index 83c7e6e2c..5f72d5670 100644 --- a/src/expr/metakind_template.cpp +++ b/src/expr/metakind_template.cpp @@ -2,9 +2,9 @@ /*! \file metakind_template.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli, Dejan Jovanovic + ** Morgan Deters, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/metakind_template.h b/src/expr/metakind_template.h index fb1626adb..5fa10c90a 100644 --- a/src/expr/metakind_template.h +++ b/src/expr/metakind_template.h @@ -2,9 +2,9 @@ /*! \file metakind_template.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli, Dejan Jovanovic + ** Morgan Deters, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node.cpp b/src/expr/node.cpp index a8fc9d54c..90fb1f004 100644 --- a/src/expr/node.cpp +++ b/src/expr/node.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Yoni Zohar ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node.h b/src/expr/node.h index 2f9d0b0ac..e431727f4 100644 --- a/src/expr/node.h +++ b/src/expr/node.h @@ -2,9 +2,9 @@ /*! \file node.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Tim King + ** Morgan Deters, Dejan Jovanovic, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node_algorithm.cpp b/src/expr/node_algorithm.cpp index 44430f072..be436bf8b 100644 --- a/src/expr/node_algorithm.cpp +++ b/src/expr/node_algorithm.cpp @@ -2,9 +2,9 @@ /*! \file node_algorithm.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa, Andres Noetzli + ** Andrew Reynolds, Andres Noetzli, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -491,7 +491,13 @@ void getOperatorsMap( // add the current operator to the result if (cur.hasOperator()) { - ops[tn].insert(NodeManager::currentNM()->operatorOf(cur.getKind())); + Node o; + if (cur.getMetaKind() == kind::metakind::PARAMETERIZED) { + o = cur.getOperator(); + } else { + o = NodeManager::currentNM()->operatorOf(cur.getKind()); + } + ops[tn].insert(o); } // add children to visit in the future for (TNode cn : cur) @@ -622,17 +628,104 @@ void getComponentTypes( TypeNode curr = toProcess.back(); toProcess.pop_back(); // if not already visited - if (types.find(t) == types.end()) + if (types.find(curr) == types.end()) { - types.insert(t); + types.insert(curr); // get component types from the children - for (unsigned i = 0, nchild = t.getNumChildren(); i < nchild; i++) + for (unsigned i = 0, nchild = curr.getNumChildren(); i < nchild; i++) { - toProcess.push_back(t[i]); + toProcess.push_back(curr[i]); } } } while (!toProcess.empty()); } +bool match(Node x, + Node y, + std::unordered_map<Node, Node, NodeHashFunction>& subs) +{ + std::unordered_set<std::pair<TNode, TNode>, TNodePairHashFunction> visited; + std::unordered_set<std::pair<TNode, TNode>, TNodePairHashFunction>::iterator + it; + std::unordered_map<Node, Node, NodeHashFunction>::iterator subsIt; + + std::vector<std::pair<TNode, TNode>> stack; + stack.emplace_back(x, y); + std::pair<TNode, TNode> curr; + + while (!stack.empty()) + { + curr = stack.back(); + stack.pop_back(); + if (curr.first == curr.second) + { + // holds trivially + continue; + } + it = visited.find(curr); + if (it != visited.end()) + { + // already processed + continue; + } + visited.insert(curr); + if (curr.first.getNumChildren() == 0) + { + if (!curr.first.getType().isComparableTo(curr.second.getType())) + { + // the two subterms have different types + return false; + } + // if the two subterms are not equal and the first one is a bound + // variable... + if (curr.first.getKind() == kind::BOUND_VARIABLE) + { + // and we have not seen this variable before... + subsIt = subs.find(curr.first); + if (subsIt == subs.cend()) + { + // add the two subterms to `sub` + subs.emplace(curr.first, curr.second); + } + else + { + // if we saw this variable before, make sure that (now and before) it + // maps to the same subterm + if (curr.second != subsIt->second) + { + return false; + } + } + } + else + { + // the two subterms are not equal + return false; + } + } + else + { + // if the two subterms are not equal, make sure that their operators are + // equal + // we compare operators instead of kinds because different terms may have + // the same kind (both `(id x)` and `(square x)` have kind APPLY_UF) + // since many builtin operators like `PLUS` allow arbitrary number of + // arguments, we also need to check if the two subterms have the same + // number of children + if (curr.first.getNumChildren() != curr.second.getNumChildren() + || curr.first.getOperator() != curr.second.getOperator()) + { + return false; + } + // recurse on children + for (size_t i = 0, n = curr.first.getNumChildren(); i < n; ++i) + { + stack.emplace_back(curr.first[i], curr.second[i]); + } + } + } + return true; +} + } // namespace expr } // namespace CVC4 diff --git a/src/expr/node_algorithm.h b/src/expr/node_algorithm.h index 894dce7c6..4fb40c739 100644 --- a/src/expr/node_algorithm.h +++ b/src/expr/node_algorithm.h @@ -2,9 +2,9 @@ /*! \file node_algorithm.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli, Haniel Barbosa + ** Andrew Reynolds, Andres Noetzli, Yoni Zohar ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -157,7 +157,7 @@ void getOperatorsMap( /* * Substitution of Nodes in a capture avoiding way. - * If x occurs free in n and it is substituted by a term t + * If x occurs free in n and it is substituted by a term t * and t includes some variable y that is bound in n, * then using alpha conversion y is replaced with a fresh bound variable * before the substitution. @@ -166,9 +166,9 @@ void getOperatorsMap( Node substituteCaptureAvoiding(TNode n, Node src, Node dest); /** - * Same as substituteCaptureAvoiding above, but with a - * simultaneous substitution of a vector of variables. - * Elements in source will be replaced by their corresponding element in dest. + * Same as substituteCaptureAvoiding above, but with a + * simultaneous substitution of a vector of variables. + * Elements in source will be replaced by their corresponding element in dest. * Both vectors should have the same size. */ Node substituteCaptureAvoiding(TNode n, @@ -185,6 +185,29 @@ Node substituteCaptureAvoiding(TNode n, void getComponentTypes( TypeNode t, std::unordered_set<TypeNode, TypeNodeHashFunction>& types); +/** match + * + * Given two terms `n1` and `n2` containing free variables, match returns true + * if `n2` is an instance of `n1`. In which case, `subs` is a mapping from the + * free variables in `n1` to corresponding terms in `n2` such that: + * + * n1 * subs = n2 (where * denotes application of substitution). + * + * For example, given: + * n1 = (+ a (* x 2)) (x denotes a free variable) + * n2 = (+ a (* b 2)) + * a call to match should return `true` with subs = {(x, b)} + * + * @param n1 the term (containing free vars) to compare an instance term + * against + * @param n2 the instance term in question + * @param subs the mapping from free vars in `n1` to terms in `n2` + * @return whether or not `n2` is an instance of `n1` + */ +bool match(Node n1, + Node n2, + std::unordered_map<Node, Node, NodeHashFunction>& subs); + } // namespace expr } // namespace CVC4 diff --git a/src/expr/node_builder.h b/src/expr/node_builder.h index fb1d0fa6a..899961d73 100644 --- a/src/expr/node_builder.h +++ b/src/expr/node_builder.h @@ -2,9 +2,9 @@ /*! \file node_builder.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Christopher L. Conway + ** Morgan Deters, Mathias Preiner, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node_manager.cpp b/src/expr/node_manager.cpp index feec9b782..88c4db778 100644 --- a/src/expr/node_manager.cpp +++ b/src/expr/node_manager.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -27,6 +27,7 @@ #include "expr/dtype.h" #include "expr/node_manager_attributes.h" #include "expr/node_manager_listeners.h" +#include "expr/skolem_manager.h" #include "expr/type_checker.h" #include "options/options.h" #include "options/smt_options.h" @@ -95,6 +96,7 @@ NodeManager::NodeManager(ExprManager* exprManager) : d_options(new Options()), d_statisticsRegistry(new StatisticsRegistry()), d_resourceManager(new ResourceManager(*d_statisticsRegistry, *d_options)), + d_skManager(new SkolemManager), d_registrations(new ListenerRegistrationList()), next_id(0), d_attrManager(new expr::attr::AttributeManager()), @@ -111,6 +113,7 @@ NodeManager::NodeManager(ExprManager* exprManager, const Options& options) : d_options(new Options()), d_statisticsRegistry(new StatisticsRegistry()), d_resourceManager(new ResourceManager(*d_statisticsRegistry, *d_options)), + d_skManager(new SkolemManager), d_registrations(new ListenerRegistrationList()), next_id(0), d_attrManager(new expr::attr::AttributeManager()), @@ -168,6 +171,9 @@ NodeManager::~NodeManager() { NodeManagerScope nms(this); + // Destroy skolem manager before cleaning up attributes and zombies + d_skManager = nullptr; + { ScopedBool dontGC(d_inReclaimZombies); // hopefully by this point all SmtEngines have been deleted @@ -495,6 +501,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 +871,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..c3435f445 100644 --- a/src/expr/node_manager.h +++ b/src/expr/node_manager.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Christopher L. Conway, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -42,6 +42,7 @@ namespace CVC4 { class StatisticsRegistry; class ResourceManager; +class SkolemManager; class DType; @@ -113,6 +114,9 @@ class NodeManager { ResourceManager* d_resourceManager; + /** The skolem manager */ + std::shared_ptr<SkolemManager> d_skManager; + /** * A list of registrations on d_options to that call into d_resourceManager. * These must be garbage collected before d_options and d_resourceManager. @@ -405,6 +409,8 @@ public: /** Get this node manager's resource manager */ ResourceManager* getResourceManager() { return d_resourceManager; } + /** Get this node manager's skolem manager */ + SkolemManager* getSkolemManager() { return d_skManager.get(); } /** Get this node manager's statistics registry */ StatisticsRegistry* getStatisticsRegistry() const @@ -444,6 +450,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. */ @@ -525,13 +545,13 @@ public: * "SKOLEM_NO_NOTIFY | SKOLEM_EXACT_NAME"). Of course, SKOLEM_DEFAULT * cannot be composed in such a manner. */ - enum SkolemFlags { - SKOLEM_DEFAULT = 0, /**< default behavior */ - SKOLEM_NO_NOTIFY = 1, /**< do not notify subscribers */ - SKOLEM_EXACT_NAME = 2,/**< do not make the name unique by adding the id */ - SKOLEM_IS_GLOBAL = 4 /**< global vars appear in models even after a pop */ - };/* enum SkolemFlags */ - + enum SkolemFlags + { + SKOLEM_DEFAULT = 0, /**< default behavior */ + SKOLEM_NO_NOTIFY = 1, /**< do not notify subscribers */ + SKOLEM_EXACT_NAME = 2, /**< do not make the name unique by adding the id */ + SKOLEM_IS_GLOBAL = 4 /**< global vars appear in models even after a pop */ + }; /** * Create a skolem constant with the given name, type, and comment. * @@ -875,9 +895,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/node_manager_attributes.h b/src/expr/node_manager_attributes.h index 99bfcb8a9..be1fe5a6b 100644 --- a/src/expr/node_manager_attributes.h +++ b/src/expr/node_manager_attributes.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node_manager_listeners.cpp b/src/expr/node_manager_listeners.cpp index ecb089dc9..56a827deb 100644 --- a/src/expr/node_manager_listeners.cpp +++ b/src/expr/node_manager_listeners.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node_manager_listeners.h b/src/expr/node_manager_listeners.h index 501c6129f..e296b7ec6 100644 --- a/src/expr/node_manager_listeners.h +++ b/src/expr/node_manager_listeners.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node_self_iterator.h b/src/expr/node_self_iterator.h index 79df7691c..ae76434af 100644 --- a/src/expr/node_self_iterator.h +++ b/src/expr/node_self_iterator.h @@ -2,9 +2,9 @@ /*! \file node_self_iterator.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli + ** Morgan Deters, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node_traversal.cpp b/src/expr/node_traversal.cpp index ad1a9ec71..5968c4348 100644 --- a/src/expr/node_traversal.cpp +++ b/src/expr/node_traversal.cpp @@ -2,7 +2,7 @@ /*! \file node_traversal.cpp ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir + ** Alex Ozdemir, Andres Noetzli ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. @@ -17,20 +17,20 @@ namespace CVC4 { NodeDfsIterator::NodeDfsIterator(TNode n, - bool postorder, + VisitOrder order, std::function<bool(TNode)> skipIf) : d_stack{n}, d_visited(), - d_postorder(postorder), + d_order(order), d_current(TNode()), d_skipIf(skipIf) { } -NodeDfsIterator::NodeDfsIterator(bool postorder) +NodeDfsIterator::NodeDfsIterator(VisitOrder order) : d_stack(), d_visited(), - d_postorder(postorder), + d_order(order), d_current(TNode()), d_skipIf([](TNode) { return false; }) { @@ -63,18 +63,21 @@ TNode& NodeDfsIterator::operator*() return d_current; } -bool NodeDfsIterator::operator==(const NodeDfsIterator& other) const +bool NodeDfsIterator::operator==(NodeDfsIterator& other) { + // Unitialize this node, and the other, before comparing. + initializeIfUninitialized(); + other.initializeIfUninitialized(); // The stack and current node uniquely represent traversal state. We need not // use the scheduled node set. // // Users should not compare iterators for traversals of different nodes, or // traversals with different skipIfs. - Assert(d_postorder == other.d_postorder); + Assert(d_order == other.d_order); return d_stack == other.d_stack && d_current == other.d_current; } -bool NodeDfsIterator::operator!=(const NodeDfsIterator& other) const +bool NodeDfsIterator::operator!=(NodeDfsIterator& other) { return !(*this == other); } @@ -102,12 +105,12 @@ void NodeDfsIterator::advanceToNextVisit() { d_stack.push_back(back[i]); } - if (!d_postorder) + if (d_order == VisitOrder::PREORDER) { return; } } - else if (!d_postorder || visitEntry->second) + else if (d_order == VisitOrder::PREORDER || visitEntry->second) { // if we're previsiting or we've already post-visited this node: skip it d_stack.pop_back(); @@ -134,38 +137,21 @@ void NodeDfsIterator::initializeIfUninitialized() } } -NodeDfsIterable::NodeDfsIterable(TNode n) - : d_node(n), d_postorder(true), d_skipIf([](TNode) { return false; }) -{ -} - -NodeDfsIterable& NodeDfsIterable::inPostorder() -{ - d_postorder = true; - return *this; -} - -NodeDfsIterable& NodeDfsIterable::inPreorder() -{ - d_postorder = false; - return *this; -} - -NodeDfsIterable& NodeDfsIterable::skipIf( - std::function<bool(TNode)> skipCondition) +NodeDfsIterable::NodeDfsIterable(TNode n, + VisitOrder order, + std::function<bool(TNode)> skipIf) + : d_node(n), d_order(order), d_skipIf(skipIf) { - d_skipIf = skipCondition; - return *this; } NodeDfsIterator NodeDfsIterable::begin() const { - return NodeDfsIterator(d_node, d_postorder, d_skipIf); + return NodeDfsIterator(d_node, d_order, d_skipIf); } NodeDfsIterator NodeDfsIterable::end() const { - return NodeDfsIterator(d_postorder); + return NodeDfsIterator(d_order); } } // namespace CVC4 diff --git a/src/expr/node_traversal.h b/src/expr/node_traversal.h index 1078f08c8..586cbb64d 100644 --- a/src/expr/node_traversal.h +++ b/src/expr/node_traversal.h @@ -2,7 +2,7 @@ /*! \file node_traversal.h ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir + ** Alex Ozdemir, Andres Noetzli ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. @@ -27,7 +27,16 @@ namespace CVC4 { -// Iterator for traversing a node in post-order +/** + * Enum that represents an order in which nodes are visited. + */ +enum class VisitOrder +{ + PREORDER, + POSTORDER +}; + +// Iterator for traversing a node in pre-/post-order // It does DAG-traversal, so indentical sub-nodes will be visited once only. class NodeDfsIterator { @@ -40,9 +49,9 @@ class NodeDfsIterator using difference_type = std::ptrdiff_t; // Construct a traversal iterator beginning at `n` - NodeDfsIterator(TNode n, bool postorder, std::function<bool(TNode)> skipIf); + NodeDfsIterator(TNode n, VisitOrder order, std::function<bool(TNode)> skipIf); // Construct an end-of-traversal iterator - NodeDfsIterator(bool postorder); + NodeDfsIterator(VisitOrder order); // Move/copy construction and assignment. Destructor. NodeDfsIterator(NodeDfsIterator&&) = default; @@ -58,9 +67,13 @@ class NodeDfsIterator // Dereference reference operator*(); // Equals - bool operator==(const NodeDfsIterator&) const; + // It is not constant, because an unitilized node must be initialized before + // comparison + bool operator==(NodeDfsIterator&); // Not equals - bool operator!=(const NodeDfsIterator&) const; + // It is not constant, because an unitilized node must be initialized before + // comparison + bool operator!=(NodeDfsIterator&); private: // While we're not at an appropriate visit (see d_postorder), advance. @@ -88,12 +101,8 @@ class NodeDfsIterator // Set to `true` if we've also already post-visited it. std::unordered_map<TNode, bool, TNodeHashFunction> d_visited; - // Whether this is a post-order iterator (the alternative is pre-order) - bool d_postorder; - - // Whether this iterator has been initialized (advanced to its first - // visit) - bool d_initialized; + // The visit order that this iterator is using + VisitOrder d_order; // Current referent node. A valid node to visit if non-null. // Null after construction (but before first access) and at the end. @@ -103,20 +112,23 @@ class NodeDfsIterator std::function<bool(TNode)> d_skipIf; }; -// Node wrapper that is iterable in DAG post-order +// Node wrapper that is iterable in DAG pre-/post-order class NodeDfsIterable { public: - NodeDfsIterable(TNode n); - - // Modifying the traversal order - // Modify this iterable to be in post-order (default) - NodeDfsIterable& inPostorder(); - // Modify this iterable to be in pre-order - NodeDfsIterable& inPreorder(); - - // Skip a node (and its descendants) if true. - NodeDfsIterable& skipIf(std::function<bool(TNode)> skipCondition); + /** + * Creates a new node wrapper that can be used to iterate over the children + * of a node in pre-/post-order. + * + * @param n The node the iterate + * @param order The order in which the children are visited. + * @param skipIf Function that determines whether a given node and its + * descendants should be skipped or not. + */ + NodeDfsIterable( + TNode n, + VisitOrder order = VisitOrder::POSTORDER, + std::function<bool(TNode)> skipIf = [](TNode) { return false; }); // Move/copy construction and assignment. Destructor. NodeDfsIterable(NodeDfsIterable&&) = default; @@ -130,7 +142,7 @@ class NodeDfsIterable private: TNode d_node; - bool d_postorder; + VisitOrder d_order; std::function<bool(TNode)> d_skipIf; }; diff --git a/src/expr/node_trie.cpp b/src/expr/node_trie.cpp index 0900ec9af..da1e6a001 100644 --- a/src/expr/node_trie.cpp +++ b/src/expr/node_trie.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node_trie.h b/src/expr/node_trie.h index 7aa740a42..c1c7fdfc0 100644 --- a/src/expr/node_trie.h +++ b/src/expr/node_trie.h @@ -2,9 +2,9 @@ /*! \file node_trie.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node_value.cpp b/src/expr/node_value.cpp index ef1cd966e..908f93104 100644 --- a/src/expr/node_value.cpp +++ b/src/expr/node_value.cpp @@ -2,9 +2,9 @@ /*! \file node_value.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Dejan Jovanovic + ** Morgan Deters, Aina Niemetz, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node_value.h b/src/expr/node_value.h index 2c52c46be..fdc07b1ef 100644 --- a/src/expr/node_value.h +++ b/src/expr/node_value.h @@ -2,9 +2,9 @@ /*! \file node_value.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Tim King + ** Morgan Deters, Aina Niemetz, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/node_visitor.h b/src/expr/node_visitor.h index 47ed6eff8..c960dde09 100644 --- a/src/expr/node_visitor.h +++ b/src/expr/node_visitor.h @@ -2,9 +2,9 @@ /*! \file node_visitor.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Morgan Deters, Liana Hadarean + ** Dejan Jovanovic, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/proof.cpp b/src/expr/proof.cpp index eff222b92..20e8e29e2 100644 --- a/src/expr/proof.cpp +++ b/src/expr/proof.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -25,6 +25,22 @@ CDProof::CDProof(ProofNodeManager* pnm, context::Context* c) CDProof::~CDProof() {} +std::shared_ptr<ProofNode> CDProof::getProofFor(Node fact) +{ + std::shared_ptr<ProofNode> pf = getProofSymm(fact); + if (pf != nullptr) + { + return pf; + } + // add as assumption + std::vector<Node> pargs = {fact}; + std::vector<std::shared_ptr<ProofNode>> passume; + std::shared_ptr<ProofNode> pfa = + d_manager->mkNode(PfRule::ASSUME, passume, pargs, fact); + d_nodes.insert(fact, pfa); + return pfa; +} + std::shared_ptr<ProofNode> CDProof::getProof(Node fact) const { NodeProofNodeMap::iterator it = d_nodes.find(fact); @@ -35,42 +51,100 @@ std::shared_ptr<ProofNode> CDProof::getProof(Node fact) const return nullptr; } +std::shared_ptr<ProofNode> CDProof::getProofSymm(Node fact) +{ + Trace("cdproof") << "CDProof::getProofSymm: " << fact << std::endl; + std::shared_ptr<ProofNode> pf = getProof(fact); + if (pf != nullptr && !isAssumption(pf.get())) + { + Trace("cdproof") << "...existing non-assume " << pf->getRule() << std::endl; + return pf; + } + Node symFact = getSymmFact(fact); + if (symFact.isNull()) + { + Trace("cdproof") << "...no possible symm" << std::endl; + // no symmetry possible, return original proof (possibly assumption) + return pf; + } + // See if a proof exists for the opposite direction, if so, add the step. + // Notice that SYMM is also disallowed. + std::shared_ptr<ProofNode> pfs = getProof(symFact); + if (pfs != nullptr) + { + // The symmetric fact exists, and the current one either does not, or is + // an assumption. We make a new proof that applies SYMM to pfs. + std::vector<std::shared_ptr<ProofNode>> pschild; + pschild.push_back(pfs); + std::vector<Node> args; + if (pf == nullptr) + { + Trace("cdproof") << "...fresh make symm" << std::endl; + std::shared_ptr<ProofNode> psym = + d_manager->mkNode(PfRule::SYMM, pschild, args, fact); + Assert(psym != nullptr); + d_nodes.insert(fact, psym); + return psym; + } + else if (!isAssumption(pfs.get())) + { + // if its not an assumption, make the connection + Trace("cdproof") << "...update symm" << std::endl; + // update pf + bool sret = d_manager->updateNode(pf.get(), PfRule::SYMM, pschild, args); + AlwaysAssert(sret); + } + } + else + { + Trace("cdproof") << "...no symm, return " + << (pf == nullptr ? "null" : "non-null") << std::endl; + } + // return original proof (possibly assumption) + return pf; +} + bool CDProof::addStep(Node expected, PfRule id, const std::vector<Node>& children, const std::vector<Node>& args, bool ensureChildren, - bool forceOverwrite) + CDPOverwrite opolicy) { - // we must provide expected + Trace("cdproof") << "CDProof::addStep: " << id << " " << expected + << ", ensureChildren = " << ensureChildren + << ", overwrite policy = " << opolicy << std::endl; + // We must always provide expected to this method Assert(!expected.isNull()); - NodeProofNodeMap::iterator it = d_nodes.find(expected); - if (it != d_nodes.end()) + std::shared_ptr<ProofNode> pprev = getProofSymm(expected); + if (pprev != nullptr) { - if (!forceOverwrite - && ((*it).second->getRule() != PfRule::ASSUME || id == PfRule::ASSUME)) + if (!shouldOverwrite(pprev.get(), id, opolicy)) { - // we do not overwrite if forceOverwrite is false and the previously - // provided step was not an assumption, or if the currently provided step - // is a (duplicate) assumption + // we should not overwrite the current step + Trace("cdproof") << "...success, no overwrite" << std::endl; return true; } + Trace("cdproof") << "existing proof " << pprev->getRule() + << ", overwrite..." << std::endl; // we will overwrite the existing proof node by updating its contents below } - // collect the child proofs, for each premise std::vector<std::shared_ptr<ProofNode>> pchildren; for (const Node& c : children) { - std::shared_ptr<ProofNode> pc = getProof(c); + Trace("cdproof") << "- get child " << c << std::endl; + std::shared_ptr<ProofNode> pc = getProofSymm(c); if (pc == nullptr) { if (ensureChildren) { // failed to get a proof for a child, fail + Trace("cdproof") << "...fail, no child" << std::endl; return false; } + Trace("cdproof") << "--- add assume" << std::endl; // otherwise, we initialize it as an assumption std::vector<Node> pcargs = {c}; std::vector<std::shared_ptr<ProofNode>> pcassume; @@ -82,37 +156,150 @@ bool CDProof::addStep(Node expected, pchildren.push_back(pc); } + // the user may have provided SYMM of an assumption + if (id == PfRule::SYMM) + { + Assert(pchildren.size() == 1); + if (isAssumption(pchildren[0].get())) + { + // the step we are constructing is a (symmetric fact of an) assumption, so + // there is no use adding it to the proof. + return true; + } + } + + bool ret = true; // create or update it std::shared_ptr<ProofNode> pthis; - if (it == d_nodes.end()) + if (pprev == nullptr) { + Trace("cdproof") << " new node " << expected << "..." << std::endl; pthis = d_manager->mkNode(id, pchildren, args, expected); if (pthis == nullptr) { // failed to construct the node, perhaps due to a proof checking failure + Trace("cdproof") << "...fail, proof checking" << std::endl; return false; } d_nodes.insert(expected, pthis); } else { + Trace("cdproof") << " update node " << expected << "..." << std::endl; // update its value - pthis = (*it).second; - d_manager->updateNode(pthis.get(), id, pchildren, args); + pthis = pprev; + // We return the value of updateNode here. This means this method may return + // false if this call failed, regardless of whether we already have a proof + // step for expected. + ret = d_manager->updateNode(pthis.get(), id, pchildren, args); + } + if (ret) + { + // the result of the proof node should be expected + Assert(pthis->getResult() == expected); + + // notify new proof + notifyNewProof(expected); + } + + Trace("cdproof") << "...return " << ret << std::endl; + return ret; +} + +void CDProof::notifyNewProof(Node expected) +{ + // ensure SYMM proof is also linked to an existing proof, if it is an + // assumption. + Node symExpected = getSymmFact(expected); + if (!symExpected.isNull()) + { + Trace("cdproof") << " check connect symmetry " << symExpected << std::endl; + // if it exists, we may need to update it + std::shared_ptr<ProofNode> pfs = getProof(symExpected); + if (pfs != nullptr) + { + Trace("cdproof") << " connect via getProofSymm method..." << std::endl; + // call the get function with symmetry, which will do the update + std::shared_ptr<ProofNode> pfss = getProofSymm(symExpected); + } + else + { + Trace("cdproof") << " no connect" << std::endl; + } + } +} + +bool CDProof::addStep(Node expected, + const ProofStep& step, + bool ensureChildren, + CDPOverwrite opolicy) +{ + return addStep(expected, + step.d_rule, + step.d_children, + step.d_args, + ensureChildren, + opolicy); +} + +bool CDProof::addSteps(const ProofStepBuffer& psb, + bool ensureChildren, + CDPOverwrite opolicy) +{ + const std::vector<std::pair<Node, ProofStep>>& steps = psb.getSteps(); + for (const std::pair<Node, ProofStep>& ps : steps) + { + if (!addStep(ps.first, ps.second, ensureChildren, opolicy)) + { + return false; + } } - // the result of the proof node should be expected - Assert(pthis->getResult() == expected); return true; } -bool CDProof::addProof(ProofNode* pn, bool forceOverwrite) +bool CDProof::addProof(std::shared_ptr<ProofNode> pn, + CDPOverwrite opolicy, + bool doCopy) { + if (!doCopy) + { + // If we aren't doing a deep copy, we either store pn or link its top + // node into the existing pointer + Node curFact = pn->getResult(); + std::shared_ptr<ProofNode> cur = getProofSymm(curFact); + if (cur == nullptr) + { + // Assert that the checker of this class agrees with (the externally + // provided) pn. This ensures that if pn was checked by a different + // checker than the one of the manager in this class, then it is double + // checked here, so that this class maintains the invariant that all of + // its nodes in d_nodes have been checked by the underlying checker. + Assert(d_manager->getChecker() == nullptr + || d_manager->getChecker()->check(pn.get(), curFact) == curFact); + // just store the proof for fact + d_nodes.insert(curFact, pn); + } + else if (shouldOverwrite(cur.get(), pn->getRule(), opolicy)) + { + // We update cur to have the structure of the top node of pn. Notice that + // the interface to update this node will ensure that the proof apf is a + // proof of the assumption. If it does not, then pn was wrong. + if (!d_manager->updateNode( + cur.get(), pn->getRule(), pn->getChildren(), pn->getArguments())) + { + return false; + } + } + // also need to connect via SYMM if necessary + notifyNewProof(curFact); + return true; + } std::unordered_map<ProofNode*, bool> visited; std::unordered_map<ProofNode*, bool>::iterator it; std::vector<ProofNode*> visit; ProofNode* cur; Node curFact; - visit.push_back(pn); + visit.push_back(pn.get()); bool retValue = true; do { @@ -143,12 +330,8 @@ bool CDProof::addProof(ProofNode* pn, bool forceOverwrite) pexp.push_back(c->getResult()); } // can ensure children at this point - bool res = addStep(curFact, - cur->getRule(), - pexp, - cur->getArguments(), - true, - forceOverwrite); + bool res = addStep( + curFact, cur->getRule(), pexp, cur->getArguments(), true, opolicy); // should always succeed Assert(res); retValue = retValue && res; @@ -159,4 +342,88 @@ bool CDProof::addProof(ProofNode* pn, bool forceOverwrite) return retValue; } +bool CDProof::hasStep(Node fact) +{ + std::shared_ptr<ProofNode> pf = getProof(fact); + if (pf != nullptr && !isAssumption(pf.get())) + { + return true; + } + Node symFact = getSymmFact(fact); + if (symFact.isNull()) + { + return false; + } + pf = getProof(symFact); + if (pf != nullptr && !isAssumption(pf.get())) + { + return true; + } + return false; +} + +ProofNodeManager* CDProof::getManager() const { return d_manager; } + +bool CDProof::shouldOverwrite(ProofNode* pn, PfRule newId, CDPOverwrite opol) +{ + Assert(pn != nullptr); + // we overwrite only if opol is CDPOverwrite::ALWAYS, or if + // opol is CDPOverwrite::ASSUME_ONLY and the previously + // provided proof pn was an assumption and the currently provided step is not + return opol == CDPOverwrite::ALWAYS + || (opol == CDPOverwrite::ASSUME_ONLY && isAssumption(pn) + && newId != PfRule::ASSUME); +} + +bool CDProof::isAssumption(ProofNode* pn) +{ + PfRule rule = pn->getRule(); + if (rule == PfRule::ASSUME) + { + return true; + } + else if (rule == PfRule::SYMM) + { + const std::vector<std::shared_ptr<ProofNode>>& pc = pn->getChildren(); + Assert(pc.size() == 1); + return pc[0]->getRule() == PfRule::ASSUME; + } + return false; +} + +bool CDProof::isSame(TNode f, TNode g) +{ + if (f == g) + { + return true; + } + Kind fk = f.getKind(); + Kind gk = g.getKind(); + if (fk == EQUAL && gk == EQUAL && f[0] == g[1] && f[1] == g[0]) + { + // symmetric equality + return true; + } + if (fk == NOT && gk == NOT && f[0][0] == g[0][1] && f[0][1] == g[0][0]) + { + // symmetric disequality + return true; + } + return false; +} + +Node CDProof::getSymmFact(TNode f) +{ + bool polarity = f.getKind() != NOT; + TNode fatom = polarity ? f : f[0]; + if (fatom.getKind() != EQUAL || fatom[0] == fatom[1]) + { + return Node::null(); + } + Node symFact = fatom[1].eqNode(fatom[0]); + return polarity ? symFact : symFact.notNode(); +} + +std::string CDProof::identify() const { return "CDProof"; } + } // namespace CVC4 diff --git a/src/expr/proof.h b/src/expr/proof.h index c3b9698ca..ff6b8bbf1 100644 --- a/src/expr/proof.h +++ b/src/expr/proof.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -22,8 +22,10 @@ #include "context/cdhashmap.h" #include "expr/node.h" +#include "expr/proof_generator.h" #include "expr/proof_node.h" #include "expr/proof_node_manager.h" +#include "expr/proof_step_buffer.h" namespace CVC4 { @@ -76,10 +78,11 @@ namespace CVC4 { * Notice that the proof of A by ID_A was not overwritten by ASSUME in the * addStep call above. * - * The policy for overwriting proof steps gives ASSUME a special status. An - * ASSUME step can be seen as a step whose justification has not yet been - * provided. Thus, it is always overwritten. Other proof rules are never - * overwritten, unless the argument forceOverwrite is true. + * The default policy for overwriting proof steps (CDPOverwrite::ASSUME_ONLY) + * gives ASSUME a special status. An ASSUME step can be seen as a step whose + * justification has not yet been provided. Thus, it is always overwritten. + * Other proof rules are never overwritten, unless the argument opolicy is + * CDPOverwrite::ALWAYS. * * As an another example, say that we call: * - addStep( B, ID_B1 {}, {} ) @@ -87,7 +90,7 @@ namespace CVC4 { * At this point, getProof( A ) returns: * ID_A1( ID_B1(), ASSUME(C) ) * Now, assume an additional call is made to addProof, where notice - * forceOverwrite is false by default: + * the overwrite policy is CDPOverwrite::ASSUME_ONLY by default: * - addProof( D, ID_D( ID_A2( ID_B2(), ID_C() ) ) ) * where assume ID_B2() and ID_C() prove B and C respectively. This call is * equivalent to calling: @@ -114,22 +117,39 @@ namespace CVC4 { * proof step for each Node. Thus, the ProofNode objects returned by this * class share proofs for common subformulas, as guaranteed by the fact that * Node objects have perfect sharing. + * + * Notice that this class is agnostic to symmetry of equality. In other + * words, adding a step that concludes (= x y) is effectively the same as + * providing a step that concludes (= y x) from the point of view of a user + * of this class. This is accomplished by adding SYMM steps on demand when + * a formula is looked up. For example say we call: + * - addStep( (= x y), ID_1 {}, {} ) + * - addStep( P, ID_2, {(= y x)}, {} ) + * Afterwards, getProof( P ) returns: + * ID_2( SYMM( ID_1() ) ) + * where notice SYMM was added so that (= y x) is a premise of the application + * of ID_2. More generally, CDProof::isSame(F,G) returns true if F and G are + * essentially the same formula according to this class. */ -class CDProof +class CDProof : public ProofGenerator { - typedef context::CDHashMap<Node, std::shared_ptr<ProofNode>, NodeHashFunction> - NodeProofNodeMap; - public: CDProof(ProofNodeManager* pnm, context::Context* c = nullptr); - ~CDProof(); + virtual ~CDProof(); /** - * Get proof for fact, or nullptr if it does not exist. Notice that this call - * does *not* clone the ProofNode object. Hence, the returned proof may - * be updated by further calls to this class. The caller should call - * ProofNode::clone if they want to own it. + * Make proof for fact. + * + * This method always returns a non-null ProofNode. It may generate new + * steps so that a ProofNode can be constructed for fact. In particular, + * if no step exists for fact, then we may construct and return ASSUME(fact). + * If fact is of the form (= t s), no step exists for fact, but a proof + * P for (= s t) exists, then this method returns SYMM(P). + * + * Notice that this call does *not* clone the ProofNode object. Hence, the + * returned proof may be updated by further calls to this class. The caller + * should call ProofNode::clone if they want to own it. */ - std::shared_ptr<ProofNode> getProof(Node fact) const; + std::shared_ptr<ProofNode> getProofFor(Node fact) override; /** Add step * * @param expected The intended conclusion of this proof step. This must be @@ -141,8 +161,8 @@ class CDProof * @param args The arguments of the proof step. * @param ensureChildren Whether we wish to ensure steps have been added * for all nodes in children - * @param forceOverwrite Whether we wish to overwrite if a step for expected - * was already provided (via a previous call to addStep) + * @param opolicy Policy for whether to overwrite if a step for + * expected was already provided (via a previous call to addStep) * @return The true if indeed the proof step proves expected, or * false otherwise. The latter can happen if the proof has a different (or * invalid) conclusion, or if one of the children does not have a proof and @@ -156,39 +176,87 @@ class CDProof * of order. * * This method only overwrites proofs for facts that were added as - * steps with id ASSUME when forceOverwrite is false, and otherwise always - * overwrites an existing step if one was provided when forceOverwrite is - * true. + * steps with id ASSUME when opolicy is CDPOverwrite::ASSUME_ONLY, and always + * (resp. never) overwrites an existing step if one was provided when opolicy + * is CDPOverwrite::ALWAYS (resp. CDPOverwrite::NEVER). */ bool addStep(Node expected, PfRule id, const std::vector<Node>& children, const std::vector<Node>& args, bool ensureChildren = false, - bool forceOverwrite = false); + CDPOverwrite opolicy = CDPOverwrite::ASSUME_ONLY); + /** Version with ProofStep */ + bool addStep(Node expected, + const ProofStep& step, + bool ensureChildren = false, + CDPOverwrite opolicy = CDPOverwrite::ASSUME_ONLY); + /** Version with ProofStepBuffer */ + bool addSteps(const ProofStepBuffer& psb, + bool ensureChildren = false, + CDPOverwrite opolicy = CDPOverwrite::ASSUME_ONLY); /** Add proof * * @param pn The proof of the given fact. - * @param forceOverwrite Whether we wish to force overwriting if a step was - * already provided, for each node in the proof. + * @param opolicy Policy for whether to force overwriting if a step + * was already provided. This is used for each node in the proof if doCopy + * is true. + * @param doCopy Whether we make a deep copy of the pn. * @return true if all steps were successfully added to this class. If it * returns true, it registers a copy of all of the subnodes of pn to this * proof class. * - * This method is implemented by calling addStep above for all subnodes - * of pn, traversed as a dag. This means that fresh ProofNode objects may be - * generated by this call, and further modifications to pn does not impact the - * internal data of this class. + * If doCopy is true, this method is implemented by calling addStep above for + * all subnodes of pn, traversed as a dag. This means that fresh ProofNode + * objects may be generated by this call, and further modifications to pn do + * not impact the internal data of this class. + */ + bool addProof(std::shared_ptr<ProofNode> pn, + CDPOverwrite opolicy = CDPOverwrite::ASSUME_ONLY, + bool doCopy = false); + /** Return true if fact already has a proof step */ + bool hasStep(Node fact); + /** Get the proof manager for this proof */ + ProofNodeManager* getManager() const; + /** + * Is same? Returns true if f and g are the same formula, or if they are + * symmetric equalities. If two nodes f and g are the same, then a proof for + * f suffices as a proof for g according to this class. + */ + static bool isSame(TNode f, TNode g); + /** + * Get symmetric fact (a g such that isSame returns true for isSame(f,g)), or + * null if none exist. */ - bool addProof(ProofNode* pn, bool forceOverwrite = false); + static Node getSymmFact(TNode f); + /** identify */ + std::string identify() const override; protected: + typedef context::CDHashMap<Node, std::shared_ptr<ProofNode>, NodeHashFunction> + NodeProofNodeMap; /** The proof manager, used for allocating new ProofNode objects */ ProofNodeManager* d_manager; /** A dummy context used by this class if none is provided */ context::Context d_context; /** The nodes of the proof */ NodeProofNodeMap d_nodes; + /** Get proof for fact, or nullptr if it does not exist. */ + std::shared_ptr<ProofNode> getProof(Node fact) const; + /** Ensure fact sym */ + std::shared_ptr<ProofNode> getProofSymm(Node fact); + /** + * Returns true if we should overwrite proof node pn with a step having id + * newId, based on policy opol. + */ + static bool shouldOverwrite(ProofNode* pn, PfRule newId, CDPOverwrite opol); + /** Returns true if pn is an assumption. */ + static bool isAssumption(ProofNode* pn); + /** + * Notify new proof, called when a new proof of expected is provided. This is + * used internally to connect proofs of symmetric facts, when necessary. + */ + void notifyNewProof(Node expected); }; } // namespace CVC4 diff --git a/src/expr/proof_checker.cpp b/src/expr/proof_checker.cpp index 7e7a26c5b..acbf6ee49 100644 --- a/src/expr/proof_checker.cpp +++ b/src/expr/proof_checker.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -14,7 +14,7 @@ #include "expr/proof_checker.h" -#include "expr/proof_skolem_cache.h" +#include "expr/skolem_manager.h" #include "smt/smt_statistics_registry.h" using namespace CVC4::kind; @@ -28,11 +28,11 @@ Node ProofRuleChecker::check(PfRule id, // convert to witness form std::vector<Node> childrenw = children; std::vector<Node> argsw = args; - ProofSkolemCache::convertToWitnessFormVec(childrenw); - ProofSkolemCache::convertToWitnessFormVec(argsw); + SkolemManager::convertToWitnessFormVec(childrenw); + SkolemManager::convertToWitnessFormVec(argsw); Node res = checkInternal(id, childrenw, argsw); // res is in terms of witness form, convert back to Skolem form - return ProofSkolemCache::getSkolemForm(res); + return SkolemManager::getSkolemForm(res); } Node ProofRuleChecker::checkChildrenArg(PfRule id, @@ -92,14 +92,17 @@ bool ProofRuleChecker::getBool(TNode n, bool& b) } ProofCheckerStatistics::ProofCheckerStatistics() - : d_ruleChecks("ProofCheckerStatistics::ruleChecks") + : d_ruleChecks("ProofCheckerStatistics::ruleChecks"), + d_totalRuleChecks("ProofCheckerStatistics::totalRuleChecks", 0) { smtStatisticsRegistry()->registerStat(&d_ruleChecks); + smtStatisticsRegistry()->registerStat(&d_totalRuleChecks); } ProofCheckerStatistics::~ProofCheckerStatistics() { smtStatisticsRegistry()->unregisterStat(&d_ruleChecks); + smtStatisticsRegistry()->unregisterStat(&d_totalRuleChecks); } Node ProofChecker::check(ProofNode* pn, Node expected) @@ -123,6 +126,7 @@ Node ProofChecker::check( } // record stat d_stats.d_ruleChecks << id; + ++d_stats.d_totalRuleChecks; Trace("pfcheck") << "ProofChecker::check: " << id << std::endl; std::vector<Node> cchildren; for (const std::shared_ptr<ProofNode>& pc : children) @@ -183,6 +187,8 @@ Node ProofChecker::checkDebug(PfRule id, { Trace(traceTag) << " success" << std::endl; } + Trace(traceTag) << "cchildren: " << cchildren << std::endl; + Trace(traceTag) << " args: " << args << std::endl; return res; } diff --git a/src/expr/proof_checker.h b/src/expr/proof_checker.h index 99c02b8dc..d6d77df2b 100644 --- a/src/expr/proof_checker.h +++ b/src/expr/proof_checker.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -77,7 +77,7 @@ class ProofRuleChecker /** * This checks a single step in a proof. It is identical to check above * except that children and args have been converted to "witness form" - * (see ProofSkolemCache). Likewise, its output should be in witness form. + * (see SkolemManager). Likewise, its output should be in witness form. * * @param id The id of the proof node to check * @param children The premises of the proof node to check. These are nodes @@ -100,6 +100,8 @@ class ProofCheckerStatistics ~ProofCheckerStatistics(); /** Counts the number of checks for each kind of proof rule */ HistogramStat<PfRule> d_ruleChecks; + /** Total number of rule checks */ + IntStat d_totalRuleChecks; }; /** A class for checking proofs */ diff --git a/src/expr/proof_generator.cpp b/src/expr/proof_generator.cpp new file mode 100644 index 000000000..fd8f50415 --- /dev/null +++ b/src/expr/proof_generator.cpp @@ -0,0 +1,74 @@ +/********************* */ +/*! \file proof_generator.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 generator utility + **/ + +#include "expr/proof_generator.h" + +#include "expr/proof.h" + +namespace CVC4 { + +std::ostream& operator<<(std::ostream& out, CDPOverwrite opol) +{ + switch (opol) + { + case CDPOverwrite::ALWAYS: out << "ALWAYS"; break; + case CDPOverwrite::ASSUME_ONLY: out << "ASSUME_ONLY"; break; + case CDPOverwrite::NEVER: out << "NEVER"; break; + default: out << "CDPOverwrite:unknown"; break; + } + return out; +} + +ProofGenerator::ProofGenerator() {} + +ProofGenerator::~ProofGenerator() {} + +std::shared_ptr<ProofNode> ProofGenerator::getProofFor(Node f) +{ + Unreachable() << "ProofGenerator::getProofFor: " << identify() + << " has no implementation" << std::endl; + return nullptr; +} + +bool ProofGenerator::addProofTo(Node f, CDProof* pf, CDPOverwrite opolicy) +{ + Trace("pfgen") << "ProofGenerator::addProofTo: " << f << "..." << std::endl; + Assert(pf != nullptr); + // plug in the proof provided by the generator, if it exists + std::shared_ptr<ProofNode> apf = getProofFor(f); + if (apf != nullptr) + { + if (Trace.isOn("pfgen")) + { + std::stringstream ss; + apf->printDebug(ss); + Trace("pfgen") << "...got proof " << ss.str() << std::endl; + } + // Add the proof, without deep copying. + if (pf->addProof(apf, opolicy, false)) + { + Trace("pfgen") << "...success!" << std::endl; + return true; + } + Trace("pfgen") << "...failed to add proof" << std::endl; + } + else + { + Trace("pfgen") << "...failed, no proof" << std::endl; + Assert(false) << "Failed to get proof from generator for fact " << f; + } + return false; +} + +} // namespace CVC4 diff --git a/src/expr/proof_generator.h b/src/expr/proof_generator.h new file mode 100644 index 000000000..35f94194f --- /dev/null +++ b/src/expr/proof_generator.h @@ -0,0 +1,110 @@ +/********************* */ +/*! \file proof_generator.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 abstract proof generator class + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__EXPR__PROOF_GENERATOR_H +#define CVC4__EXPR__PROOF_GENERATOR_H + +#include "expr/node.h" +#include "expr/proof_node.h" + +namespace CVC4 { + +class CDProof; + +/** An overwrite policy for CDProof */ +enum class CDPOverwrite : uint32_t +{ + // always overwrite an existing step. + ALWAYS, + // overwrite ASSUME with non-ASSUME steps. + ASSUME_ONLY, + // never overwrite an existing step. + NEVER, +}; +/** Writes a overwrite policy name to a stream. */ +std::ostream& operator<<(std::ostream& out, CDPOverwrite opol); + +/** + * An abstract proof generator class. + * + * A proof generator is intended to be used as a utility e.g. in theory + * solvers for constructing and storing proofs internally. A theory may have + * multiple instances of ProofGenerator objects, e.g. if it has more than one + * way of justifying lemmas or conflicts. + * + * A proof generator has two main interfaces for generating proofs: + * (1) getProofFor, and (2) addProofTo. The latter is optional. + * + * The addProofTo method can be used as an optimization for avoiding + * the construction of the ProofNode for a given fact. + * + * If no implementation of addProofTo is provided, then addProofTo(f, pf) + * calls getProofFor(f) and links the topmost ProofNode of the returned proof + * into pf. Note this top-most ProofNode can be avoided in the addProofTo + * method. + */ +class ProofGenerator +{ + public: + ProofGenerator(); + virtual ~ProofGenerator(); + /** Get the proof for formula f + * + * This forces the proof generator to construct a proof for formula f and + * return it. If this is an "eager" proof generator, this function is expected + * to be implemented as a map lookup. If this is a "lazy" proof generator, + * this function is expected to invoke a proof producing procedure of the + * generator. + * + * It should be the case that hasProofFor(f) is true. + * + * @param f The fact to get the proof for. + * @return The proof for f. + */ + virtual std::shared_ptr<ProofNode> getProofFor(Node f); + /** + * Add the proof for formula f to proof pf. The proof of f is overwritten in + * pf based on the policy opolicy. + * + * @param f The fact to get the proof for. + * @param pf The CDProof object to add the proof to. + * @param opolicy The overwrite policy for adding to pf. + * @return True if this call was sucessful. + */ + virtual bool addProofTo(Node f, + CDProof* pf, + CDPOverwrite opolicy = CDPOverwrite::ASSUME_ONLY); + /** + * Can we give the proof for formula f? This is used for debugging. This + * returns false if the generator cannot provide a proof of formula f. + * + * Also notice that this function does not require the proof for f to be + * constructed at the time of this call. Thus, if this is a "lazy" proof + * generator, it is expected that this call is implemented as a map lookup + * into the bookkeeping maintained by the generator only. + * + * Notice the default return value is true. In other words, a proof generator + * may choose to override this function to verify the construction, although + * we do not insist this is the case. + */ + virtual bool hasProofFor(Node f) { return true; } + /** Identify this generator (for debugging, etc..) */ + virtual std::string identify() const = 0; +}; + +} // namespace CVC4 + +#endif /* CVC4__EXPR__PROOF_GENERATOR_H */ diff --git a/src/expr/proof_node.cpp b/src/expr/proof_node.cpp index b5e391049..d817cbd65 100644 --- a/src/expr/proof_node.cpp +++ b/src/expr/proof_node.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -14,6 +14,9 @@ #include "expr/proof_node.h" +#include "expr/proof_node_algorithm.h" +#include "expr/proof_node_to_sexpr.h" + namespace CVC4 { ProofNode::ProofNode(PfRule id, @@ -34,71 +37,24 @@ const std::vector<Node>& ProofNode::getArguments() const { return d_args; } Node ProofNode::getResult() const { return d_proven; } -void ProofNode::getFreeAssumptions(std::vector<Node>& assump) const +bool ProofNode::isClosed() { - // visited set false after preorder traversal, true after postorder traversal - std::unordered_map<const ProofNode*, bool> visited; - std::unordered_map<const ProofNode*, bool>::iterator it; - std::vector<const ProofNode*> visit; - // the current set of formulas bound by SCOPE - std::unordered_set<Node, NodeHashFunction> currentScope; - const ProofNode* cur; - visit.push_back(this); - do - { - cur = visit.back(); - visit.pop_back(); - it = visited.find(cur); - if (it == visited.end()) - { - visited[cur] = true; - PfRule id = cur->getRule(); - if (id == PfRule::ASSUME) - { - Assert(cur->d_args.size() == 1); - Node f = cur->d_args[0]; - if (currentScope.find(f) == currentScope.end()) - { - assump.push_back(f); - } - } - else - { - if (id == PfRule::SCOPE) - { - // mark that its arguments are bound in the current scope - for (const Node& a : cur->d_args) - { - // should not have assumption shadowing - Assert(currentScope.find(a) != currentScope.end()); - currentScope.insert(a); - } - // will need to unbind the variables below - visited[cur] = false; - } - for (const std::shared_ptr<ProofNode>& cp : cur->d_children) - { - visit.push_back(cp.get()); - } - } - } - else if (!it->second) - { - Assert(cur->getRule() == PfRule::SCOPE); - // unbind its assumptions - for (const Node& a : cur->d_args) - { - currentScope.erase(a); - } - } - } while (!visit.empty()); + std::vector<Node> assumps; + expr::getFreeAssumptions(this, assumps); + return assumps.empty(); } -bool ProofNode::isClosed() const +std::shared_ptr<ProofNode> ProofNode::clone() const { - std::vector<Node> assumps; - getFreeAssumptions(assumps); - return assumps.empty(); + std::vector<std::shared_ptr<ProofNode>> cchildren; + for (const std::shared_ptr<ProofNode>& cp : d_children) + { + cchildren.push_back(cp->clone()); + } + std::shared_ptr<ProofNode> thisc = + std::make_shared<ProofNode>(d_rule, cchildren, d_args); + thisc->d_proven = d_proven; + return thisc; } void ProofNode::setValue( @@ -113,17 +69,10 @@ void ProofNode::setValue( void ProofNode::printDebug(std::ostream& os) const { - os << "(" << d_rule; - for (const std::shared_ptr<ProofNode>& c : d_children) - { - os << " "; - c->printDebug(os); - } - if (!d_args.empty()) - { - os << " :args " << d_args; - } - os << ")"; + // convert to sexpr and print + ProofNodeToSExpr pnts; + Node ps = pnts.convertToSExpr(this); + os << ps; } } // namespace CVC4 diff --git a/src/expr/proof_node.h b/src/expr/proof_node.h index c3f1719e7..bca86f44f 100644 --- a/src/expr/proof_node.h +++ b/src/expr/proof_node.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -45,6 +45,33 @@ class ProofNodeManager; * ProofNode objects in trusted ways that ensure that the node maintains * the invariant above. Furthermore, notice that this class is not responsible * for setting d_proven; this is done externally by a ProofNodeManager class. + * + * Notice that all fields of ProofNode are stored in ***Skolem form***. Their + * correctness is checked in ***witness form*** (for details on this + * terminology, see expr/skolem_manager.h). As a simple example, say a + * theory solver has a term t, and wants to introduce a unit lemma (= k t) + * where k is a fresh Skolem variable. It creates this variable via: + * k = SkolemManager::mkPurifySkolem(t,"k"); + * A checked ProofNode for the fact (= k t) then may have fields: + * d_rule := MACRO_SR_PRED_INTRO, + * d_children := {}, + * d_args := {(= k t)} + * d_proven := (= k t). + * Its justification via the rule MACRO_SR_PRED_INTRO (see documentation + * in theory/builtin/proof_kinds) is in terms of the witness form of the + * argument: + * (= (witness ((z T)) (= z t)) t) + * which, by that rule's side condition, is such that: + * Rewriter::rewrite((= (witness ((z T)) (= z t)) t)) = true. + * Notice that the correctness of the rule is justified here by rewriting + * the witness form of (= k t). The conversion to/from witness form is + * managed by ProofRuleChecker::check. + * + * An external proof checker is expected to formalize the ProofNode only in + * terms of *witness* forms. + * + * However, the rest of CVC4 sees only the *Skolem* form of arguments and + * conclusions in ProofNode, since this is what is used throughout CVC4. */ class ProofNode { @@ -64,22 +91,13 @@ class ProofNode /** get what this node proves, or the null node if this is an invalid proof */ Node getResult() const; /** - * This adds to the vector assump all formulas that are "free assumptions" of - * the proof whose root is this ProofNode. A free assumption is a formula F - * that is an argument (in d_args) of a ProofNode whose kind is ASSUME, and - * that proof node is not beneath an application of SCOPE containing F as an - * argument. - * - * This traverses the structure of the dag represented by this ProofNode. - * Its implementation is analogous to expr::getFreeVariables. - */ - void getFreeAssumptions(std::vector<Node>& assump) const; - /** * Returns true if this is a closed proof (i.e. it has no free assumptions). */ - bool isClosed() const; + bool isClosed(); /** Print debug on output strem os */ void printDebug(std::ostream& os) const; + /** Clone, create a deep copy of this */ + std::shared_ptr<ProofNode> clone() const; private: /** diff --git a/src/expr/proof_node_algorithm.cpp b/src/expr/proof_node_algorithm.cpp new file mode 100644 index 000000000..45dc2d995 --- /dev/null +++ b/src/expr/proof_node_algorithm.cpp @@ -0,0 +1,118 @@ +/********************* */ +/*! \file proof_node_algorithm.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 node algorithm utilities + **/ + +#include "expr/proof_node_algorithm.h" + +namespace CVC4 { +namespace expr { + +void getFreeAssumptions(ProofNode* pn, std::vector<Node>& assump) +{ + std::map<Node, std::vector<ProofNode*>> amap; + getFreeAssumptionsMap(pn, amap); + for (const std::pair<const Node, std::vector<ProofNode*>>& p : amap) + { + assump.push_back(p.first); + } +} + +void getFreeAssumptionsMap(ProofNode* pn, + std::map<Node, std::vector<ProofNode*>>& amap) +{ + // proof should not be cyclic + // visited set false after preorder traversal, true after postorder traversal + std::unordered_map<ProofNode*, bool> visited; + std::unordered_map<ProofNode*, bool>::iterator it; + std::vector<ProofNode*> visit; + // Maps a bound assumption to the number of bindings it is under + // e.g. in (SCOPE (SCOPE (ASSUME x) (x y)) (y)), y would be mapped to 2 at + // (ASSUME x), and x would be mapped to 1. + // + // This map is used to track which nodes are in scope while traversing the + // DAG. The in-scope assumptions are keys in the map. They're removed when + // their binding count drops to zero. Let's annotate the above example to + // serve as an illustration: + // + // (SCOPE0 (SCOPE1 (ASSUME x) (x y)) (y)) + // + // This is how the map changes during the traversal: + // after previsiting SCOPE0: { y: 1 } + // after previsiting SCOPE1: { y: 2, x: 1 } + // at ASSUME: { y: 2, x: 1 } (so x is in scope!) + // after postvisiting SCOPE1: { y: 1 } + // after postvisiting SCOPE2: {} + // + std::unordered_map<Node, uint32_t, NodeHashFunction> scopeDepth; + ProofNode* cur; + visit.push_back(pn); + do + { + cur = visit.back(); + visit.pop_back(); + it = visited.find(cur); + const std::vector<Node>& cargs = cur->getArguments(); + if (it == visited.end()) + { + visited[cur] = true; + PfRule id = cur->getRule(); + if (id == PfRule::ASSUME) + { + Assert(cargs.size() == 1); + Node f = cargs[0]; + if (!scopeDepth.count(f)) + { + amap[f].push_back(cur); + } + } + else + { + if (id == PfRule::SCOPE) + { + // mark that its arguments are bound in the current scope + for (const Node& a : cargs) + { + scopeDepth[a] += 1; + } + // will need to unbind the variables below + visited[cur] = false; + } + // The following loop cannot be merged with the loop above because the + // same subproof + const std::vector<std::shared_ptr<ProofNode>>& cs = cur->getChildren(); + for (const std::shared_ptr<ProofNode>& cp : cs) + { + visit.push_back(cp.get()); + } + } + } + else if (!it->second) + { + Assert(cur->getRule() == PfRule::SCOPE); + // unbind its assumptions + for (const Node& a : cargs) + { + auto scopeCt = scopeDepth.find(a); + Assert(scopeCt != scopeDepth.end()); + scopeCt->second -= 1; + if (scopeCt->second == 0) + { + scopeDepth.erase(scopeCt); + } + } + } + } while (!visit.empty()); +} + +} // namespace expr +} // namespace CVC4 diff --git a/src/expr/proof_node_algorithm.h b/src/expr/proof_node_algorithm.h new file mode 100644 index 000000000..bc44d7314 --- /dev/null +++ b/src/expr/proof_node_algorithm.h @@ -0,0 +1,58 @@ +/********************* */ +/*! \file proof_node_algorithm.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 node algorithm utilities. + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__EXPR__PROOF_NODE_ALGORITHM_H +#define CVC4__EXPR__PROOF_NODE_ALGORITHM_H + +#include <vector> + +#include "expr/node.h" +#include "expr/proof_node.h" + +namespace CVC4 { +namespace expr { + +/** + * This adds to the vector assump all formulas that are "free assumptions" of + * the proof whose root is ProofNode pn. A free assumption is a formula F + * that is an argument (in d_args) of a ProofNode whose kind is ASSUME, and + * that proof node is not beneath an application of SCOPE containing F as an + * argument. + * + * This traverses the structure of the dag represented by this ProofNode. + * Its implementation is analogous to expr::getFreeVariables. + * + * @param pn The proof node. + * @param assump The vector to add the free asumptions of pn to. + */ +void getFreeAssumptions(ProofNode* pn, std::vector<Node>& assump); +/** + * Same as above, but maps assumptions to the proof pointer(s) for that + * assumption. Notice that depending on how pn is constructed, there may be + * multiple ProofNode that are ASSUME proofs of the same assumption, which + * are each added to the range of the assumption. + * + * @param pn The proof node. + * @param amap The mapping to add the free asumptions of pn and their + * corresponding proof nodes to. + */ +void getFreeAssumptionsMap(ProofNode* pn, + std::map<Node, std::vector<ProofNode*>>& amap); + +} // namespace expr +} // namespace CVC4 + +#endif /* CVC4__EXPR__PROOF_NODE_ALGORITHM_H */ diff --git a/src/expr/proof_node_manager.cpp b/src/expr/proof_node_manager.cpp index e2f5ca2dc..078e918b8 100644 --- a/src/expr/proof_node_manager.cpp +++ b/src/expr/proof_node_manager.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -14,6 +14,9 @@ #include "expr/proof_node_manager.h" +#include "expr/proof.h" +#include "expr/proof_node_algorithm.h" + using namespace CVC4::kind; namespace CVC4 { @@ -39,27 +42,145 @@ std::shared_ptr<ProofNode> ProofNodeManager::mkNode( return pn; } +std::shared_ptr<ProofNode> ProofNodeManager::mkAssume(Node fact) +{ + Assert(!fact.isNull()); + Assert(fact.getType().isBoolean()); + return mkNode(PfRule::ASSUME, {}, {fact}, fact); +} + +std::shared_ptr<ProofNode> ProofNodeManager::mkScope( + std::shared_ptr<ProofNode> pf, + std::vector<Node>& assumps, + bool ensureClosed, + bool doMinimize, + Node expected) +{ + if (!ensureClosed) + { + return mkNode(PfRule::SCOPE, {pf}, assumps, expected); + } + Trace("pnm-scope") << "ProofNodeManager::mkScope " << assumps << std::endl; + // we first ensure the assumptions are flattened + std::unordered_set<Node, NodeHashFunction> ac{assumps.begin(), assumps.end()}; + + // The free assumptions of the proof + std::map<Node, std::vector<ProofNode*>> famap; + expr::getFreeAssumptionsMap(pf.get(), famap); + std::unordered_set<Node, NodeHashFunction> acu; + for (const std::pair<const Node, std::vector<ProofNode*>>& fa : famap) + { + Node a = fa.first; + if (ac.find(a) != ac.end()) + { + // already covered by an assumption + acu.insert(a); + continue; + } + Trace("pnm-scope") << "- try matching free assumption " << a << "\n"; + // otherwise it may be due to symmetry? + Node aeqSym = CDProof::getSymmFact(a); + Trace("pnm-scope") << " - try sym " << aeqSym << "\n"; + if (!aeqSym.isNull()) + { + if (ac.count(aeqSym)) + { + Trace("pnm-scope") << "- reorient assumption " << aeqSym << " via " << a + << " for " << fa.second.size() << " proof nodes" + << std::endl; + std::shared_ptr<ProofNode> pfaa = mkAssume(aeqSym); + for (ProofNode* pfs : fa.second) + { + Assert(pfs->getResult() == a); + // must correct the orientation on this leaf + std::vector<std::shared_ptr<ProofNode>> children; + children.push_back(pfaa); + std::vector<Node> args; + args.push_back(a); + updateNode(pfs, PfRule::MACRO_SR_PRED_TRANSFORM, children, args); + } + Trace("pnm-scope") << "...finished" << std::endl; + acu.insert(aeqSym); + continue; + } + } + // All free assumptions should be arguments to SCOPE. + std::stringstream ss; + pf->printDebug(ss); + ss << std::endl << "Free assumption: " << a << std::endl; + for (const Node& aprint : ac) + { + ss << "- assumption: " << aprint << std::endl; + } + Unreachable() << "Generated a proof that is not closed by the scope: " + << ss.str() << std::endl; + } + if (acu.size() < ac.size()) + { + // All assumptions should match a free assumption; if one does not, then + // the explanation could have been smaller. + for (const Node& a : ac) + { + if (acu.find(a) == acu.end()) + { + Notice() << "ProofNodeManager::mkScope: assumption " << a + << " does not match a free assumption in proof" << std::endl; + } + } + } + if (doMinimize && acu.size() < ac.size()) + { + assumps.clear(); + assumps.insert(assumps.end(), acu.begin(), acu.end()); + } + else if (ac.size() < assumps.size()) + { + // remove duplicates to avoid redundant literals in clauses + assumps.clear(); + assumps.insert(assumps.end(), ac.begin(), ac.end()); + } + Node minExpected; + NodeManager* nm = NodeManager::currentNM(); + Node exp; + Node conc = pf->getResult(); + if (assumps.empty()) + { + Assert(!conc.isConst()); + minExpected = conc; + } + else + { + exp = assumps.size() == 1 ? assumps[0] : nm->mkNode(AND, assumps); + if (conc.isConst() && !conc.getConst<bool>()) + { + minExpected = exp.notNode(); + } + else + { + minExpected = nm->mkNode(IMPLIES, exp, conc); + } + } + return mkNode(PfRule::SCOPE, {pf}, assumps, minExpected); +} + bool ProofNodeManager::updateNode( ProofNode* pn, PfRule id, const std::vector<std::shared_ptr<ProofNode>>& children, const std::vector<Node>& args) { - // should have already computed what is proven - Assert(!pn->d_proven.isNull()) - << "ProofNodeManager::updateProofNode: invalid proof provided"; - // We expect to prove the same thing as before - Node res = checkInternal(id, children, args, pn->d_proven); - if (res.isNull()) + return updateNodeInternal(pn, id, children, args, true); +} + +bool ProofNodeManager::updateNode(ProofNode* pn, ProofNode* pnr) +{ + if (pn->getResult() != pnr->getResult()) { - // if it was invalid, then we do not update return false; } - // we update its value - pn->setValue(id, children, args); - // proven field should already be the same as the result - Assert(res == pn->d_proven); - return true; + // can shortcut re-check of rule + return updateNodeInternal( + pn, pnr->getRule(), pnr->getChildren(), pnr->getArguments(), false); } Node ProofNodeManager::checkInternal( @@ -86,4 +207,77 @@ Node ProofNodeManager::checkInternal( return res; } +ProofChecker* ProofNodeManager::getChecker() const { return d_checker; } + +bool ProofNodeManager::updateNodeInternal( + ProofNode* pn, + PfRule id, + const std::vector<std::shared_ptr<ProofNode>>& children, + const std::vector<Node>& args, + bool needsCheck) +{ + // ---------------- check for cyclic + std::unordered_map<const ProofNode*, bool> visited; + std::unordered_map<const ProofNode*, bool>::iterator it; + std::vector<const ProofNode*> visit; + for (const std::shared_ptr<ProofNode>& cp : children) + { + visit.push_back(cp.get()); + } + const ProofNode* cur; + while (!visit.empty()) + { + cur = visit.back(); + visit.pop_back(); + it = visited.find(cur); + if (it == visited.end()) + { + visited[cur] = true; + if (cur == pn) + { + std::stringstream ss; + ss << "ProofNodeManager::updateNode: attempting to make cyclic proof! " + << id << " " << pn->getResult() << ", children = " << std::endl; + for (const std::shared_ptr<ProofNode>& cp : children) + { + ss << " " << cp->getRule() << " " << cp->getResult() << std::endl; + } + ss << "Full children:" << std::endl; + for (const std::shared_ptr<ProofNode>& cp : children) + { + ss << " - "; + cp->printDebug(ss); + ss << std::endl; + } + Unreachable() << ss.str(); + } + for (const std::shared_ptr<ProofNode>& cp : cur->d_children) + { + visit.push_back(cp.get()); + } + } + } + // ---------------- end check for cyclic + + // should have already computed what is proven + Assert(!pn->d_proven.isNull()) + << "ProofNodeManager::updateProofNode: invalid proof provided"; + if (needsCheck) + { + // We expect to prove the same thing as before + Node res = checkInternal(id, children, args, pn->d_proven); + if (res.isNull()) + { + // if it was invalid, then we do not update + return false; + } + // proven field should already be the same as the result + Assert(res == pn->d_proven); + } + + // we update its value + pn->setValue(id, children, args); + return true; +} + } // namespace CVC4 diff --git a/src/expr/proof_node_manager.h b/src/expr/proof_node_manager.h index 17c5580bf..774177d66 100644 --- a/src/expr/proof_node_manager.h +++ b/src/expr/proof_node_manager.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -74,6 +74,52 @@ class ProofNodeManager const std::vector<Node>& args, Node expected = Node::null()); /** + * Make the proof node corresponding to the assumption of fact. + * + * @param fact The fact to assume. + * @return The ASSUME proof of fact. + */ + std::shared_ptr<ProofNode> mkAssume(Node fact); + /** + * Make scope having body pf and arguments (assumptions-to-close) assumps. + * If ensureClosed is true, then this method throws an assertion failure if + * the returned proof is not closed. This is the case if a free assumption + * of pf is missing from the vector assumps. + * + * For conveinence, the proof pf may be modified to ensure that the overall + * result is closed. For instance, given input: + * pf = TRANS( ASSUME( x=y ), ASSUME( y=z ) ) + * assumps = { y=x, y=z } + * This method will modify pf to be: + * pf = TRANS( SYMM( ASSUME( y=x ) ), ASSUME( y=z ) ) + * so that y=x matches the free assumption. The returned proof is: + * SCOPE(TRANS( SYMM( ASSUME( y=x ) ), ASSUME( y=z ) ) :args { y=x, y=z }) + * + * When ensureClosed is true, duplicates are eliminated from assumps. The + * reason for this is due to performance, since in this method, assumps is + * converted to an unordered_set to do the above check and hence it is a + * convienient time to eliminate duplicate literals. + * + * Additionally, if both ensureClosed and doMinimize are true, assumps is + * updated to contain exactly the free asumptions of pf. This also includes + * having no duplicates. + * + * In each case, the update vector assumps is passed as arguments to SCOPE. + * + * @param pf The body of the proof, + * @param assumps The assumptions-to-close of the scope, + * @param ensureClosed Whether to ensure that the proof is closed, + * @param doMinimize Whether to minimize assumptions. + * @param expected the node that the scope should prove. + * @return The scoped proof. + */ + std::shared_ptr<ProofNode> mkScope(std::shared_ptr<ProofNode> pf, + std::vector<Node>& assumps, + bool ensureClosed = true, + bool doMinimize = false, + Node expected = Node::null()); + + /** * This method updates pn to be a proof of the form <id>( children, args ), * while maintaining its d_proven field. This method returns false if this * proof manager is using a checker, and we compute that the above proof @@ -92,6 +138,14 @@ class ProofNodeManager PfRule id, const std::vector<std::shared_ptr<ProofNode>>& children, const std::vector<Node>& args); + /** + * Update node pn to have the contents of pnr. It should be the case that + * pn and pnr prove the same fact, otherwise false is returned and pn is + * unchanged. + */ + bool updateNode(ProofNode* pn, ProofNode* pnr); + /** Get the underlying proof checker */ + ProofChecker* getChecker() const; private: /** The (optional) proof checker */ @@ -110,6 +164,18 @@ class ProofNodeManager const std::vector<std::shared_ptr<ProofNode>>& children, const std::vector<Node>& args, Node expected); + /** + * Update node internal, return true if successful. This is called by + * the update node methods above. The argument needsCheck is whether we + * need to check the correctness of the rule application. This is false + * for the updateNode routine where pnr is an (already checked) proof node. + */ + bool updateNodeInternal( + ProofNode* pn, + PfRule id, + const std::vector<std::shared_ptr<ProofNode>>& children, + const std::vector<Node>& args, + bool needsCheck); }; } // namespace CVC4 diff --git a/src/expr/proof_node_to_sexpr.cpp b/src/expr/proof_node_to_sexpr.cpp index cf58daa3a..c6bde49fd 100644 --- a/src/expr/proof_node_to_sexpr.cpp +++ b/src/expr/proof_node_to_sexpr.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/proof_node_to_sexpr.h b/src/expr/proof_node_to_sexpr.h index 3a5cd566a..1f38f4cad 100644 --- a/src/expr/proof_node_to_sexpr.h +++ b/src/expr/proof_node_to_sexpr.h @@ -1,10 +1,10 @@ /********************* */ -/*! \file proof_to_sexpr.h +/*! \file proof_node_to_sexpr.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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/proof_rule.cpp b/src/expr/proof_rule.cpp index e555f5691..d00f1658b 100644 --- a/src/expr/proof_rule.cpp +++ b/src/expr/proof_rule.cpp @@ -2,9 +2,9 @@ /*! \file proof_rule.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Haniel Barbosa, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -25,7 +25,78 @@ 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"; + //================================================= 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"; + //================================================= 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"; + //================================================= Quantifiers rules + case PfRule::WITNESS_INTRO: return "WITNESS_INTRO"; + case PfRule::EXISTS_INTRO: return "EXISTS_INTRO"; + case PfRule::SKOLEMIZE: return "SKOLEMIZE"; + case PfRule::INSTANTIATE: return "INSTANTIATE"; + //================================================= Arith rules + case PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS: return "ARITH_SCALE_SUM_UPPER_BOUNDS"; + case PfRule::ARITH_TRICHOTOMY: return "ARITH_TRICHOTOMY"; + case PfRule::INT_TIGHT_LB: return "INT_TIGHT_LB"; + case PfRule::INT_TIGHT_UB: return "INT_TIGHT_UB"; + case PfRule::INT_TRUST: return "INT_TRUST"; + case PfRule::ARITH_OP_ELIM_AXIOM: return "ARITH_OP_ELIM_AXIOM"; //================================================= 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..ec589a16e 100644 --- a/src/expr/proof_rule.h +++ b/src/expr/proof_rule.h @@ -2,9 +2,9 @@ /*! \file proof_rule.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Haniel Barbosa, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -72,6 +72,505 @@ enum class PfRule : uint32_t // proof with no free assumptions always concludes a valid formula. SCOPE, + //======================== 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, + + //================================================= 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, + + //================================================= 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, + + //================================================= Quantifiers rules + // ======== Witness intro + // Children: (P:F[t]) + // Arguments: (t) + // ---------------------------------------- + // Conclusion: (= t (witness ((x T)) F[x])) + // where x is a BOUND_VARIABLE unique to the pair F,t. + WITNESS_INTRO, + // ======== Exists intro + // Children: (P:F[t]) + // Arguments: (t) + // ---------------------------------------- + // Conclusion: (exists ((x T)) F[x]) + // where x is a BOUND_VARIABLE unique to the pair F,t. + EXISTS_INTRO, + // ======== Skolemize + // Children: (P:(exists ((x1 T1) ... (xn Tn)) F)) + // Arguments: none + // ---------------------------------------- + // Conclusion: F*sigma + // sigma maps x1 ... xn to their representative skolems obtained by + // SkolemManager::mkSkolemize, returned in the skolems argument of that + // method. + SKOLEMIZE, + // ======== Instantiate + // Children: (P:(forall ((x1 T1) ... (xn Tn)) F)) + // Arguments: (t1 ... tn) + // ---------------------------------------- + // Conclusion: F*sigma + // sigma maps x1 ... xn to t1 ... tn. + INSTANTIATE, + + // ======== Adding Inequalities + // Note: an ArithLiteral is a term of the form (>< poly const) + // where + // >< is >=, >, ==, <, <=, or not(== ...). + // poly is a polynomial + // const is a rational constant + + // Children: (P1:l1, ..., Pn:ln) + // where each li is an ArithLiteral + // not(= ...) is dis-allowed! + // + // Arguments: (k1, ..., kn), non-zero reals + // --------------------- + // Conclusion: (>< (* k t1) (* k t2)) + // where >< is the fusion of the combination of the ><i, (flipping each it + // its ki is negative). >< is always one of <, <= + // NB: this implies that lower bounds must have negative ki, + // and upper bounds must have positive ki. + // t1 is the sum of the polynomials. + // t2 is the sum of the constants. + ARITH_SCALE_SUM_UPPER_BOUNDS, + + // ======== Tightening Strict Integer Upper Bounds + // Children: (P:(< i c)) + // where i has integer type. + // Arguments: none + // --------------------- + // Conclusion: (<= i greatestIntLessThan(c)}) + INT_TIGHT_UB, + + // ======== Tightening Strict Integer Lower Bounds + // Children: (P:(> i c)) + // where i has integer type. + // Arguments: none + // --------------------- + // Conclusion: (>= i leastIntGreaterThan(c)}) + INT_TIGHT_LB, + + // ======== Trichotomy of the reals + // Children: (A B) + // Arguments: (C) + // --------------------- + // Conclusion: (C), + // where (not A) (not B) and C + // are (> x c) (< x c) and (= x c) + // in some order + // note that "not" here denotes arithmetic negation, flipping + // >= to <, etc. + ARITH_TRICHOTOMY, + + // ======== Arithmetic operator elimination + // Children: none + // Arguments: (t) + // --------------------- + // Conclusion: arith::OperatorElim::getAxiomFor(t) + ARITH_OP_ELIM_AXIOM, + + // ======== Int Trust + // Children: (P1 ... Pn) + // Arguments: (Q) + // --------------------- + // Conclusion: (Q) + INT_TRUST, + //================================================= Unknown rule UNKNOWN, }; diff --git a/src/expr/proof_skolem_cache.cpp b/src/expr/proof_skolem_cache.cpp deleted file mode 100644 index da991415e..000000000 --- a/src/expr/proof_skolem_cache.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/********************* */ -/*! \file proof_skolem_cache.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 skolem cache - **/ - -#include "expr/proof_skolem_cache.h" - -#include "expr/attribute.h" - -using namespace CVC4::kind; - -namespace CVC4 { - -struct WitnessFormAttributeId -{ -}; -typedef expr::Attribute<WitnessFormAttributeId, Node> WitnessFormAttribute; - -struct SkolemFormAttributeId -{ -}; -typedef expr::Attribute<SkolemFormAttributeId, Node> SkolemFormAttribute; - -struct PurifySkolemAttributeId -{ -}; -typedef expr::Attribute<PurifySkolemAttributeId, Node> PurifySkolemAttribute; - -Node ProofSkolemCache::mkSkolem(Node v, - Node pred, - const std::string& prefix, - const std::string& comment, - int flags) -{ - Assert(v.getKind() == BOUND_VARIABLE); - // make the witness term - NodeManager* nm = NodeManager::currentNM(); - Node bvl = nm->mkNode(BOUND_VAR_LIST, v); - // translate pred to witness form, since pred itself may contain skolem - Node predw = getWitnessForm(pred); - // make the witness term, which should not contain any skolem - Node w = nm->mkNode(WITNESS, bvl, predw); - return getOrMakeSkolem(w, prefix, comment, flags); -} - -Node ProofSkolemCache::mkSkolemExists(Node v, - Node q, - const std::string& prefix, - const std::string& comment, - int flags) -{ - Assert(q.getKind() == EXISTS); - bool foundVar = false; - std::vector<Node> ovars; - for (const Node& av : q[0]) - { - if (av == v) - { - foundVar = true; - continue; - } - ovars.push_back(av); - } - if (!foundVar) - { - Assert(false); - return Node::null(); - } - Node pred = q[1]; - if (!ovars.empty()) - { - NodeManager* nm = NodeManager::currentNM(); - Node bvl = nm->mkNode(BOUND_VAR_LIST, ovars); - pred = nm->mkNode(EXISTS, bvl, pred); - } - return mkSkolem(v, pred, prefix, comment, flags); -} - -Node ProofSkolemCache::mkPurifySkolem(Node t, - const std::string& prefix, - const std::string& comment, - int flags) -{ - PurifySkolemAttribute psa; - if (t.hasAttribute(psa)) - { - return t.getAttribute(psa); - } - // The case where t is a witness term is special: we set its Skolem attribute - // directly. - if (t.getKind() == WITNESS) - { - return getOrMakeSkolem(t, prefix, comment, flags); - } - Node v = NodeManager::currentNM()->mkBoundVar(t.getType()); - Node k = mkSkolem(v, v.eqNode(t), prefix, comment, flags); - t.setAttribute(psa, k); - return k; -} - -Node ProofSkolemCache::getWitnessForm(Node n) -{ - return convertInternal(n, true); -} - -Node ProofSkolemCache::getSkolemForm(Node n) -{ - return convertInternal(n, false); -} - -Node ProofSkolemCache::convertInternal(Node n, bool toWitness) -{ - if (n.isNull()) - { - return n; - } - Trace("pf-skolem-debug") << "ProofSkolemCache::convertInternal: " << toWitness - << " " << n << std::endl; - WitnessFormAttribute wfa; - SkolemFormAttribute sfa; - NodeManager* nm = NodeManager::currentNM(); - std::unordered_map<TNode, Node, TNodeHashFunction> visited; - std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it; - std::vector<TNode> visit; - TNode cur; - visit.push_back(n); - do - { - cur = visit.back(); - visit.pop_back(); - it = visited.find(cur); - - if (it == visited.end()) - { - if (toWitness && cur.hasAttribute(wfa)) - { - visited[cur] = cur.getAttribute(wfa); - } - else if (!toWitness && cur.hasAttribute(sfa)) - { - visited[cur] = cur.getAttribute(sfa); - } - else - { - visited[cur] = Node::null(); - visit.push_back(cur); - for (const Node& cn : cur) - { - visit.push_back(cn); - } - } - } - else if (it->second.isNull()) - { - Node ret = cur; - bool childChanged = false; - std::vector<Node> children; - if (cur.getMetaKind() == metakind::PARAMETERIZED) - { - children.push_back(cur.getOperator()); - } - for (const Node& cn : cur) - { - it = visited.find(cn); - Assert(it != visited.end()); - Assert(!it->second.isNull()); - childChanged = childChanged || cn != it->second; - children.push_back(it->second); - } - if (childChanged) - { - ret = nm->mkNode(cur.getKind(), children); - } - if (toWitness) - { - cur.setAttribute(wfa, ret); - } - else - { - cur.setAttribute(sfa, ret); - } - visited[cur] = ret; - } - } while (!visit.empty()); - Assert(visited.find(n) != visited.end()); - Assert(!visited.find(n)->second.isNull()); - Trace("pf-skolem-debug") << "..return " << visited[n] << std::endl; - return visited[n]; -} - -void ProofSkolemCache::convertToWitnessFormVec(std::vector<Node>& vec) -{ - for (unsigned i = 0, nvec = vec.size(); i < nvec; i++) - { - vec[i] = getWitnessForm(vec[i]); - } -} -void ProofSkolemCache::convertToSkolemFormVec(std::vector<Node>& vec) -{ - for (unsigned i = 0, nvec = vec.size(); i < nvec; i++) - { - vec[i] = getSkolemForm(vec[i]); - } -} - -Node ProofSkolemCache::getOrMakeSkolem(Node w, - const std::string& prefix, - const std::string& comment, - int flags) -{ - Assert(w.getKind() == WITNESS); - SkolemFormAttribute sfa; - // could already have a skolem if we used w already - if (w.hasAttribute(sfa)) - { - return w.getAttribute(sfa); - } - NodeManager* nm = NodeManager::currentNM(); - // make the new skolem - Node k = nm->mkSkolem(prefix, w.getType(), comment, flags); - // set witness form attribute for k - WitnessFormAttribute wfa; - k.setAttribute(wfa, w); - // set skolem form attribute for w - w.setAttribute(sfa, k); - Trace("pf-skolem") << "ProofSkolemCache::mkSkolem: " << k << " : " << w - << std::endl; - return k; -} - -} // namespace CVC4 diff --git a/src/expr/proof_step_buffer.cpp b/src/expr/proof_step_buffer.cpp new file mode 100644 index 000000000..7108e4dae --- /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-2020 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..5a9d82e42 --- /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-2020 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/record.cpp b/src/expr/record.cpp index 074205d04..075ca4de4 100644 --- a/src/expr/record.cpp +++ b/src/expr/record.cpp @@ -2,9 +2,9 @@ /*! \file record.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters + ** Tim King, Morgan Deters, Piotr Trojanek ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/record.h b/src/expr/record.h index bfa5d9395..0a2dcc515 100644 --- a/src/expr/record.h +++ b/src/expr/record.h @@ -2,9 +2,9 @@ /*! \file record.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andres Noetzli + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/record.i b/src/expr/record.i deleted file mode 100644 index dce785ea3..000000000 --- a/src/expr/record.i +++ /dev/null @@ -1,55 +0,0 @@ -%{ -#include "expr/record.h" - -#ifdef SWIGJAVA - -#include "bindings/java_iterator_adapter.h" -#include "bindings/java_stream_adapters.h" - -#endif /* SWIGJAVA */ -%} - -%include "stdint.i" - -%rename(equals) CVC4::RecordUpdate::operator==(const RecordUpdate&) const; -%ignore CVC4::RecordUpdate::operator!=(const RecordUpdate&) const; - -%rename(equals) CVC4::Record::operator==(const Record&) const; -%ignore CVC4::Record::operator!=(const Record&) const; -%rename(getField) CVC4::Record::operator[](size_t) const; - -%rename(apply) CVC4::RecordHashFunction::operator()(const Record&) const; -%rename(apply) CVC4::RecordUpdateHashFunction::operator()(const RecordUpdate&) const; - -%ignore CVC4::operator<<(std::ostream&, const Record&); -%ignore CVC4::operator<<(std::ostream&, const RecordUpdate&); - -#ifdef SWIGJAVA - -// These Object arrays are always of two elements, the first is a String and the second a -// Type. (On the C++ side, it is a std::pair<std::string, Type>.) -%typemap(jni) std::pair<std::string, CVC4::Type> "jobjectArray"; -%typemap(jtype) std::pair<std::string, CVC4::Type> "java.lang.Object[]"; -%typemap(jstype) std::pair<std::string, CVC4::Type> "java.lang.Object[]"; -%typemap(javaout) std::pair<std::string, CVC4::Type> { return $jnicall; } -%typemap(out) std::pair<std::string, CVC4::Type> { - $result = jenv->NewObjectArray(2, jenv->FindClass("java/lang/Object"), $null); - jenv->SetObjectArrayElement($result, 0, jenv->NewStringUTF($1.first.c_str())); - jclass clazz = jenv->FindClass("edu/stanford/CVC4/Type"); - jmethodID methodid = jenv->GetMethodID(clazz, "<init>", "(JZ)V"); - jenv->SetObjectArrayElement($result, 1, jenv->NewObject(clazz, methodid, reinterpret_cast<uintptr_t>(new CVC4::Type($1.second)), true)); - }; - - - -#endif /* SWIGJAVA */ - -%include "expr/record.h" - -#ifdef SWIGJAVA - -%include "bindings/java_iterator_adapter.h" -%include "bindings/java_stream_adapters.h" - - -#endif /* SWIGJAVA */ diff --git a/src/expr/sequence.cpp b/src/expr/sequence.cpp index f70a70027..0eb8401e6 100644 --- a/src/expr/sequence.cpp +++ b/src/expr/sequence.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/sequence.h b/src/expr/sequence.h index 2e0721b4a..0e5cf6a1d 100644 --- a/src/expr/sequence.h +++ b/src/expr/sequence.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/skolem_manager.cpp b/src/expr/skolem_manager.cpp new file mode 100644 index 000000000..99f252530 --- /dev/null +++ b/src/expr/skolem_manager.cpp @@ -0,0 +1,345 @@ +/********************* */ +/*! \file skolem_manager.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 skolem manager class + **/ + +#include "expr/skolem_manager.h" + +#include "expr/attribute.h" + +using namespace CVC4::kind; + +namespace CVC4 { + +// Attributes are global maps from Nodes to data. Thus, note that these could +// be implemented as internal maps in SkolemManager. +struct WitnessFormAttributeId +{ +}; +typedef expr::Attribute<WitnessFormAttributeId, Node> WitnessFormAttribute; + +struct SkolemFormAttributeId +{ +}; +typedef expr::Attribute<SkolemFormAttributeId, Node> SkolemFormAttribute; + +struct PurifySkolemAttributeId +{ +}; +typedef expr::Attribute<PurifySkolemAttributeId, Node> PurifySkolemAttribute; + +Node SkolemManager::mkSkolem(Node v, + Node pred, + const std::string& prefix, + const std::string& comment, + int flags, + ProofGenerator* pg) +{ + Assert(v.getKind() == BOUND_VARIABLE); + // make the witness term + NodeManager* nm = NodeManager::currentNM(); + Node bvl = nm->mkNode(BOUND_VAR_LIST, v); + // translate pred to witness form, since pred itself may contain skolem + Node predw = getWitnessForm(pred); + // make the witness term, which should not contain any skolem + Node w = nm->mkNode(WITNESS, bvl, predw); + // store the mapping to proof generator if it exists + if (pg != nullptr) + { + Node q = nm->mkNode(EXISTS, w[0], w[1]); + // Notice this may overwrite an existing proof generator. This does not + // matter since either should be able to prove q. + d_gens[q] = pg; + } + return getOrMakeSkolem(w, prefix, comment, flags); +} + +Node SkolemManager::mkSkolemize(Node q, + std::vector<Node>& skolems, + const std::string& prefix, + const std::string& comment, + int flags, + ProofGenerator* pg) +{ + Trace("sk-manager-debug") << "mkSkolemize..." << std::endl; + Assert(q.getKind() == EXISTS); + Node currQ = q; + for (const Node& av : q[0]) + { + Assert(currQ.getKind() == EXISTS && av == currQ[0][0]); + // currQ is updated to the result of skolemizing its first variable in + // the method below. + Node sk = skolemize(currQ, currQ, prefix, comment, flags); + Trace("sk-manager-debug") + << "made skolem " << sk << " for " << av << std::endl; + skolems.push_back(sk); + } + if (pg != nullptr) + { + // Same as above, this may overwrite an existing proof generator + d_gens[q] = pg; + } + return currQ; +} + +Node SkolemManager::skolemize(Node q, + Node& qskolem, + const std::string& prefix, + const std::string& comment, + int flags) +{ + Assert(q.getKind() == EXISTS); + Node v; + std::vector<Node> ovars; + std::vector<Node> ovarsW; + Trace("sk-manager-debug") << "mkSkolemize..." << std::endl; + NodeManager* nm = NodeManager::currentNM(); + for (const Node& av : q[0]) + { + if (v.isNull()) + { + v = av; + continue; + } + // must make fresh variable to avoid shadowing, which is unique per + // variable av to ensure that this method is deterministic. Having this + // method deterministic ensures that the proof checker (e.g. for + // quantifiers) is capable of proving the expected value for conclusions + // of proof rules, instead of an alpha-equivalent variant of a conclusion. + Node avp = getOrMakeBoundVariable(av, av); + ovarsW.push_back(avp); + ovars.push_back(av); + } + Assert(!v.isNull()); + Node pred = q[1]; + qskolem = q[1]; + Trace("sk-manager-debug") << "make exists predicate" << std::endl; + if (!ovars.empty()) + { + Node bvl = nm->mkNode(BOUND_VAR_LIST, ovarsW); + pred = nm->mkNode(EXISTS, bvl, pred); + // skolem form keeps the old variables + bvl = nm->mkNode(BOUND_VAR_LIST, ovars); + qskolem = nm->mkNode(EXISTS, bvl, pred); + } + Trace("sk-manager-debug") << "call sub mkSkolem" << std::endl; + // don't use a proof generator, since this may be an intermediate, partially + // skolemized formula. + Node k = mkSkolem(v, pred, prefix, comment, flags, nullptr); + Assert(k.getType() == v.getType()); + TNode tv = v; + TNode tk = k; + Trace("sk-manager-debug") + << "qskolem apply " << tv << " -> " << tk << " to " << pred << std::endl; + qskolem = qskolem.substitute(tv, tk); + Trace("sk-manager-debug") << "qskolem done substitution" << std::endl; + return k; +} + +Node SkolemManager::mkPurifySkolem(Node t, + const std::string& prefix, + const std::string& comment, + int flags) +{ + PurifySkolemAttribute psa; + if (t.hasAttribute(psa)) + { + return t.getAttribute(psa); + } + // The case where t is a witness term is special: we set its Skolem attribute + // directly. + if (t.getKind() == WITNESS) + { + return getOrMakeSkolem(t, prefix, comment, flags); + } + Node v = NodeManager::currentNM()->mkBoundVar(t.getType()); + Node k = mkSkolem(v, v.eqNode(t), prefix, comment, flags); + t.setAttribute(psa, k); + return k; +} + +Node SkolemManager::mkExistential(Node t, Node p) +{ + Assert(p.getType().isBoolean()); + NodeManager* nm = NodeManager::currentNM(); + Node v = getOrMakeBoundVariable(t, p); + Node bvl = nm->mkNode(BOUND_VAR_LIST, v); + Node psubs = p.substitute(TNode(t), TNode(v)); + return nm->mkNode(EXISTS, bvl, psubs); +} + +ProofGenerator* SkolemManager::getProofGenerator(Node t) +{ + std::map<Node, ProofGenerator*>::iterator it = d_gens.find(t); + if (it != d_gens.end()) + { + return it->second; + } + return nullptr; +} + +Node SkolemManager::getWitnessForm(Node n) { return convertInternal(n, true); } + +Node SkolemManager::getSkolemForm(Node n) { return convertInternal(n, false); } + +Node SkolemManager::convertInternal(Node n, bool toWitness) +{ + if (n.isNull()) + { + return n; + } + Trace("sk-manager-debug") << "SkolemManager::convertInternal: " << toWitness + << " " << n << std::endl; + WitnessFormAttribute wfa; + SkolemFormAttribute sfa; + NodeManager* nm = NodeManager::currentNM(); + std::unordered_map<TNode, Node, TNodeHashFunction> visited; + std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it; + std::vector<TNode> visit; + TNode cur; + visit.push_back(n); + do + { + cur = visit.back(); + visit.pop_back(); + it = visited.find(cur); + + if (it == visited.end()) + { + if (toWitness && cur.hasAttribute(wfa)) + { + visited[cur] = cur.getAttribute(wfa); + } + else if (!toWitness && cur.hasAttribute(sfa)) + { + visited[cur] = cur.getAttribute(sfa); + } + else + { + visited[cur] = Node::null(); + visit.push_back(cur); + if (cur.getMetaKind() == metakind::PARAMETERIZED) + { + visit.push_back(cur.getOperator()); + } + for (const Node& cn : cur) + { + visit.push_back(cn); + } + } + } + else if (it->second.isNull()) + { + Node ret = cur; + bool childChanged = false; + std::vector<Node> children; + if (cur.getMetaKind() == metakind::PARAMETERIZED) + { + it = visited.find(cur.getOperator()); + Assert(it != visited.end()); + Assert(!it->second.isNull()); + childChanged = childChanged || cur.getOperator() != it->second; + children.push_back(it->second); + } + for (const Node& cn : cur) + { + it = visited.find(cn); + Assert(it != visited.end()); + Assert(!it->second.isNull()); + childChanged = childChanged || cn != it->second; + children.push_back(it->second); + } + if (childChanged) + { + ret = nm->mkNode(cur.getKind(), children); + } + if (toWitness) + { + cur.setAttribute(wfa, ret); + } + else + { + // notice that WITNESS terms t may be assigned a skolem form that is + // of kind WITNESS here, if t contains a free variable. This is due to + // the fact that witness terms in the bodies of quantified formulas are + // not eliminated and thus may appear in places where getSkolemForm is + // called on them. Regardless, witness terms with free variables + // should never be themselves assigned skolems (otherwise we would have + // assertions with free variables), and thus they can be treated like + // ordinary terms here. + cur.setAttribute(sfa, ret); + } + visited[cur] = ret; + } + } while (!visit.empty()); + Assert(visited.find(n) != visited.end()); + Assert(!visited.find(n)->second.isNull()); + Trace("sk-manager-debug") << "..return " << visited[n] << std::endl; + return visited[n]; +} + +void SkolemManager::convertToWitnessFormVec(std::vector<Node>& vec) +{ + for (unsigned i = 0, nvec = vec.size(); i < nvec; i++) + { + vec[i] = getWitnessForm(vec[i]); + } +} +void SkolemManager::convertToSkolemFormVec(std::vector<Node>& vec) +{ + for (unsigned i = 0, nvec = vec.size(); i < nvec; i++) + { + vec[i] = getSkolemForm(vec[i]); + } +} + +Node SkolemManager::getOrMakeSkolem(Node w, + const std::string& prefix, + const std::string& comment, + int flags) +{ + Assert(w.getKind() == WITNESS); + SkolemFormAttribute sfa; + // could already have a skolem if we used w already + if (w.hasAttribute(sfa)) + { + return w.getAttribute(sfa); + } + NodeManager* nm = NodeManager::currentNM(); + // make the new skolem + Node k = nm->mkSkolem(prefix, w.getType(), comment, flags); + // set witness form attribute for k + WitnessFormAttribute wfa; + k.setAttribute(wfa, w); + // set skolem form attribute for w + w.setAttribute(sfa, k); + Trace("sk-manager") << "SkolemManager::mkSkolem: " << k << " : " << w + << std::endl; + return k; +} + +Node SkolemManager::getOrMakeBoundVariable(Node t, Node s) +{ + std::pair<Node, Node> key(t, s); + std::map<std::pair<Node, Node>, Node>::iterator it = + d_witnessBoundVar.find(key); + if (it != d_witnessBoundVar.end()) + { + return it->second; + } + TypeNode tt = t.getType(); + Node v = NodeManager::currentNM()->mkBoundVar(tt); + d_witnessBoundVar[key] = v; + return v; +} + +} // namespace CVC4 diff --git a/src/expr/proof_skolem_cache.h b/src/expr/skolem_manager.h index c0de1e472..8dd3a3ef9 100644 --- a/src/expr/proof_skolem_cache.h +++ b/src/expr/skolem_manager.h @@ -1,21 +1,21 @@ /********************* */ -/*! \file proof_skolem_cache.h +/*! \file skolem_manager.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 + ** Copyright (c) 2009-2020 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 skolem cache utility + ** \brief Skolem manager utility **/ #include "cvc4_private.h" -#ifndef CVC4__EXPR__PROOF_SKOLEM_CACHE_H -#define CVC4__EXPR__PROOF_SKOLEM_CACHE_H +#ifndef CVC4__EXPR__SKOLEM_MANAGER_H +#define CVC4__EXPR__SKOLEM_MANAGER_H #include <string> @@ -23,6 +23,8 @@ namespace CVC4 { +class ProofGenerator; + /** * A manager for skolems that can be used in proofs. This is designed to be * a trusted interface to NodeManager::mkSkolem, where one @@ -34,11 +36,11 @@ namespace CVC4 { * reference counting of skolem variables which may be deleted if they are not * used. */ -class ProofSkolemCache +class SkolemManager { public: - ProofSkolemCache() {} - ~ProofSkolemCache() {} + SkolemManager() {} + ~SkolemManager() {} /** * This makes a skolem of same type as bound variable v, (say its type is T), * whose definition is (witness ((v T)) pred). This definition is maintained @@ -81,37 +83,76 @@ class ProofSkolemCache * @param prefix The prefix of the name of the Skolem * @param comment Debug information about the Skolem * @param flags The flags for the Skolem (see NodeManager::mkSkolem) + * @param pg The proof generator for this skolem. If non-null, this proof + * generator must respond to a call to getProofFor(exists v. pred) during + * the lifetime of the current node manager. * @return The skolem whose witness form is registered by this class. */ - static Node mkSkolem(Node v, - Node pred, - const std::string& prefix, - const std::string& comment = "", - int flags = NodeManager::SKOLEM_DEFAULT); + Node mkSkolem(Node v, + Node pred, + const std::string& prefix, + const std::string& comment = "", + int flags = NodeManager::SKOLEM_DEFAULT, + ProofGenerator* pg = nullptr); /** - * Same as above, but where pred is an existential quantified formula - * whose bound variable list contains v. For example, calling this method on: - * x, (exists ((x Int) (y Int)) (P x y)) - * will return: - * (witness ((x Int)) (exists ((y Int)) (P x y))) - * If the variable v is not in the bound variable list of q, then null is - * returned and an assertion failure is thrown. + * Make skolemized form of existentially quantified formula q, and store its + * Skolems into the argument skolems. + * + * For example, calling this method on: + * (exists ((x Int) (y Int)) (P x y)) + * returns: + * (P w1 w2) + * where w1 and w2 are skolems with witness forms: + * (witness ((x Int)) (exists ((y' Int)) (P x y'))) + * (witness ((y Int)) (P w1 y)) + * respectively. Additionally, this method will add { w1, w2 } to skolems. + * Notice that y is renamed to y' in the witness form of w1 to avoid variable + * shadowing. + * + * In contrast to mkSkolem, the proof generator is for the *entire* + * existentially quantified formula q, which may have multiple variables in + * its prefix. + * + * @param q The existentially quantified formula to skolemize, + * @param skolems Vector to add Skolems of q to, + * @param prefix The prefix of the name of each of the Skolems + * @param comment Debug information about each of the Skolems + * @param flags The flags for the Skolem (see NodeManager::mkSkolem) + * @param pg The proof generator for this skolem. If non-null, this proof + * generator must respond to a call to getProofFor(q) during + * the lifetime of the current node manager. + * @return The skolemized form of q. */ - static Node mkSkolemExists(Node v, - Node q, - const std::string& prefix, - const std::string& comment = "", - int flags = NodeManager::SKOLEM_DEFAULT); + Node mkSkolemize(Node q, + std::vector<Node>& skolems, + const std::string& prefix, + const std::string& comment = "", + int flags = NodeManager::SKOLEM_DEFAULT, + ProofGenerator* pg = nullptr); /** * Same as above, but for special case of (witness ((x T)) (= x t)) * where T is the type of t. This skolem is unique for each t, which we * implement via an attribute on t. This attribute is used to ensure to * associate a unique skolem for each t. + * + * Notice that a purification skolem is trivial to justify, and hence it + * does not require a proof generator. + */ + Node mkPurifySkolem(Node t, + const std::string& prefix, + const std::string& comment = "", + int flags = NodeManager::SKOLEM_DEFAULT); + /** + * Get proof generator for existentially quantified formula q. This returns + * the proof generator that was provided in a call to mkSkolem above. + */ + ProofGenerator* getProofGenerator(Node q); + /** + * Make existential. Given t and p[t] where p is a formula, this returns + * (exists ((x T)) p[x]) + * where T is the type of t, and x is a variable unique to t,p. */ - static Node mkPurifySkolem(Node t, - const std::string& prefix, - const std::string& comment = "", - int flags = NodeManager::SKOLEM_DEFAULT); + Node mkExistential(Node t, Node p); /** convert to witness form * * @param n The term or formula to convert to witness form described above @@ -130,6 +171,15 @@ class ProofSkolemCache static void convertToSkolemFormVec(std::vector<Node>& vec); private: + /** + * Mapping from witness terms to proof generators. + */ + std::map<Node, ProofGenerator*> d_gens; + /** + * Map to canonical bound variables. This is used for example by the method + * mkExistential. + */ + std::map<std::pair<Node, Node>, Node> d_witnessBoundVar; /** Convert to witness or skolem form */ static Node convertInternal(Node n, bool toWitness); /** Get or make skolem attribute for witness term w */ @@ -137,6 +187,29 @@ class ProofSkolemCache const std::string& prefix, const std::string& comment, int flags); + /** + * Skolemize the first variable of existentially quantified formula q. + * For example, calling this method on: + * (exists ((x Int) (y Int)) (P x y)) + * will return: + * (witness ((x Int)) (exists ((y Int)) (P x y))) + * If q is not an existentially quantified formula, then null is + * returned and an assertion failure is thrown. + * + * This method additionally updates qskolem to be the skolemized form of q. + * In the above example, this is set to: + * (exists ((y Int)) (P (witness ((x Int)) (exists ((y' Int)) (P x y'))) y)) + */ + Node skolemize(Node q, + Node& qskolem, + const std::string& prefix, + const std::string& comment = "", + int flags = NodeManager::SKOLEM_DEFAULT); + /** + * Get or make bound variable unique to (s,t), for d_witnessBoundVar, where + * t and s are terms. + */ + Node getOrMakeBoundVariable(Node t, Node s); }; } // namespace CVC4 diff --git a/src/expr/sygus_datatype.cpp b/src/expr/sygus_datatype.cpp index bea8a41b8..d14f0d1a7 100644 --- a/src/expr/sygus_datatype.cpp +++ b/src/expr/sygus_datatype.cpp @@ -2,9 +2,9 @@ /*! \file sygus_datatype.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/sygus_datatype.h b/src/expr/sygus_datatype.h index e7b60f3a3..1bf74d8d3 100644 --- a/src/expr/sygus_datatype.h +++ b/src/expr/sygus_datatype.h @@ -2,9 +2,9 @@ /*! \file sygus_datatype.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/symbol_table.cpp b/src/expr/symbol_table.cpp index deaf781f4..68d3904d3 100644 --- a/src/expr/symbol_table.cpp +++ b/src/expr/symbol_table.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/symbol_table.h b/src/expr/symbol_table.h index 8f3b0ec1b..2824d9f7a 100644 --- a/src/expr/symbol_table.h +++ b/src/expr/symbol_table.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/term_canonize.cpp b/src/expr/term_canonize.cpp index d9a5f6e1a..4f92edd31 100644 --- a/src/expr/term_canonize.cpp +++ b/src/expr/term_canonize.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/term_canonize.h b/src/expr/term_canonize.h index 6049cd804..32ac2fd72 100644 --- a/src/expr/term_canonize.h +++ b/src/expr/term_canonize.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/term_conversion_proof_generator.cpp b/src/expr/term_conversion_proof_generator.cpp new file mode 100644 index 000000000..70b429510 --- /dev/null +++ b/src/expr/term_conversion_proof_generator.cpp @@ -0,0 +1,249 @@ +/********************* */ +/*! \file term_conversion_proof_generator.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 term conversion proof generator utility + **/ + +#include "expr/term_conversion_proof_generator.h" + +using namespace CVC4::kind; + +namespace CVC4 { + +TConvProofGenerator::TConvProofGenerator(ProofNodeManager* pnm, + context::Context* c) + : d_proof(pnm, nullptr, c), d_rewriteMap(c ? c : &d_context) +{ +} + +TConvProofGenerator::~TConvProofGenerator() {} + +void TConvProofGenerator::addRewriteStep(Node t, Node s, ProofGenerator* pg) +{ + // should not rewrite term more than once + Assert(!hasRewriteStep(t)); + Node eq = t.eqNode(s); + d_proof.addLazyStep(eq, pg); + d_rewriteMap[t] = s; +} + +void TConvProofGenerator::addRewriteStep(Node t, Node s, ProofStep ps) +{ + // should not rewrite term more than once + Assert(!hasRewriteStep(t)); + Node eq = t.eqNode(s); + d_proof.addStep(eq, ps); + d_rewriteMap[t] = s; +} + +void TConvProofGenerator::addRewriteStep(Node t, + Node s, + PfRule id, + const std::vector<Node>& children, + const std::vector<Node>& args) +{ + // should not rewrite term more than once + Assert(!hasRewriteStep(t)); + Node eq = t.eqNode(s); + d_proof.addStep(eq, id, children, args); + d_rewriteMap[t] = s; +} + +bool TConvProofGenerator::hasRewriteStep(Node t) const +{ + return !getRewriteStep(t).isNull(); +} + +std::shared_ptr<ProofNode> TConvProofGenerator::getProofFor(Node f) +{ + Trace("tconv-pf-gen") << "TConvProofGenerator::getProofFor: " << f + << std::endl; + if (f.getKind() != EQUAL) + { + Trace("tconv-pf-gen") << "... fail, non-equality" << std::endl; + Assert(false); + return nullptr; + } + std::shared_ptr<ProofNode> pf = getProofForRewriting(f[0]); + if (pf == nullptr) + { + // failed to generate proof + Trace("tconv-pf-gen") << "...failed to get proof" << std::endl; + Assert(false); + return pf; + } + if (pf->getResult() != f) + { + Trace("tconv-pf-gen") << "...failed, mismatch: returned proof concludes " + << pf->getResult() << std::endl; + Assert(false); + return nullptr; + } + Trace("tconv-pf-gen") << "... success" << std::endl; + return pf; +} + +std::shared_ptr<ProofNode> TConvProofGenerator::getProofForRewriting(Node t) +{ + // we use the existing proofs + LazyCDProof pf(d_proof.getManager(), &d_proof); + NodeManager* nm = NodeManager::currentNM(); + // Invariant: if visited[t] = s or rewritten[t] = s and t,s are distinct, + // then pf is able to generate a proof of t=s. + // the final rewritten form of terms + std::unordered_map<TNode, Node, TNodeHashFunction> visited; + // the rewritten form of terms we have processed so far + std::unordered_map<TNode, Node, TNodeHashFunction> rewritten; + std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it; + std::unordered_map<TNode, Node, TNodeHashFunction>::iterator itr; + std::vector<TNode> visit; + TNode cur; + visit.push_back(t); + do + { + cur = visit.back(); + visit.pop_back(); + it = visited.find(cur); + + if (it == visited.end()) + { + visited[cur] = Node::null(); + // did we rewrite the current node (possibly at pre-rewrite)? + Node rcur = getRewriteStep(cur); + if (!rcur.isNull()) + { + // d_proof should have a proof of cur = rcur. Hence there is nothing + // to do here, as pf will reference prg to get the proof from d_proof. + // It may be the case that rcur also rewrites, thus we cannot assign + // the final rewritten form for cur yet. Instead we revisit cur after + // finishing visiting rcur. + rewritten[cur] = rcur; + visit.push_back(cur); + visit.push_back(rcur); + } + else + { + visit.push_back(cur); + visit.insert(visit.end(), cur.begin(), cur.end()); + } + } + else if (it->second.isNull()) + { + itr = rewritten.find(cur); + if (itr != rewritten.end()) + { + // if it was rewritten, check the status of the rewritten node, + // which should be finished now + Node rcur = itr->second; + Assert(cur != rcur); + // the final rewritten form of cur is the final form of rcur + Node rcurFinal = visited[rcur]; + if (rcurFinal != rcur) + { + // must connect via TRANS + std::vector<Node> pfChildren; + pfChildren.push_back(cur.eqNode(rcur)); + pfChildren.push_back(rcur.eqNode(rcurFinal)); + Node result = cur.eqNode(rcurFinal); + pf.addStep(result, PfRule::TRANS, pfChildren, {}); + } + visited[cur] = rcurFinal; + } + else + { + Node ret = cur; + bool childChanged = false; + std::vector<Node> children; + if (cur.getMetaKind() == metakind::PARAMETERIZED) + { + children.push_back(cur.getOperator()); + } + for (const Node& cn : cur) + { + it = visited.find(cn); + Assert(it != visited.end()); + Assert(!it->second.isNull()); + childChanged = childChanged || cn != it->second; + children.push_back(it->second); + } + if (childChanged) + { + ret = nm->mkNode(cur.getKind(), children); + rewritten[cur] = ret; + // congruence to show (cur = ret) + std::vector<Node> pfChildren; + for (size_t i = 0, size = cur.getNumChildren(); i < size; i++) + { + if (cur[i] == ret[i]) + { + // ensure REFL proof for unchanged children + pf.addStep(cur[i].eqNode(cur[i]), PfRule::REFL, {}, {cur[i]}); + } + pfChildren.push_back(cur[i].eqNode(ret[i])); + } + std::vector<Node> pfArgs; + Kind k = cur.getKind(); + if (kind::metaKindOf(k) == kind::metakind::PARAMETERIZED) + { + pfArgs.push_back(cur.getOperator()); + } + else + { + pfArgs.push_back(nm->operatorOf(k)); + } + Node result = cur.eqNode(ret); + pf.addStep(result, PfRule::CONG, pfChildren, pfArgs); + } + // did we rewrite ret (at post-rewrite)? + Node rret = getRewriteStep(ret); + if (!rret.isNull()) + { + if (cur != ret) + { + visit.push_back(cur); + } + // d_proof should have a proof of ret = rret, hence nothing to do + // here, for the same reasons as above. It also may be the case that + // rret rewrites, hence we must revisit ret. + rewritten[ret] = rret; + visit.push_back(ret); + visit.push_back(rret); + } + else + { + // it is final + visited[cur] = ret; + } + } + } + } while (!visit.empty()); + Assert(visited.find(t) != visited.end()); + Assert(!visited.find(t)->second.isNull()); + // make the overall proof + Node teq = t.eqNode(visited[t]); + return pf.getProofFor(teq); +} + +Node TConvProofGenerator::getRewriteStep(Node t) const +{ + NodeNodeMap::const_iterator it = d_rewriteMap.find(t); + if (it == d_rewriteMap.end()) + { + return Node::null(); + } + return (*it).second; +} +std::string TConvProofGenerator::identify() const +{ + return "TConvProofGenerator"; +} + +} // namespace CVC4 diff --git a/src/expr/term_conversion_proof_generator.h b/src/expr/term_conversion_proof_generator.h new file mode 100644 index 000000000..56b89f65c --- /dev/null +++ b/src/expr/term_conversion_proof_generator.h @@ -0,0 +1,123 @@ +/********************* */ +/*! \file term_conversion_proof_generator.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 Term conversion proof generator utility + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__EXPR__TERM_CONVERSION_PROOF_GENERATOR_H +#define CVC4__EXPR__TERM_CONVERSION_PROOF_GENERATOR_H + +#include "context/cdhashmap.h" +#include "expr/lazy_proof.h" +#include "expr/proof_generator.h" +#include "expr/proof_node_manager.h" + +namespace CVC4 { + +/** + * The term conversion proof generator. + * + * This class is used for proofs of t = t', where t' is obtained from t by + * applying (context-free) small step rewrites on subterms of t. Its main + * interface functions are: + * (1) addRewriteStep(t,s,<justification>) which notifies this class that t + * rewrites to s, where justification is either a proof generator or proof + * step, + * (2) getProofFor(f) where f is any equality that can be justified by the + * rewrite steps given above. + * + * For example, say we make the following calls: + * addRewriteStep(a,b,P1) + * addRewriteStep(f(a),c,P2) + * addRewriteStep(c,d,P3) + * where P1 and P2 are proof steps. Afterwards, this class may justify any + * equality t = s where s is obtained by applying the rewrites a->b, f(a)->c, + * c->d, based on the strategy outlined below [***]. For example, the call to: + * getProofFor(g(f(a),h(a),f(e)) = g(d,h(b),f(e))) + * will return the proof: + * CONG( + * TRANS(P2,P3), ; f(a)=d + * CONG(P1 :args h), ; h(a)=h(b) + * REFL(:args f(e)) ; f(e)=f(e) + * :args g) + * + * [***] This class traverses the left hand side of a given equality-to-prove + * (the term g(f(a),h(a),e) in the above example) and "replays" the rewrite + * steps to obtain its rewritten form. To do so, it applies any available + * rewrite step both at pre-rewrite (pre-order traversal) and post-rewrite + * (post-order traversal). It thus does not require the user of this class to + * distinguish whether a rewrite is a pre-rewrite or a post-rewrite during + * addRewriteStep. In particular, notice that in the above example, we realize + * that f(a) --> c at pre-rewrite instead of post-rewriting a --> b and then + * ending with f(a)=f(b). + */ +class TConvProofGenerator : public ProofGenerator +{ + public: + /** Constructor + * + * @param pnm The proof node manager for constructing ProofNode objects. + * @param c The context that this class depends on. If none is provided, + * this class is context-independent. + */ + TConvProofGenerator(ProofNodeManager* pnm, context::Context* c = nullptr); + ~TConvProofGenerator(); + /** + * Add rewrite step t --> s based on proof generator. + */ + void addRewriteStep(Node t, Node s, ProofGenerator* pg); + /** Same as above, for a single step */ + void addRewriteStep(Node t, Node s, ProofStep ps); + /** Same as above, with explicit arguments */ + void addRewriteStep(Node t, + Node s, + PfRule id, + const std::vector<Node>& children, + const std::vector<Node>& args); + /** Has rewrite step for term t */ + bool hasRewriteStep(Node t) const; + /** + * Get rewrite step for term t, returns the s provided in a call to + * addRewriteStep if one exists, or null otherwise. + */ + Node getRewriteStep(Node t) const; + /** + * Get the proof for formula f. It should be the case that f is of the form + * t = t', where t' is the result of rewriting t based on the rewrite steps + * registered to this class. + * + * @param f The fact to get the proof for. + * @return The proof for f. + */ + std::shared_ptr<ProofNode> getProofFor(Node f) override; + /** Identify this generator (for debugging, etc..) */ + std::string identify() const override; + + protected: + typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap; + /** A dummy context used by this class if none is provided */ + context::Context d_context; + /** The (lazy) context dependent proof object. */ + LazyCDProof d_proof; + /** map to rewritten forms */ + NodeNodeMap d_rewriteMap; + /** + * Get the proof for term t. Returns a proof of t = t' where t' is the + * result of rewriting t based on the rewrite steps registered to this class. + */ + std::shared_ptr<ProofNode> getProofForRewriting(Node t); +}; + +} // namespace CVC4 + +#endif /* CVC4__EXPR__TERM_CONVERSION_PROOF_GENERATOR_H */ diff --git a/src/expr/type.cpp b/src/expr/type.cpp index 031dcb3f0..7696d9d7a 100644 --- a/src/expr/type.cpp +++ b/src/expr/type.cpp @@ -2,9 +2,9 @@ /*! \file type.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Tim King + ** Morgan Deters, Dejan Jovanovic, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..61cb7eabf 100644 --- a/src/expr/type.h +++ b/src/expr/type.h @@ -2,9 +2,9 @@ /*! \file type.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Tim King + ** Morgan Deters, Dejan Jovanovic, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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.i b/src/expr/type.i index 16d059eac..8262c4cea 100644 --- a/src/expr/type.i +++ b/src/expr/type.i @@ -2,6 +2,77 @@ #include "expr/type.h" %} +%ignore CVC4::expr::exportTypeInternal(TypeNode n, NodeManager* from, NodeManager* nm, ExprManagerMapCollection& vmap); + +%ignore CVC4::Type::Type(const Type&); +%ignore CVC4::Type::operator=(const Type&); +%ignore CVC4::Type::operator!=(const Type&) const; +%rename(equals) CVC4::Type::operator==(const Type&) const; +%rename(less) CVC4::Type::operator<(const Type&) const; +%rename(lessEqual) CVC4::Type::operator<=(const Type&) const; +%rename(greater) CVC4::Type::operator>(const Type&) const; +%rename(greaterEqual) CVC4::Type::operator>=(const Type&) const; + +%ignore CVC4::BitVectorType::BitVectorType(); +%ignore CVC4::BitVectorType::BitVectorType(const Type&); + +%ignore CVC4::BooleanType::BooleanType(); +%ignore CVC4::BooleanType::BooleanType(const Type&); + +%ignore CVC4::ConstructorType::ConstructorType(); +%ignore CVC4::ConstructorType::ConstructorType(const Type&); + +%ignore CVC4::FloatingPointType::FloatingPointType(); +%ignore CVC4::FloatingPointType::FloatingPointType(const Type&); + +%ignore CVC4::DatatypeType::DatatypeType(); +%ignore CVC4::DatatypeType::DatatypeType(const Type&); +%ignore CVC4::DatatypeType::getRecord() const; + +%ignore CVC4::FunctionType::FunctionType(); +%ignore CVC4::FunctionType::FunctionType(const Type&); + +%ignore CVC4::IntegerType::IntegerType(); +%ignore CVC4::IntegerType::IntegerType(const Type&); + +%ignore CVC4::RealType::RealType(); +%ignore CVC4::RealType::RealType(const Type&); + +%ignore CVC4::RegExpType::RegExpType(); +%ignore CVC4::RegExpType::RegExpType(const Type&); + +%ignore CVC4::RoundingModeType::RoundingModeType(); +%ignore CVC4::RoundingModeType::RoundingModeType(const Type&); + +%ignore CVC4::SelectorType::SelectorType(); +%ignore CVC4::SelectorType::SelectorType(const Type&); + +%ignore CVC4::SequenceType::SequenceType(); +%ignore CVC4::SequenceType::SequenceType(const Type&); + +%ignore CVC4::SExprType::SExprType(); +%ignore CVC4::SExprType::SExprType(const Type&); + +%ignore CVC4::SortType::SortType(); +%ignore CVC4::SortType::SortType(const Type&); + +%ignore CVC4::SortConstructorType::SortConstructorType(); +%ignore CVC4::SortConstructorType::SortConstructorType(const Type&); + +%ignore CVC4::StringType::StringType(); +%ignore CVC4::StringType::StringType(const Type&); + +%ignore CVC4::TesterType::TesterType(); +%ignore CVC4::TesterType::TesterType(const Type&); + +%ignore CVC4::ArrayType::ArrayType(); +%ignore CVC4::ArrayType::ArrayType(const Type&); + +%ignore CVC4::SetType::SetType(); +%ignore CVC4::SetType::SetType(const Type&); + +%ignore CVC4::operator<<(std::ostream&, const Type&); + #ifdef SWIGPYTHON %rename(doApply) CVC4::TypeHashFunction::operator()(const CVC4::Type&) const; #else /* SWIGPYTHON */ @@ -9,62 +80,358 @@ #endif /* SWIGPYTHON */ #ifdef SWIGJAVA + +%include "bindings/java/cvc4_std_vector.i" + +%typemap(javaout) CVC4::Expr { + return new Expr(this.em, $jnicall, true); +} + +%typemap(javaout) std::vector<CVC4::Type> { + return new vectorType(this.em, $jnicall, true); +} + %typemap(javabody) CVC4::Type %{ private long swigCPtr; protected boolean swigCMemOwn; + // Prevent ExprManager from being garbage collected before this instance + protected ExprManager em; - protected $javaclassname(long cPtr, boolean cMemoryOwn) { + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { swigCMemOwn = cMemoryOwn; swigCPtr = cPtr; - this.em = SmtEngine.mkRef(getExprManager()); // keep ref to em in SWIG proxy class + this.em = em; } protected static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } %} -%javamethodmodifiers CVC4::Type::operator=(const Type&) "protected"; -%typemap(javacode) CVC4::Type %{ - // a ref is kept here to keep Java GC from collecting the ExprManager - // before the Type - private Object em; - public Type assign(Type t) { - Type r = assignInternal(t); - this.em = SmtEngine.mkRef(getExprManager()); // keep ref to em in SWIG proxy class - return r; +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea +%typemap(javaconstruct) Type { + this(null, $imcall, true); +} + +%typemap(javaconstruct) CVC4::Type { + this(null, $imcall, true); +} + + +%typemap(javaout) CVC4::Type { + return new Type(this.em, $jnicall, true); +} + +SWIG_STD_VECTOR_EM(CVC4::Type, const CVC4::Type&) + +%typemap(javaout) CVC4::Type { + return new Type(this.em, $jnicall, true); +} +%typemap(javaout) const CVC4::Type& { + return new Type(this.em, $jnicall, false); +} +%template(vectorType) std::vector<CVC4::Type>; + +%typemap(javabody_derived) CVC4::BitVectorType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; } %} -%typemap(javaconstruct) Type { - this($imcall, true); - this.em = SmtEngine.mkRef(getExprManager()); // keep ref to em in SWIG proxy class - } -%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") CVC4::Type { - SmtEngine.dlRef(em); - em = null; - if (swigCPtr != 0) { - if (swigCMemOwn) { - swigCMemOwn = false; - CVC4JNI.delete_Type(swigCPtr); - } - swigCPtr = 0; - } + +%typemap(javabody_derived) CVC4::BooleanType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; } -#endif /* SWIGJAVA */ -%ignore CVC4::operator<<(std::ostream&, const Type&); -%rename(assignInternal) CVC4::Type::operator=(const Type&); -%rename(equals) CVC4::Type::operator==(const Type&) const; -%ignore CVC4::Type::operator!=(const Type&) const; -%rename(less) CVC4::Type::operator<(const Type&) const; -%rename(lessEqual) CVC4::Type::operator<=(const Type&) const; -%rename(greater) CVC4::Type::operator>(const Type&) const; -%rename(greaterEqual) CVC4::Type::operator>=(const Type&) const; + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::ConstructorType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } -namespace CVC4 { - namespace expr { - %ignore exportTypeInternal; - }/* CVC4::expr namespace */ -}/* CVC4 namespace */ + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::FloatingPointType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::DatatypeType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +SWIG_STD_VECTOR_EM(CVC4::DatatypeType, const CVC4::DatatypeType&) + +%typemap(javaout) CVC4::DatatypeType { + return new DatatypeType(this.em, $jnicall, true); +} +%typemap(javaout) const CVC4::DatatypeType& { + return new DatatypeType(this.em, $jnicall, false); +} +%template(vectorDatatypeType) std::vector<CVC4::DatatypeType>; + +%typemap(javabody_derived) CVC4::FunctionType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::IntegerType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::RealType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::RegExpType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::RoundingModeType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::SelectorType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::SequenceType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::SExprType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::SortType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::SortConstructorType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::StringType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::TesterType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::ArrayType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCPtr = cPtr; + swigCMemOwn = cMemoryOwn; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javabody_derived) CVC4::SetType %{ + private transient long swigCPtr; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + super(em, CVC4JNI.$javaclassname_SWIGUpcast(cPtr), cMemoryOwn); + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +%typemap(javaout) CVC4::SetType { + return new SetType(this.em, $jnicall, true); +} + +%typemap(javaout) CVC4::BooleanType { + return new BooleanType(this.em, $jnicall, true); +} + +%typemap(javaout) const CVC4::Datatype& { + return new Datatype(this.em, $jnicall, true); +} + +%typemap(javaout) CVC4::DatatypeType { + return new DatatypeType(this.em, $jnicall, true); +} + +%typemap(javaout) CVC4::SortType { + return new SortType(this.em, $jnicall, true); +} + +%typemap(javaout) typeVector { + return new typeVector(this.em, $jnicall, true); +} + +#endif /* SWIGJAVA */ %include "expr/type.h" diff --git a/src/expr/type_checker.h b/src/expr/type_checker.h index bf0229bf8..4b8bff946 100644 --- a/src/expr/type_checker.h +++ b/src/expr/type_checker.h @@ -2,9 +2,9 @@ /*! \file type_checker.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/type_checker_template.cpp b/src/expr/type_checker_template.cpp index 3ed12cf6a..3dedd856a 100644 --- a/src/expr/type_checker_template.cpp +++ b/src/expr/type_checker_template.cpp @@ -2,9 +2,9 @@ /*! \file type_checker_template.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Dejan Jovanovic + ** Morgan Deters, Mathias Preiner, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/type_checker_util.h b/src/expr/type_checker_util.h index fc5513d7b..411733dcb 100644 --- a/src/expr/type_checker_util.h +++ b/src/expr/type_checker_util.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/type_matcher.cpp b/src/expr/type_matcher.cpp index f99c8a2da..c09f98ee1 100644 --- a/src/expr/type_matcher.cpp +++ b/src/expr/type_matcher.cpp @@ -2,9 +2,9 @@ /*! \file type_matcher.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -86,6 +86,11 @@ bool TypeMatcher::doMatching(TypeNode pattern, TypeNode tn) { return false; } + else if (pattern.getNumChildren() == 0) + { + // fail if the type parameter or type constructors are different + return pattern == tn; + } for (size_t j = 0, nchild = pattern.getNumChildren(); j < nchild; j++) { if (!doMatching(pattern[j], tn[j])) diff --git a/src/expr/type_matcher.h b/src/expr/type_matcher.h index 13423f401..17a3917c8 100644 --- a/src/expr/type_matcher.h +++ b/src/expr/type_matcher.h @@ -2,9 +2,9 @@ /*! \file type_matcher.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/type_node.cpp b/src/expr/type_node.cpp index 110db6162..ff4de9dc8 100644 --- a/src/expr/type_node.cpp +++ b/src/expr/type_node.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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 @@ -300,11 +304,7 @@ Node TypeNode::mkGroundValue() const return *te; } -bool TypeNode::isStringLike() const -{ - // TODO (cvc4-projects #23): sequence here - return isString(); -} +bool TypeNode::isStringLike() const { return isString() || isSequence(); } bool TypeNode::isSubtypeOf(TypeNode t) const { if(*this == t) { @@ -353,6 +353,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..5082fe1d3 100644 --- a/src/expr/type_node.h +++ b/src/expr/type_node.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Dejan Jovanovic, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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/expr/type_properties_template.h b/src/expr/type_properties_template.h index 8e4ce797e..a8adadf6e 100644 --- a/src/expr/type_properties_template.h +++ b/src/expr/type_properties_template.h @@ -2,9 +2,9 @@ /*! \file type_properties_template.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/uninterpreted_constant.cpp b/src/expr/uninterpreted_constant.cpp index 574580259..2b66a3b7a 100644 --- a/src/expr/uninterpreted_constant.cpp +++ b/src/expr/uninterpreted_constant.cpp @@ -2,9 +2,9 @@ /*! \file uninterpreted_constant.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andrew Reynolds + ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/uninterpreted_constant.h b/src/expr/uninterpreted_constant.h index fb6557497..46d9a2800 100644 --- a/src/expr/uninterpreted_constant.h +++ b/src/expr/uninterpreted_constant.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/variable_type_map.h b/src/expr/variable_type_map.h index ba1c60549..38f6e520d 100644 --- a/src/expr/variable_type_map.h +++ b/src/expr/variable_type_map.h @@ -2,9 +2,9 @@ /*! \file variable_type_map.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/expr/variable_type_map.i b/src/expr/variable_type_map.i index 95c705c1e..17ca6a110 100644 --- a/src/expr/variable_type_map.i +++ b/src/expr/variable_type_map.i @@ -2,6 +2,50 @@ #include "expr/variable_type_map.h" %} +#if SWIGJAVA + +%typemap(javabody) CVC4::VariableTypeMap %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; + + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; + } + + public VariableTypeMap(ExprManager em) { + this(); + this.em = em; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +%} + +// Workaround for https://github.com/swig/swig/commit/63a5a8af88271559a7b170794b4c61c30b8934ea +%typemap(javaconstruct) VariableTypeMap { + this(null, $imcall, true); +} + +%typemap(javaconstruct) CVC4::VariableTypeMap { + this(null, $imcall, true); +} + +%typemap(javaout) CVC4::Expr& { + return new Expr(this.em, $jnicall, false); +} + +%typemap(javaout) CVC4::Type& { + return new Type(this.em, $jnicall, false); +} + +%javamethodmodifiers CVC4::VariableTypeMap::VariableTypeMap() "private"; + +#endif /* SWIGJAVA */ + %rename(get) CVC4::VariableTypeMap::operator[](Expr); %rename(get) CVC4::VariableTypeMap::operator[](Type); diff --git a/src/include/cvc4.h b/src/include/cvc4.h index 86433731f..89c90a8c4 100644 --- a/src/include/cvc4.h +++ b/src/include/cvc4.h @@ -2,9 +2,9 @@ /*! \file cvc4.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/include/cvc4_private.h b/src/include/cvc4_private.h index cadbbae33..ebf074f31 100644 --- a/src/include/cvc4_private.h +++ b/src/include/cvc4_private.h @@ -2,9 +2,9 @@ /*! \file cvc4_private.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Mathias Preiner, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/include/cvc4_private_library.h b/src/include/cvc4_private_library.h index 6c0c8f324..875a4d78b 100644 --- a/src/include/cvc4_private_library.h +++ b/src/include/cvc4_private_library.h @@ -2,9 +2,9 @@ /*! \file cvc4_private_library.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli, Tim King + ** Andres Noetzli, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/include/cvc4_public.h b/src/include/cvc4_public.h index 39b919f9f..9cd2f9469 100644 --- a/src/include/cvc4_public.h +++ b/src/include/cvc4_public.h @@ -2,9 +2,9 @@ /*! \file cvc4_public.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/include/cvc4parser_private.h b/src/include/cvc4parser_private.h index 203105fe6..51bf5ba17 100644 --- a/src/include/cvc4parser_private.h +++ b/src/include/cvc4parser_private.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/include/cvc4parser_public.h b/src/include/cvc4parser_public.h index fe8d017bf..08c8bdc08 100644 --- a/src/include/cvc4parser_public.h +++ b/src/include/cvc4parser_public.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/lib/clock_gettime.c b/src/lib/clock_gettime.c index 82cb8a4cb..733f3cb7c 100644 --- a/src/lib/clock_gettime.c +++ b/src/lib/clock_gettime.c @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/lib/clock_gettime.h b/src/lib/clock_gettime.h index d9382f506..83164e7cf 100644 --- a/src/lib/clock_gettime.h +++ b/src/lib/clock_gettime.h @@ -2,9 +2,9 @@ /*! \file clock_gettime.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/lib/ffs.c b/src/lib/ffs.c index 4715b35f2..3421e590a 100644 --- a/src/lib/ffs.c +++ b/src/lib/ffs.c @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/lib/ffs.h b/src/lib/ffs.h index ce7ecc2a1..aa6c6cf4a 100644 --- a/src/lib/ffs.h +++ b/src/lib/ffs.h @@ -2,9 +2,9 @@ /*! \file ffs.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/lib/replacements.h b/src/lib/replacements.h index fef6baa28..768ba03fe 100644 --- a/src/lib/replacements.h +++ b/src/lib/replacements.h @@ -2,9 +2,9 @@ /*! \file replacements.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/lib/strtok_r.c b/src/lib/strtok_r.c index 1d0e039b0..1be1aefa6 100644 --- a/src/lib/strtok_r.c +++ b/src/lib/strtok_r.c @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/lib/strtok_r.h b/src/lib/strtok_r.h index 0640893c9..db90b24e8 100644 --- a/src/lib/strtok_r.h +++ b/src/lib/strtok_r.h @@ -2,9 +2,9 @@ /*! \file strtok_r.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/main/command_executor.cpp b/src/main/command_executor.cpp index c5ed54925..7081e0f56 100644 --- a/src/main/command_executor.cpp +++ b/src/main/command_executor.cpp @@ -2,9 +2,9 @@ /*! \file command_executor.cpp ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal, Tim King, Morgan Deters + ** Kshitij Bansal, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/main/command_executor.h b/src/main/command_executor.h index a9b6d9077..ca49d9964 100644 --- a/src/main/command_executor.h +++ b/src/main/command_executor.h @@ -2,9 +2,9 @@ /*! \file command_executor.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Kshitij Bansal, Aina Niemetz + ** Aina Niemetz, Kshitij Bansal, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/main/driver_unified.cpp b/src/main/driver_unified.cpp index 0f440ac37..7a39f5fc2 100644 --- a/src/main/driver_unified.cpp +++ b/src/main/driver_unified.cpp @@ -2,9 +2,9 @@ /*! \file driver_unified.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Liana Hadarean + ** Morgan Deters, Liana Hadarean, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/main/interactive_shell.cpp b/src/main/interactive_shell.cpp index f582d20e5..bb28c6dbc 100644 --- a/src/main/interactive_shell.cpp +++ b/src/main/interactive_shell.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Christopher L. Conway, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/main/interactive_shell.h b/src/main/interactive_shell.h index 7ed5a1c1f..87845b0ed 100644 --- a/src/main/interactive_shell.h +++ b/src/main/interactive_shell.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Christopher L. Conway, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/main/main.cpp b/src/main/main.cpp index 96ba1bc93..9cf168392 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Christopher L. Conway ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -57,9 +57,9 @@ int main(int argc, char* argv[]) { #ifdef CVC4_COMPETITION_MODE *opts.getOut() << "unknown" << endl; #endif - cerr << "CVC4 Error:" << endl << e << endl << endl - << "Please use --help to get help on command-line options." - << endl; + cerr << "(error \"" << e << "\")" << endl + << endl + << "Please use --help to get help on command-line options." << endl; } catch(Exception& e) { #ifdef CVC4_COMPETITION_MODE *opts.getOut() << "unknown" << endl; @@ -68,7 +68,7 @@ int main(int argc, char* argv[]) { { *opts.getOut() << "(error \"" << e << "\")" << endl; } else { - *opts.getErr() << "CVC4 Error:" << endl << e << endl; + *opts.getErr() << "(error \"" << e << "\")" << endl; } if(opts.getStatistics() && pExecutor != NULL) { pTotalTime->stop(); diff --git a/src/main/main.h b/src/main/main.h index 266d043aa..6d321f05a 100644 --- a/src/main/main.h +++ b/src/main/main.h @@ -2,9 +2,9 @@ /*! \file main.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Andres Noetzli + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/main/util.cpp b/src/main/util.cpp index 115703b09..69f79e56c 100644 --- a/src/main/util.cpp +++ b/src/main/util.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andres Noetzli, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/arith_options.toml b/src/options/arith_options.toml index d16513cfb..ce747b62d 100644 --- a/src/options/arith_options.toml +++ b/src/options/arith_options.toml @@ -429,22 +429,13 @@ header = "options/arith_options.h" help = "apply pseudo boolean rewrites" [[option]] - name = "sNormInferEq" - category = "regular" - long = "snorm-infer-eq" - type = "bool" - default = "false" - read_only = true - help = "infer equalities based on Shostak normalization" - -[[option]] name = "nlExt" category = "regular" long = "nl-ext" type = "bool" default = "true" read_only = true - help = "extended approach to non-linear" + help = "incremental linearization approach to non-linear" [[option]] name = "nlExtResBound" @@ -453,7 +444,7 @@ header = "options/arith_options.h" type = "bool" default = "false" read_only = true - help = "use resolution-style inference for inferring new bounds" + help = "use resolution-style inference for inferring new bounds in non-linear incremental linearization solver" [[option]] name = "nlExtFactor" @@ -462,7 +453,7 @@ header = "options/arith_options.h" type = "bool" default = "true" read_only = true - help = "use factoring inference in non-linear solver" + help = "use factoring inference in non-linear incremental linearization solver" [[option]] name = "nlExtTangentPlanes" @@ -471,7 +462,7 @@ header = "options/arith_options.h" type = "bool" default = "false" read_only = true - help = "use non-terminating tangent plane strategy for non-linear" + help = "use non-terminating tangent plane strategy for non-linear incremental linearization solver" [[option]] name = "nlExtTangentPlanesInterleave" @@ -479,7 +470,7 @@ header = "options/arith_options.h" long = "nl-ext-tplanes-interleave" type = "bool" default = "false" - help = "interleave tangent plane strategy for non-linear" + help = "interleave tangent plane strategy for non-linear incremental linearization solver" [[option]] name = "nlExtTfTangentPlanes" @@ -488,7 +479,7 @@ header = "options/arith_options.h" type = "bool" default = "true" read_only = true - help = "use non-terminating tangent plane strategy for transcendental functions for non-linear" + help = "use non-terminating tangent plane strategy for transcendental functions for non-linear incremental linearization solver" [[option]] name = "nlExtEntailConflicts" @@ -506,7 +497,7 @@ header = "options/arith_options.h" type = "bool" default = "true" read_only = true - help = "do rewrites in non-linear solver" + help = "do context-dependent simplification based on rewrites in non-linear solver" [[option]] name = "nlExtPurify" diff --git a/src/options/arrays_options.toml b/src/options/arrays_options.toml index 8c82a7fb5..389bb6e4c 100644 --- a/src/options/arrays_options.toml +++ b/src/options/arrays_options.toml @@ -73,3 +73,12 @@ header = "options/arrays_options.h" type = "int" default = "2" help = "propagation effort for arrays: 0 is none, 1 is some, 2 is full" + +[[option]] + name = "arraysExp" + category = "experimental" + long = "arrays-exp" + type = "bool" + default = "false" + help = "enable experimental features in the theory of arrays" + diff --git a/src/options/base_handlers.h b/src/options/base_handlers.h index fae6549f3..ba14e49a1 100644 --- a/src/options/base_handlers.h +++ b/src/options/base_handlers.h @@ -2,9 +2,9 @@ /*! \file base_handlers.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/bv_options.toml b/src/options/bv_options.toml index 5c8cd8f58..517d864d3 100644 --- a/src/options/bv_options.toml +++ b/src/options/bv_options.toml @@ -286,9 +286,9 @@ header = "options/bv_options.h" help = "algebraic inferences for extended functions" [[option]] - name = "bvPrintConstsInBinary" + name = "bvPrintConstsAsIndexedSymbols" category = "regular" - long = "bv-print-consts-in-binary" + long = "bv-print-consts-as-indexed-symbols" type = "bool" default = "false" - help = "print bit-vector constants in binary (e.g. #b0001) instead of decimal (e.g. (_ bv1 4)), applies to SMT-LIB 2.x" + help = "print bit-vector constants in decimal (e.g. (_ bv1 4)) instead of binary (e.g. #b0001), applies to SMT-LIB 2.x" diff --git a/src/options/datatypes_options.toml b/src/options/datatypes_options.toml index ac371efeb..19434fa33 100644 --- a/src/options/datatypes_options.toml +++ b/src/options/datatypes_options.toml @@ -68,6 +68,15 @@ header = "options/datatypes_options.h" help = "when applicable, blast splitting lemmas for all variables at once" [[option]] + name = "dtNestedRec" + category = "regular" + long = "dt-nested-rec" + type = "bool" + default = "false" + read_only = true + help = "allow nested recursion in datatype definitions" + +[[option]] name = "dtSharedSelectors" category = "regular" long = "dt-share-sel" diff --git a/src/options/decision_weight.h b/src/options/decision_weight.h index 16c12a3b4..3fc7f037f 100644 --- a/src/options/decision_weight.h +++ b/src/options/decision_weight.h @@ -2,9 +2,9 @@ /*! \file decision_weight.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Kshitij Bansal + ** Mathias Preiner, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/didyoumean.cpp b/src/options/didyoumean.cpp index cbaa4d09e..a420beb37 100644 --- a/src/options/didyoumean.cpp +++ b/src/options/didyoumean.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Kshitij Bansal, Tim King, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/didyoumean.h b/src/options/didyoumean.h index f33716565..abace1352 100644 --- a/src/options/didyoumean.h +++ b/src/options/didyoumean.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Kshitij Bansal, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/didyoumean_test.cpp b/src/options/didyoumean_test.cpp index 2dd28a40f..8ff0a5847 100644 --- a/src/options/didyoumean_test.cpp +++ b/src/options/didyoumean_test.cpp @@ -2,9 +2,9 @@ /*! \file didyoumean_test.cpp ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal, Tim King + ** Kshitij Bansal, Tim King, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/language.cpp b/src/options/language.cpp index 885549b43..b00d5c102 100644 --- a/src/options/language.cpp +++ b/src/options/language.cpp @@ -2,9 +2,9 @@ /*! \file language.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andrew Reynolds, Andres Noetzli + ** Andrew Reynolds, Morgan Deters, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -29,15 +29,12 @@ Language LANG_SMTLIB_V2_END = LANG_SMTLIB_V2_6; bool isInputLang_smt2(InputLanguage lang) { - return (lang >= input::LANG_SMTLIB_V2_0 && lang <= input::LANG_SMTLIB_V2_END) - || lang == input::LANG_Z3STR; + return lang >= input::LANG_SMTLIB_V2_0 && lang <= input::LANG_SMTLIB_V2_END; } bool isOutputLang_smt2(OutputLanguage lang) { - return (lang >= output::LANG_SMTLIB_V2_0 - && lang <= output::LANG_SMTLIB_V2_END) - || lang == output::LANG_Z3STR; + return lang >= output::LANG_SMTLIB_V2_0 && lang <= output::LANG_SMTLIB_V2_END; } bool isInputLang_smt2_5(InputLanguage lang, bool exact) @@ -70,12 +67,12 @@ bool isOutputLang_smt2_6(OutputLanguage lang, bool exact) bool isInputLangSygus(InputLanguage lang) { - return lang == input::LANG_SYGUS_V1 || lang == input::LANG_SYGUS_V2; + return lang == input::LANG_SYGUS_V2; } bool isOutputLangSygus(OutputLanguage lang) { - return lang == output::LANG_SYGUS_V1 || lang == output::LANG_SYGUS_V2; + return lang == output::LANG_SYGUS_V2; } InputLanguage toInputLanguage(OutputLanguage language) { @@ -85,8 +82,6 @@ InputLanguage toInputLanguage(OutputLanguage language) { case output::LANG_SMTLIB_V2_6: case output::LANG_TPTP: case output::LANG_CVC4: - case output::LANG_Z3STR: - case output::LANG_SYGUS_V1: case output::LANG_SYGUS_V2: // these entries directly correspond (by design) return InputLanguage(int(language)); @@ -107,8 +102,6 @@ OutputLanguage toOutputLanguage(InputLanguage language) { case input::LANG_SMTLIB_V2_6: case input::LANG_TPTP: case input::LANG_CVC4: - case input::LANG_Z3STR: - case input::LANG_SYGUS_V1: case input::LANG_SYGUS_V2: // these entries directly correspond (by design) return OutputLanguage(int(language)); @@ -152,13 +145,6 @@ OutputLanguage toOutputLanguage(std::string language) { return output::LANG_SMTLIB_V2_6; } else if(language == "tptp" || language == "LANG_TPTP") { return output::LANG_TPTP; - } else if(language == "z3str" || language == "z3-str" || - language == "LANG_Z3STR") { - return output::LANG_Z3STR; - } - else if (language == "sygus1" || language == "LANG_SYGUS_V1") - { - return output::LANG_SYGUS_V1; } else if (language == "sygus" || language == "LANG_SYGUS" || language == "sygus2" || language == "LANG_SYGUS_V2") @@ -195,13 +181,6 @@ InputLanguage toInputLanguage(std::string language) { return input::LANG_SMTLIB_V2_6; } else if(language == "tptp" || language == "LANG_TPTP") { return input::LANG_TPTP; - } else if(language == "z3str" || language == "z3-str" || - language == "LANG_Z3STR") { - return input::LANG_Z3STR; - } - else if (language == "sygus1" || language == "LANG_SYGUS_V1") - { - return input::LANG_SYGUS_V1; } else if (language == "sygus2" || language == "LANG_SYGUS_V2") { diff --git a/src/options/language.h b/src/options/language.h index d0bdc6e77..0a0f63ca6 100644 --- a/src/options/language.h +++ b/src/options/language.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andrew Reynolds, Francois Bobot ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -56,10 +56,6 @@ enum CVC4_PUBLIC Language LANG_TPTP, /** The CVC4 input language */ LANG_CVC4, - /** The Z3-str input language */ - LANG_Z3STR, - /** The SyGuS input language version 1.0 */ - LANG_SYGUS_V1, /** The SyGuS input language version 2.0 */ LANG_SYGUS_V2, @@ -91,10 +87,6 @@ inline std::ostream& operator<<(std::ostream& out, Language lang) { case LANG_CVC4: out << "LANG_CVC4"; break; - case LANG_Z3STR: - out << "LANG_Z3STR"; - break; - case LANG_SYGUS_V1: out << "LANG_SYGUS_V1"; break; case LANG_SYGUS_V2: out << "LANG_SYGUS_V2"; break; default: out << "undefined_input_language"; @@ -132,10 +124,6 @@ enum CVC4_PUBLIC Language LANG_TPTP = input::LANG_TPTP, /** The CVC4 output language */ LANG_CVC4 = input::LANG_CVC4, - /** The Z3-str output language */ - LANG_Z3STR = input::LANG_Z3STR, - /** The sygus output language version 1.0 */ - LANG_SYGUS_V1 = input::LANG_SYGUS_V1, /** The sygus output language version 2.0 */ LANG_SYGUS_V2 = input::LANG_SYGUS_V2, @@ -167,10 +155,6 @@ inline std::ostream& operator<<(std::ostream& out, Language lang) { case LANG_CVC4: out << "LANG_CVC4"; break; - case LANG_Z3STR: - out << "LANG_Z3STR"; - break; - case LANG_SYGUS_V1: out << "LANG_SYGUS_V1"; break; case LANG_SYGUS_V2: out << "LANG_SYGUS_V2"; break; case LANG_AST: out << "LANG_AST"; diff --git a/src/options/language.i b/src/options/language.i index 639cb0bda..7f81ea7c6 100644 --- a/src/options/language.i +++ b/src/options/language.i @@ -26,8 +26,6 @@ namespace CVC4 { %rename(INPUT_LANG_TPTP) CVC4::language::input::LANG_TPTP; %rename(INPUT_LANG_CVC4) CVC4::language::input::LANG_CVC4; %rename(INPUT_LANG_MAX) CVC4::language::input::LANG_MAX; -%rename(INPUT_LANG_Z3STR) CVC4::language::input::LANG_Z3STR; -%rename(INPUT_LANG_SYGUS_V1) CVC4::language::input::LANG_SYGUS_V1; %rename(INPUT_LANG_SYGUS_V2) CVC4::language::input::LANG_SYGUS_V2; %rename(OUTPUT_LANG_AUTO) CVC4::language::output::LANG_AUTO; @@ -39,8 +37,6 @@ namespace CVC4 { %rename(OUTPUT_LANG_CVC4) CVC4::language::output::LANG_CVC4; %rename(OUTPUT_LANG_AST) CVC4::language::output::LANG_AST; %rename(OUTPUT_LANG_MAX) CVC4::language::output::LANG_MAX; -%rename(OUTPUT_LANG_Z3STR) CVC4::language::output::LANG_Z3STR; -%rename(OUTPUT_LANG_SYGUS_V1) CVC4::language::output::LANG_SYGUS_V1; %rename(OUTPUT_LANG_SYGUS_V2) CVC4::language::output::LANG_SYGUS_V2; %include "options/language.h" diff --git a/src/options/module_template.cpp b/src/options/module_template.cpp index 9ac94477c..f0b4210d3 100644 --- a/src/options/module_template.cpp +++ b/src/options/module_template.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/module_template.h b/src/options/module_template.h index e3eb30fe1..4aa44d866 100644 --- a/src/options/module_template.h +++ b/src/options/module_template.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/open_ostream.cpp b/src/options/open_ostream.cpp index c65e5da2a..b5ffe8eeb 100644 --- a/src/options/open_ostream.cpp +++ b/src/options/open_ostream.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/open_ostream.h b/src/options/open_ostream.h index 592db925f..883743960 100644 --- a/src/options/open_ostream.h +++ b/src/options/open_ostream.h @@ -2,9 +2,9 @@ /*! \file open_ostream.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/option_exception.cpp b/src/options/option_exception.cpp index 09bc94023..17ae41dc2 100644 --- a/src/options/option_exception.cpp +++ b/src/options/option_exception.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/option_exception.h b/src/options/option_exception.h index d337d4c9b..c5b116cda 100644 --- a/src/options/option_exception.h +++ b/src/options/option_exception.h @@ -2,9 +2,9 @@ /*! \file option_exception.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli, Tim King + ** Morgan Deters, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/options.h b/src/options/options.h index c63af1c64..b561b3426 100644 --- a/src/options/options.h +++ b/src/options/options.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Paul Meng ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/options.i b/src/options/options.i index ba98c4fc4..319b4addb 100644 --- a/src/options/options.i +++ b/src/options/options.i @@ -2,6 +2,21 @@ #include "options/options.h" %} +%ignore CVC4::Options::registerAndNotify(ListenerCollection& collection, Listener* listener, bool notify); +%ignore CVC4::Options::registerBeforeSearchListener(Listener* listener); +%ignore CVC4::Options::registerTlimitListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerTlimitPerListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerRlimitListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerRlimitPerListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerSetDefaultExprDepthListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerSetDefaultExprDagListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerSetPrintExprTypesListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerSetDumpModeListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerSetPrintSuccessListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerDumpToFileNameListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerSetRegularOutputChannelListener(Listener* listener, bool notifyIfSet); +%ignore CVC4::Options::registerSetDiagnosticOutputChannelListener(Listener* listener, bool notifyIfSet); + %apply char** STRING_ARRAY { char* argv[] } %include "options/options.h" %clear char* argv[]; diff --git a/src/options/options_handler.cpp b/src/options/options_handler.cpp index af811e085..500cd90c5 100644 --- a/src/options/options_handler.cpp +++ b/src/options/options_handler.cpp @@ -2,9 +2,9 @@ /*! \file options_handler.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Morgan Deters + ** Tim King, Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/options_handler.h b/src/options/options_handler.h index 283558709..9a5af8865 100644 --- a/src/options/options_handler.h +++ b/src/options/options_handler.h @@ -2,9 +2,9 @@ /*! \file options_handler.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Andrew Reynolds, Aina Niemetz + ** Tim King, Mathias Preiner, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/options_holder_template.h b/src/options/options_holder_template.h index 4cd77a441..caaefdaa4 100644 --- a/src/options/options_holder_template.h +++ b/src/options/options_holder_template.h @@ -2,9 +2,9 @@ /*! \file options_holder_template.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Mathias Preiner + ** Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/options_public_functions.cpp b/src/options/options_public_functions.cpp index c7bd1006f..26cf14dfe 100644 --- a/src/options/options_public_functions.cpp +++ b/src/options/options_public_functions.cpp @@ -2,9 +2,9 @@ /*! \file options_public_functions.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Paul Meng + ** Tim King, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/options_template.cpp b/src/options/options_template.cpp index a6489fcc4..234ddd5b4 100644 --- a/src/options/options_template.cpp +++ b/src/options/options_template.cpp @@ -2,9 +2,9 @@ /*! \file options_template.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Mathias Preiner + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -418,7 +418,6 @@ Languages currently supported as arguments to the -L / --lang option:\n\ smt2.5 | smtlib2.5 SMT-LIB format 2.5\n\ smt2.6 | smtlib2.6 SMT-LIB format 2.6 with support for the strings standard\n\ tptp TPTP format (cnf, fof and tff)\n\ - sygus1 SyGuS version 1.0 \n\ sygus | sygus2 SyGuS version 2.0\n\ \n\ Languages currently supported as arguments to the --output-lang option:\n\ @@ -430,7 +429,6 @@ Languages currently supported as arguments to the --output-lang option:\n\ smt2.5 | smtlib2.5 SMT-LIB format 2.5\n\ smt2.6 | smtlib2.6 SMT-LIB format 2.6 with support for the strings standard\n\ tptp TPTP format\n\ - z3str SMT-LIB 2.0 with Z3-str string constraints\n\ ast internal format (simple syntax trees)\n\ "; diff --git a/src/options/printer_modes.cpp b/src/options/printer_modes.cpp index db116dd05..0bd770c67 100644 --- a/src/options/printer_modes.cpp +++ b/src/options/printer_modes.cpp @@ -2,9 +2,9 @@ /*! \file printer_modes.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Mathias Preiner, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/printer_modes.h b/src/options/printer_modes.h index 10f8a4eac..b743b821b 100644 --- a/src/options/printer_modes.h +++ b/src/options/printer_modes.h @@ -2,9 +2,9 @@ /*! \file printer_modes.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Morgan Deters + ** Mathias Preiner, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 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/set_language.cpp b/src/options/set_language.cpp index dfdbb1ab7..042165194 100644 --- a/src/options/set_language.cpp +++ b/src/options/set_language.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/set_language.h b/src/options/set_language.h index 0e3b32dd7..abd12f21b 100644 --- a/src/options/set_language.h +++ b/src/options/set_language.h @@ -2,9 +2,9 @@ /*! \file set_language.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/options/smt_options.toml b/src/options/smt_options.toml index 08e6f317c..c104cb3e7 100644 --- a/src/options/smt_options.toml +++ b/src/options/smt_options.toml @@ -165,6 +165,23 @@ header = "options/smt_options.h" help = "output proofs after every UNSAT/VALID response" [[option]] + name = "proofNew" + category = "regular" + long = "proof-new" + type = "bool" + default = "false" + help = "do proof production using the new infrastructure" + +[[option]] + name = "proofNewPedantic" + category = "regular" + long = "proof-new-pedantic" + type = "bool" + default = "false" + read_only = true + help = "assertion failure for any incorrect rule application or untrusted lemma for fully supported portions with proof-new" + +[[option]] name = "dumpInstantiations" category = "regular" long = "dump-instantiations" @@ -346,7 +363,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" @@ -652,6 +669,34 @@ header = "options/smt_options.h" help = "attempt to solve a pure real satisfiable problem as an integer problem (for non-linear)" [[option]] + name = "produceInterpols" + category = "undocumented" + long = "produce-interpols=MODE" + type = "ProduceInterpols" + default = "NONE" + read_only = true + help = "support the get-interpol command" + help_mode = "Interpolants grammar mode" +[[option.mode.NONE]] + name = "none" + help = "don't compute interpolants" +[[option.mode.DEFAULT]] + name = "default" + help = "use the default grammar for the theory or the user-defined grammar if given" +[[option.mode.ASSUMPTIONS]] + name = "assumptions" + help = "use only operators that occur in the assumptions" +[[option.mode.CONJECTURE]] + name = "conjecture" + help = "use only operators that occur in the conjecture" +[[option.mode.SHARED]] + name = "shared" + help = "use only operators that occur both in the assumptions and the conjecture" +[[option.mode.ALL]] + name = "all" + help = "use only operators that occur either in the assumptions or the conjecture" + +[[option]] name = "produceAbducts" category = "undocumented" long = "produce-abducts" @@ -661,6 +706,15 @@ header = "options/smt_options.h" help = "support the get-abduct command" [[option]] + name = "checkInterpols" + category = "regular" + long = "check-interpols" + type = "bool" + default = "false" + read_only = true + help = "checks whether produced solutions to get-interpol are correct" + +[[option]] name = "checkAbducts" category = "regular" long = "check-abducts" diff --git a/src/parser/antlr_input.cpp b/src/parser/antlr_input.cpp index 6dc26d439..1d5190e3f 100644 --- a/src/parser/antlr_input.cpp +++ b/src/parser/antlr_input.cpp @@ -2,9 +2,9 @@ /*! \file antlr_input.cpp ** \verbatim ** Top contributors (to current version): - ** Christopher L. Conway, Kshitij Bansal, Morgan Deters + ** Christopher L. Conway, Kshitij Bansal, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -247,7 +247,6 @@ AntlrInput* AntlrInput::newInput(InputLanguage lang, AntlrInputStream& inputStre break; } - case LANG_SYGUS_V1: case LANG_SYGUS_V2: input = new SygusInput(inputStream); break; case LANG_TPTP: diff --git a/src/parser/antlr_input.h b/src/parser/antlr_input.h index 9c53e0349..d3ae9761d 100644 --- a/src/parser/antlr_input.h +++ b/src/parser/antlr_input.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Christopher L. Conway, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/antlr_input_imports.cpp b/src/parser/antlr_input_imports.cpp index 39b109232..dd0c078a2 100644 --- a/src/parser/antlr_input_imports.cpp +++ b/src/parser/antlr_input_imports.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Christopher L. Conway, Francois Bobot, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/antlr_line_buffered_input.cpp b/src/parser/antlr_line_buffered_input.cpp index 052bd5f7f..cdf553880 100644 --- a/src/parser/antlr_line_buffered_input.cpp +++ b/src/parser/antlr_line_buffered_input.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andres Noetzli, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/antlr_line_buffered_input.h b/src/parser/antlr_line_buffered_input.h index 34cb72f1e..edd119d75 100644 --- a/src/parser/antlr_line_buffered_input.h +++ b/src/parser/antlr_line_buffered_input.h @@ -2,9 +2,9 @@ /*! \file antlr_line_buffered_input.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli + ** Andres Noetzli, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/antlr_tracing.h b/src/parser/antlr_tracing.h index d2eb742c2..c59b21233 100644 --- a/src/parser/antlr_tracing.h +++ b/src/parser/antlr_tracing.h @@ -2,9 +2,9 @@ /*! \file antlr_tracing.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/bounded_token_buffer.cpp b/src/parser/bounded_token_buffer.cpp index 5746793e3..f93b47042 100644 --- a/src/parser/bounded_token_buffer.cpp +++ b/src/parser/bounded_token_buffer.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Christopher L. Conway, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/bounded_token_buffer.h b/src/parser/bounded_token_buffer.h index 8afe6864a..f5237dc9d 100644 --- a/src/parser/bounded_token_buffer.h +++ b/src/parser/bounded_token_buffer.h @@ -2,9 +2,9 @@ /*! \file bounded_token_buffer.h ** \verbatim ** Top contributors (to current version): - ** Christopher L. Conway, Morgan Deters + ** Christopher L. Conway, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/bounded_token_factory.cpp b/src/parser/bounded_token_factory.cpp index fb6208d0c..2af675dbc 100644 --- a/src/parser/bounded_token_factory.cpp +++ b/src/parser/bounded_token_factory.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Christopher L. Conway ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/bounded_token_factory.h b/src/parser/bounded_token_factory.h index f2df9ac36..0f6cd5afe 100644 --- a/src/parser/bounded_token_factory.h +++ b/src/parser/bounded_token_factory.h @@ -2,9 +2,9 @@ /*! \file bounded_token_factory.h ** \verbatim ** Top contributors (to current version): - ** Christopher L. Conway, Morgan Deters + ** Christopher L. Conway, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/cvc/Cvc.g b/src/parser/cvc/Cvc.g index 8e4152e2e..b504d290b 100644 --- a/src/parser/cvc/Cvc.g +++ b/src/parser/cvc/Cvc.g @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andrew Reynolds, Christopher L. Conway ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -935,15 +935,8 @@ mainCommand[std::unique_ptr<CVC4::Command>* cmd] PARSER_STATE->parseError("Type mismatch in definition"); } } - std::vector<std::vector<Expr>> eformals; - for (unsigned i=0, fsize = formals.size(); i<fsize; i++) - { - eformals.push_back(api::termVectorToExprs(formals[i])); - } cmd->reset( - new DefineFunctionRecCommand(api::termVectorToExprs(funcs), - eformals, - api::termVectorToExprs(formulas))); + new DefineFunctionRecCommand(SOLVER, funcs, formals, formulas, true)); } | toplevelDeclaration[cmd] ; @@ -1159,11 +1152,11 @@ 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 = - new DefineFunctionCommand(*i, func.getExpr(), f.getExpr()); + new DefineFunctionCommand(*i, func.getExpr(), f.getExpr(), true); seq->addCommand(decl); } } @@ -1654,7 +1647,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 +1680,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 +1824,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 +1841,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 +1854,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 +1865,7 @@ postfixTerm[CVC4::api::Term& f] ) ( typeAscription[f, t] { - f = PARSER_STATE->applyTypeAscription(f,t).getExpr(); + f = PARSER_STATE->applyTypeAscription(f,t); } )? ; @@ -1885,8 +1882,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 +2133,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 +2143,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 +2153,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 +2252,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 +2360,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/cvc/cvc.cpp b/src/parser/cvc/cvc.cpp index f312fe13c..4d409a0b4 100644 --- a/src/parser/cvc/cvc.cpp +++ b/src/parser/cvc/cvc.cpp @@ -2,9 +2,9 @@ /*! \file cvc.cpp ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/cvc/cvc.h b/src/parser/cvc/cvc.h index 58d387ca8..7c226168f 100644 --- a/src/parser/cvc/cvc.h +++ b/src/parser/cvc/cvc.h @@ -2,9 +2,9 @@ /*! \file cvc.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andres Noetzli, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/cvc/cvc_input.cpp b/src/parser/cvc/cvc_input.cpp index 38e3594e8..32ed589ab 100644 --- a/src/parser/cvc/cvc_input.cpp +++ b/src/parser/cvc/cvc_input.cpp @@ -2,9 +2,9 @@ /*! \file cvc_input.cpp ** \verbatim ** Top contributors (to current version): - ** Christopher L. Conway, Morgan Deters + ** Christopher L. Conway, Morgan Deters, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/cvc/cvc_input.h b/src/parser/cvc/cvc_input.h index 50be82903..3e46dcb65 100644 --- a/src/parser/cvc/cvc_input.h +++ b/src/parser/cvc/cvc_input.h @@ -2,9 +2,9 @@ /*! \file cvc_input.h ** \verbatim ** Top contributors (to current version): - ** Christopher L. Conway, Morgan Deters, Tim King + ** Christopher L. Conway, Mathias Preiner, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/input.cpp b/src/parser/input.cpp index 78e9b474d..13903eaf5 100644 --- a/src/parser/input.cpp +++ b/src/parser/input.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Christopher L. Conway, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/input.h b/src/parser/input.h index f63a55707..35f2ae0fb 100644 --- a/src/parser/input.h +++ b/src/parser/input.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Christopher L. Conway, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/line_buffer.cpp b/src/parser/line_buffer.cpp index 6e7614d88..35ecbfdbb 100644 --- a/src/parser/line_buffer.cpp +++ b/src/parser/line_buffer.cpp @@ -2,9 +2,9 @@ /*! \file line_buffer.cpp ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli, Aina Niemetz + ** Andres Noetzli, Mathias Preiner, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/line_buffer.h b/src/parser/line_buffer.h index e8ab05691..6557539eb 100644 --- a/src/parser/line_buffer.h +++ b/src/parser/line_buffer.h @@ -2,9 +2,9 @@ /*! \file line_buffer.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/memory_mapped_input_buffer.cpp b/src/parser/memory_mapped_input_buffer.cpp index 2fa0bd7b9..a753c2404 100644 --- a/src/parser/memory_mapped_input_buffer.cpp +++ b/src/parser/memory_mapped_input_buffer.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Christopher L. Conway, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/memory_mapped_input_buffer.h b/src/parser/memory_mapped_input_buffer.h index ee143c6b3..a601704c7 100644 --- a/src/parser/memory_mapped_input_buffer.h +++ b/src/parser/memory_mapped_input_buffer.h @@ -2,9 +2,9 @@ /*! \file memory_mapped_input_buffer.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Christopher L. Conway + ** Morgan Deters, Mathias Preiner, Christopher L. Conway ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/parse_op.cpp b/src/parser/parse_op.cpp index 899ae6893..8ff1619fb 100644 --- a/src/parser/parse_op.cpp +++ b/src/parser/parse_op.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/parse_op.h b/src/parser/parse_op.h index 1105cf0c8..c68de390f 100644 --- a/src/parser/parse_op.h +++ b/src/parser/parse_op.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index c860d14c7..5d80dd55f 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -2,9 +2,9 @@ /*! \file parser.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andrew Reynolds, Christopher L. Conway + ** Andrew Reynolds, Morgan Deters, Christopher L. Conway ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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,14 +377,25 @@ 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); return unresolved; } +api::Sort Parser::mkUnresolvedType(const std::string& name, size_t arity) +{ + if (arity == 0) + { + return mkUnresolvedType(name); + } + return mkUnresolvedTypeConstructor(name, arity); +} + bool Parser::isUnresolvedType(const std::string& name) { if (!isDeclared(name, SYM_SORT)) { return false; @@ -588,11 +597,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 +634,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 +902,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..84dd4be0c 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -2,9 +2,9 @@ /*! \file parser.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andrew Reynolds, Christopher L. Conway + ** Andrew Reynolds, Morgan Deters, Christopher L. Conway ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -589,6 +589,13 @@ public: const std::vector<api::Sort>& params); /** + * Creates a new unresolved (parameterized) type constructor of the given + * arity. Calls either mkUnresolvedType or mkUnresolvedTypeConstructor + * depending on the arity. + */ + api::Sort mkUnresolvedType(const std::string& name, size_t arity); + + /** * Returns true IFF name is an unresolved type. */ bool isUnresolvedType(const std::string& name); @@ -805,10 +812,12 @@ public: d_globalDeclarations = flag; } + bool getGlobalDeclarations() { return d_globalDeclarations; } + inline SymbolTable* getSymbolTable() const { return d_symtab; } - + //------------------------ operator overloading /** is this function overloaded? */ bool isOverloadedFunction(api::Term fun) @@ -822,7 +831,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 +843,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 +856,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/parser_builder.cpp b/src/parser/parser_builder.cpp index 651dd560c..f65618267 100644 --- a/src/parser/parser_builder.cpp +++ b/src/parser/parser_builder.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Christopher L. Conway, Morgan Deters, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -89,7 +89,6 @@ Parser* ParserBuilder::build() Parser* parser = NULL; switch (d_lang) { - case language::input::LANG_SYGUS_V1: case language::input::LANG_SYGUS_V2: parser = new Smt2(d_solver, input, d_strictMode, d_parseOnly); break; diff --git a/src/parser/parser_builder.h b/src/parser/parser_builder.h index 1a9ca719e..52dc76581 100644 --- a/src/parser/parser_builder.h +++ b/src/parser/parser_builder.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Christopher L. Conway, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/parser_exception.h b/src/parser/parser_exception.h index cd5e162d2..118cc589f 100644 --- a/src/parser/parser_exception.h +++ b/src/parser/parser_exception.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Christopher L. Conway ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/smt2/Smt2.g b/src/parser/smt2/Smt2.g index d591c29de..703696cf5 100644 --- a/src/parser/smt2/Smt2.g +++ b/src/parser/smt2/Smt2.g @@ -2,9 +2,9 @@ /*! \file Smt2.g ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andrew Reynolds, Tim King + ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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())); } @@ -305,14 +305,7 @@ command [std::unique_ptr<CVC4::Command>* cmd] PARSER_STATE->checkLogicAllowsFunctions(); } // we allow overloading for function declarations - if (PARSER_STATE->sygus_v1()) - { - // it is a higher-order universal variable - api::Term func = PARSER_STATE->bindBoundVar(name, t); - cmd->reset( - new DeclareSygusFunctionCommand(name, func.getExpr(), t.getType())); - } - else if( PARSER_STATE->sygus() ) + if( PARSER_STATE->sygus() ) { PARSER_STATE->parseErrorLogic("declare-fun are not allowed in sygus " "version 2.0"); @@ -361,8 +354,12 @@ command [std::unique_ptr<CVC4::Command>* cmd] // we allow overloading for function definitions api::Term func = PARSER_STATE->bindVar(name, t, ExprManager::VAR_FLAG_DEFINED, true); - cmd->reset(new DefineFunctionCommand( - name, func.getExpr(), api::termVectorToExprs(terms), expr.getExpr())); + cmd->reset( + new DefineFunctionCommand(name, + func.getExpr(), + api::termVectorToExprs(terms), + expr.getExpr(), + PARSER_STATE->getGlobalDeclarations())); } | DECLARE_DATATYPE_TOK datatypeDefCommand[false, cmd] | DECLARE_DATATYPES_TOK datatypesDefCommand[false, cmd] @@ -563,40 +560,8 @@ sygusCommand returns [std::unique_ptr<CVC4::Command> cmd] api::Term var = PARSER_STATE->bindBoundVar(name, t); cmd.reset(new DeclareSygusVarCommand(name, var.getExpr(), t.getType())); } - | /* declare-primed-var */ - DECLARE_PRIMED_VAR_TOK { PARSER_STATE->checkThatLogicIsSet(); } - symbol[name,CHECK_UNDECLARED,SYM_VARIABLE] - { PARSER_STATE->checkUserSymbol(name); } - sortSymbol[t,CHECK_DECLARED] - { - // spurious command, we do not need to create a variable. We only keep - // track of the command for sanity checking / dumping - cmd.reset(new DeclareSygusPrimedVarCommand(name, t.getType())); - } | /* synth-fun */ - ( SYNTH_FUN_V1_TOK { isInv = false; } - | SYNTH_INV_V1_TOK { isInv = true; range = SOLVER->getBooleanSort(); } - ) - { PARSER_STATE->checkThatLogicIsSet(); } - symbol[fun,CHECK_UNDECLARED,SYM_VARIABLE] - LPAREN_TOK sortedVarList[sortedVarNames] RPAREN_TOK - ( sortSymbol[range,CHECK_DECLARED] )? - { - synthFunFactory.reset(new Smt2::SynthFunFactory( - PARSER_STATE, fun, isInv, range, sortedVarNames)); - } - ( - // optionally, read the sygus grammar - // - // `grammar` specifies the required grammar for the function to - // synthesize, expressed as a type - sygusGrammarV1[grammar, synthFunFactory->getSygusVars(), fun] - )? - { - cmd = synthFunFactory->mkCommand(grammar); - } - | /* synth-fun */ ( SYNTH_FUN_TOK { isInv = false; } | SYNTH_INV_TOK { isInv = true; range = SOLVER->getBooleanSort(); } ) @@ -643,292 +608,6 @@ sygusCommand returns [std::unique_ptr<CVC4::Command> cmd] | command[&cmd] ; -/** Reads a sygus grammar - * - * The resulting sygus datatype encoding the grammar is stored in ret. - * The argument sygus_vars indicates the sygus bound variable list, which is - * the argument list of the function-to-synthesize (or null if the grammar - * has bound variables). - * The argument fun is a unique identifier to avoid naming clashes for the - * datatypes constructed by this call. - */ -sygusGrammarV1[CVC4::api::Sort & ret, - const std::vector<CVC4::api::Term>& sygus_vars, - const std::string& fun] -@declarations -{ - CVC4::api::Sort t; - std::string name; - unsigned startIndex = 0; - std::vector<std::vector<CVC4::SygusGTerm>> sgts; - std::vector<api::DatatypeDecl> datatypes; - std::vector<api::Sort> sorts; - std::vector<std::vector<ParseOp>> ops; - std::vector<std::vector<std::string>> cnames; - std::vector<std::vector<std::vector<CVC4::api::Sort>>> cargs; - std::vector<bool> allow_const; - std::vector<std::vector<std::string>> unresolved_gterm_sym; - std::map<CVC4::api::Sort, CVC4::api::Sort> sygus_to_builtin; - std::map<CVC4::api::Sort, CVC4::api::Term> sygus_to_builtin_expr; -} - : LPAREN_TOK { PARSER_STATE->pushScope(); } - (LPAREN_TOK - symbol[name, CHECK_NONE, SYM_VARIABLE] sortSymbol[t, CHECK_DECLARED] { - if (name == "Start") - { - startIndex = datatypes.size(); - } - sgts.push_back(std::vector<CVC4::SygusGTerm>()); - sgts.back().push_back(CVC4::SygusGTerm()); - PARSER_STATE->pushSygusDatatypeDef(t, - name, - datatypes, - sorts, - ops, - cnames, - cargs, - allow_const, - unresolved_gterm_sym); - api::Sort unres_t; - if (!PARSER_STATE->isUnresolvedType(name)) - { - // if not unresolved, must be undeclared - Debug("parser-sygus") << "Make unresolved type : " << name - << std::endl; - PARSER_STATE->checkDeclaration(name, CHECK_UNDECLARED, SYM_SORT); - unres_t = PARSER_STATE->mkUnresolvedType(name); - } - else - { - Debug("parser-sygus") << "Get sort : " << name << std::endl; - unres_t = PARSER_STATE->getSort(name); - } - sygus_to_builtin[unres_t] = t; - Debug("parser-sygus") << "--- Read sygus grammar " << name - << " under function " << fun << "..." - << std::endl - << " type to resolve " << unres_t << std::endl - << " builtin type " << t << std::endl; - } - // Note the official spec for NTDef is missing the ( parens ) - // but they are necessary to parse SyGuS examples - LPAREN_TOK(sygusGTerm[sgts.back().back(), fun] { - sgts.back().push_back(CVC4::SygusGTerm()); - }) - + RPAREN_TOK { sgts.back().pop_back(); } RPAREN_TOK) - + RPAREN_TOK - { - unsigned numSTerms = sgts.size(); - Debug("parser-sygus") << "--- Process " << numSTerms << " sygus gterms..." - << std::endl; - for (unsigned i = 0; i < numSTerms; i++) - { - for (unsigned j = 0, size = sgts[i].size(); j < size; j++) - { - api::Sort sub_ret; - PARSER_STATE->processSygusGTerm(sgts[i][j], - i, - datatypes, - sorts, - ops, - cnames, - cargs, - allow_const, - unresolved_gterm_sym, - sygus_vars, - sygus_to_builtin, - sygus_to_builtin_expr, - sub_ret); - } - } - // swap index if necessary - Debug("parser-sygus") << "--- Making sygus datatypes..." << std::endl; - unsigned ndatatypes = datatypes.size(); - for (unsigned i = 0; i < ndatatypes; i++) - { - Debug("parser-sygus") << "..." << datatypes[i].getName() - << " has builtin sort " << sorts[i] << std::endl; - } - api::Term bvl; - if (!sygus_vars.empty()) - { - bvl = MK_TERM(api::BOUND_VAR_LIST, sygus_vars); - } - for (unsigned i = 0; i < ndatatypes; i++) - { - Debug("parser-sygus") << "...make " << datatypes[i].getName() - << " with builtin sort " << sorts[i] << std::endl; - if (sorts[i].isNull()) - { - PARSER_STATE->parseError( - "Internal error : could not infer " - "builtin sort for nested gterm."); - } - datatypes[i].getDatatype().setSygus( - sorts[i].getType(), bvl.getExpr(), allow_const[i], false); - PARSER_STATE->mkSygusDatatype(datatypes[i], - ops[i], - cnames[i], - cargs[i], - unresolved_gterm_sym[i], - sygus_to_builtin); - } - PARSER_STATE->setSygusStartIndex(fun, startIndex, datatypes, sorts, ops); - PARSER_STATE->popScope(); - Debug("parser-sygus") << "--- Make " << ndatatypes - << " mutual datatypes..." << std::endl; - for (unsigned i = 0; i < ndatatypes; i++) - { - Debug("parser-sygus") << " " << i << " : " << datatypes[i].getName() - << std::endl; - } - - std::vector<CVC4::Datatype> dtypes; - dtypes.reserve(ndatatypes); - - for (api::DatatypeDecl i : datatypes) - { - dtypes.push_back(i.getDatatype()); - } - - std::set<Type> tset = - api::sortSetToTypes(PARSER_STATE->getUnresolvedSorts()); - - std::vector<DatatypeType> datatypeTypes = - SOLVER->getExprManager()->mkMutualDatatypeTypes( - dtypes, tset, ExprManager::DATATYPE_FLAG_PLACEHOLDER); - - PARSER_STATE->getUnresolvedSorts().clear(); - - ret = datatypeTypes[0]; - }; - -// SyGuS grammar term. -// -// fun is the name of the synth-fun this grammar term is for. -// This method adds N operators to ops[index], N names to cnames[index] and N -// type argument vectors to cargs[index] (where typically N=1) -// This method may also add new elements pairwise into -// datatypes/sorts/ops/cnames/cargs in the case of non-flat gterms. -sygusGTerm[CVC4::SygusGTerm& sgt, const std::string& fun] -@declarations { - std::string name, name2; - CVC4::api::Kind k; - CVC4::api::Sort t; - std::string sname; - std::vector< CVC4::api::Term > let_vars; - std::string s; - CVC4::api::Term atomTerm; -} - : LPAREN_TOK - //read operator - ( SYGUS_CONSTANT_TOK sortSymbol[t,CHECK_DECLARED] - { sgt.d_gterm_type = SygusGTerm::gterm_constant; - sgt.d_type = t; - Debug("parser-sygus") << "Sygus grammar constant." << std::endl; - } - | SYGUS_VARIABLE_TOK sortSymbol[t,CHECK_DECLARED] - { sgt.d_gterm_type = SygusGTerm::gterm_variable; - sgt.d_type = t; - Debug("parser-sygus") << "Sygus grammar variable." << std::endl; - } - | SYGUS_LOCAL_VARIABLE_TOK sortSymbol[t,CHECK_DECLARED] - { sgt.d_gterm_type = SygusGTerm::gterm_local_variable; - sgt.d_type = t; - Debug("parser-sygus") << "Sygus grammar local variable...ignore." - << std::endl; - } - | SYGUS_INPUT_VARIABLE_TOK sortSymbol[t,CHECK_DECLARED] - { sgt.d_gterm_type = SygusGTerm::gterm_input_variable; - sgt.d_type = t; - Debug("parser-sygus") << "Sygus grammar (input) variable." - << std::endl; - } - | symbol[name,CHECK_NONE,SYM_VARIABLE] { - bool isBuiltinOperator = PARSER_STATE->isOperatorEnabled(name); - if(isBuiltinOperator) { - Debug("parser-sygus") << "Sygus grammar " << fun << " : builtin op : " - << name << std::endl; - k = PARSER_STATE->getOperatorKind(name); - sgt.d_name = api::kindToString(k); - sgt.d_gterm_type = SygusGTerm::gterm_op; - sgt.d_op.d_kind = k; - }else{ - // what is this sygus term trying to accomplish here, if the - // symbol isn't yet declared?! probably the following line will - // fail, but we need an operator to continue here.. - Debug("parser-sygus") - << "Sygus grammar " << fun << " : op (declare=" - << PARSER_STATE->isDeclared(name) << ") : " << name - << std::endl; - if (!PARSER_STATE->isDeclared(name)) - { - PARSER_STATE->parseError("Functions in sygus grammars must be " - "defined."); - } - sgt.d_name = name; - sgt.d_gterm_type = SygusGTerm::gterm_op; - sgt.d_op.d_expr = PARSER_STATE->getVariable(name) ; - } - } - ) - //read arguments - { Debug("parser-sygus") << "Read arguments under " << sgt.d_name - << std::endl; - sgt.addChild(); - } - ( sygusGTerm[sgt.d_children.back(), fun] - { Debug("parser-sygus") << "Finished read argument #" - << sgt.d_children.size() << "..." << std::endl; - sgt.addChild(); - } - )* - RPAREN_TOK { - //pop last child index - sgt.d_children.pop_back(); - } - | termAtomic[atomTerm] - { - Debug("parser-sygus") << "Sygus grammar " << fun << " : atomic " - << "expression " << atomTerm << std::endl; - std::stringstream ss; - ss << atomTerm; - sgt.d_op.d_expr = atomTerm.getExpr(); - sgt.d_name = ss.str(); - sgt.d_gterm_type = SygusGTerm::gterm_op; - } - | symbol[name,CHECK_NONE,SYM_VARIABLE] - { - if( name[0] == '-' ){ //hack for unary minus - Debug("parser-sygus") << "Sygus grammar " << fun - << " : unary minus integer literal " << name - << std::endl; - sgt.d_op.d_expr = SOLVER->mkReal(name); - sgt.d_name = name; - sgt.d_gterm_type = SygusGTerm::gterm_op; - }else if( PARSER_STATE->isDeclared(name,SYM_VARIABLE) ){ - Debug("parser-sygus") << "Sygus grammar " << fun << " : symbol " - << name << std::endl; - sgt.d_op.d_expr = PARSER_STATE->getExpressionForName(name); - sgt.d_name = name; - sgt.d_gterm_type = SygusGTerm::gterm_op; - }else{ - if( PARSER_STATE->isDeclared(name, SYM_SORT) ){ - Debug("parser-sygus") << "Sygus grammar " << fun - << " : nested sort " << name << std::endl; - sgt.d_type = PARSER_STATE->getSort(name); - sgt.d_gterm_type = SygusGTerm::gterm_nested_sort; - }else{ - Debug("parser-sygus") << "Sygus grammar " << fun - << " : unresolved symbol " << name - << std::endl; - sgt.d_gterm_type = SygusGTerm::gterm_unresolved; - sgt.d_name = name; - } - } - } - ; - /** Reads a sygus grammar in the sygus version 2 format * @@ -1204,7 +883,7 @@ smt25Command[std::unique_ptr<CVC4::Command>* cmd] expr = PARSER_STATE->mkHoApply( expr, flattenVars ); } cmd->reset(new DefineFunctionRecCommand( - func.getExpr(), api::termVectorToExprs(bvs), expr.getExpr())); + SOLVER, func, bvs, expr, PARSER_STATE->getGlobalDeclarations())); } | DEFINE_FUNS_REC_TOK { PARSER_STATE->checkThatLogicIsSet();} @@ -1267,15 +946,12 @@ smt25Command[std::unique_ptr<CVC4::Command>* cmd] "Number of functions defined does not match number listed in " "define-funs-rec")); } - std::vector<std::vector<Expr>> eformals; - for (unsigned i=0, fsize = formals.size(); i<fsize; i++) - { - eformals.push_back(api::termVectorToExprs(formals[i])); - } cmd->reset( - new DefineFunctionRecCommand(api::termVectorToExprs(funcs), - eformals, - api::termVectorToExprs(func_defs))); + new DefineFunctionRecCommand(SOLVER, + funcs, + formals, + func_defs, + PARSER_STATE->getGlobalDeclarations())); } ; @@ -1365,14 +1041,21 @@ extendedCommand[std::unique_ptr<CVC4::Command>* cmd] { cmd->reset(seq.release()); } | DEFINE_TOK { PARSER_STATE->checkThatLogicIsSet(); } - ( symbol[name,CHECK_UNDECLARED,SYM_VARIABLE] + ( // (define f t) + symbol[name,CHECK_UNDECLARED,SYM_VARIABLE] { PARSER_STATE->checkUserSymbol(name); } term[e,e2] - { api::Term func = PARSER_STATE->bindVar(name, e.getSort(), + { + api::Term func = PARSER_STATE->bindVar(name, e.getSort(), ExprManager::VAR_FLAG_DEFINED); - cmd->reset(new DefineFunctionCommand(name, func.getExpr(), e.getExpr())); + cmd->reset( + new DefineFunctionCommand(name, + func.getExpr(), + e.getExpr(), + PARSER_STATE->getGlobalDeclarations())); } - | LPAREN_TOK + | // (define (f (v U) ...) t) + LPAREN_TOK symbol[name,CHECK_UNDECLARED,SYM_VARIABLE] { PARSER_STATE->checkUserSymbol(name); } sortedVarList[sortedVarNames] RPAREN_TOK @@ -1382,7 +1065,8 @@ extendedCommand[std::unique_ptr<CVC4::Command>* cmd] terms = PARSER_STATE->bindBoundVars(sortedVarNames); } term[e,e2] - { PARSER_STATE->popScope(); + { + PARSER_STATE->popScope(); // declare the name down here (while parsing term, signature // must not be extended with the name itself; no recursion // permitted) @@ -1398,11 +1082,16 @@ extendedCommand[std::unique_ptr<CVC4::Command>* cmd] } api::Term func = PARSER_STATE->bindVar(name, tt, ExprManager::VAR_FLAG_DEFINED); - cmd->reset(new DefineFunctionCommand( - name, func.getExpr(), api::termVectorToExprs(terms), e.getExpr())); + cmd->reset( + new DefineFunctionCommand(name, + func.getExpr(), + api::termVectorToExprs(terms), + e.getExpr(), + PARSER_STATE->getGlobalDeclarations())); } ) - | DEFINE_CONST_TOK { PARSER_STATE->checkThatLogicIsSet(); } + | // (define-const x U t) + DEFINE_CONST_TOK { PARSER_STATE->checkThatLogicIsSet(); } symbol[name,CHECK_UNDECLARED,SYM_VARIABLE] { PARSER_STATE->checkUserSymbol(name); } sortSymbol[t,CHECK_DECLARED] @@ -1412,14 +1101,19 @@ extendedCommand[std::unique_ptr<CVC4::Command>* cmd] terms = PARSER_STATE->bindBoundVars(sortedVarNames); } term[e, e2] - { PARSER_STATE->popScope(); + { + PARSER_STATE->popScope(); // declare the name down here (while parsing term, signature // must not be extended with the name itself; no recursion // permitted) api::Term func = PARSER_STATE->bindVar(name, t, ExprManager::VAR_FLAG_DEFINED); - cmd->reset(new DefineFunctionCommand( - name, func.getExpr(), api::termVectorToExprs(terms), e.getExpr())); + cmd->reset( + new DefineFunctionCommand(name, + func.getExpr(), + api::termVectorToExprs(terms), + e.getExpr(), + PARSER_STATE->getGlobalDeclarations())); } | SIMPLIFY_TOK { PARSER_STATE->checkThatLogicIsSet(); } @@ -1442,6 +1136,17 @@ extendedCommand[std::unique_ptr<CVC4::Command>* cmd] { cmd->reset(new GetAbductCommand(name,e.getExpr(), t.getType())); } + | GET_INTERPOL_TOK { + PARSER_STATE->checkThatLogicIsSet(); + } + symbol[name,CHECK_UNDECLARED,SYM_VARIABLE] + term[e,e2] + ( + sygusGrammar[t, terms, name] + )? + { + cmd->reset(new GetInterpolCommand(SOLVER, name, e, t.getType())); + } | DECLARE_HEAP LPAREN_TOK sortSymbol[t, CHECK_DECLARED] sortSymbol[t, CHECK_DECLARED] @@ -1530,7 +1235,10 @@ datatypesDefCommand[bool isCo, std::unique_ptr<CVC4::Command>* cmd] /** * Read a list of datatype definitions for datatypes with names dnames and * parametric arities arities. A negative value in arities indicates that the - * arity for the corresponding datatype has not been fixed. + * arity for the corresponding datatype has not been fixed: notice that we do + * not know the arity of datatypes in the declare-datatype command prior to + * parsing their body, whereas the arity of datatypes in declare-datatypes is + * given in the preamble of that command and thus is known prior to this call. */ datatypesDef[bool isCo, const std::vector<std::string>& dnames, @@ -1541,7 +1249,26 @@ datatypesDef[bool isCo, std::string name; std::vector<api::Sort> params; } - : { PARSER_STATE->pushScope(true); } + : { PARSER_STATE->pushScope(true); + // Declare the datatypes that are currently being defined as unresolved + // types. If we do not know the arity of the datatype yet, we wait to + // define it until parsing the preamble of its body, which may optionally + // involve `par`. This is limited to the case of single datatypes defined + // via declare-datatype, and hence no datatype body is parsed without + // having all types declared. This ensures we can parse datatypes with + // nested recursion, e.g. datatypes D having a subfield type + // (Array Int D). + for (unsigned i=0, dsize=dnames.size(); i<dsize; i++) + { + if( arities[i]<0 ) + { + // do not know the arity yet + continue; + } + unsigned arity = static_cast<unsigned>(arities[i]); + PARSER_STATE->mkUnresolvedType(dnames[i], arity); + } + } ( LPAREN_TOK { params.clear(); Debug("parser-dt") << "Processing datatype #" << dts.size() << std::endl; @@ -1559,6 +1286,11 @@ datatypesDef[bool isCo, if( arities[dts.size()]>=0 && static_cast<int>(params.size())!=arities[dts.size()] ){ PARSER_STATE->parseError("Wrong number of parameters for datatype."); } + if (arities[dts.size()]<0) + { + // now declare it as an unresolved type + PARSER_STATE->mkUnresolvedType(dnames[dts.size()], params.size()); + } Debug("parser-dt") << params.size() << " parameters for " << dnames[dts.size()] << std::endl; dts.push_back(SOLVER->mkDatatypeDecl(dnames[dts.size()], params, isCo)); } @@ -1569,6 +1301,11 @@ datatypesDef[bool isCo, if( arities[dts.size()]>0 ){ PARSER_STATE->parseError("No parameters given for datatype."); } + else if (arities[dts.size()]<0) + { + // now declare it as an unresolved type + PARSER_STATE->mkUnresolvedType(dnames[dts.size()], 0); + } Debug("parser-dt") << params.size() << " parameters for " << dnames[dts.size()] << std::endl; dts.push_back(SOLVER->mkDatatypeDecl(dnames[dts.size()], params, @@ -1692,7 +1429,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 { @@ -1723,7 +1466,7 @@ termNonVariable[CVC4::api::Term& expr, CVC4::api::Term& expr2] expr = PARSER_STATE->applyParseOp(p, args); } | /* a let or sygus let binding */ - LPAREN_TOK ( + LPAREN_TOK LET_TOK LPAREN_TOK { PARSER_STATE->pushScope(true); } ( LPAREN_TOK symbol[name,CHECK_NONE,SYM_VARIABLE] @@ -1739,24 +1482,7 @@ termNonVariable[CVC4::api::Term& expr, CVC4::api::Term& expr2] } else { names.insert(name); } - binders.push_back(std::make_pair(name, expr)); } )+ | - SYGUS_LET_TOK LPAREN_TOK - { PARSER_STATE->pushScope(true); } - ( LPAREN_TOK symbol[name,CHECK_NONE,SYM_VARIABLE] - sortSymbol[type,CHECK_DECLARED] - term[expr, f2] - RPAREN_TOK - // this is a parallel let, so we have to save up all the contributions - // of the let and define them only later on - { if(names.count(name) == 1) { - std::stringstream ss; - ss << "warning: symbol `" << name << "' bound multiple times by let;" - << " the last binding will be used, shadowing earlier ones"; - PARSER_STATE->warning(ss.str()); - } else { - names.insert(name); - } - binders.push_back(std::make_pair(name, expr)); } )+ ) + binders.push_back(std::make_pair(name, expr)); } )+ { // now implement these bindings for (const std::pair<std::string, api::Term>& binder : binders) { @@ -1791,8 +1517,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 +1642,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; } ; @@ -1982,7 +1710,7 @@ qualIdentifier[CVC4::ParseOp& p] | LPAREN_TOK AS_TOK ( CONST_TOK sortSymbol[type, CHECK_DECLARED] { - p.d_kind = api::STORE_ALL; + p.d_kind = api::CONST_ARRAY; PARSER_STATE->parseOpApplyTypeAscription(p, type); } | identifier[p] @@ -2177,7 +1905,7 @@ attribute[CVC4::api::Term& expr, CVC4::api::Term& retExpr, std::string& attr] std::string name = sexpr.getValue(); // bind name to expr with define-fun Command* c = new DefineNamedFunctionCommand( - name, func.getExpr(), std::vector<Expr>(), expr.getExpr()); + name, func.getExpr(), std::vector<Expr>(), expr.getExpr(), PARSER_STATE->getGlobalDeclarations()); c->setMuted(true); PARSER_STATE->preemptCommand(c); } @@ -2339,8 +2067,9 @@ sortSymbol[CVC4::api::Sort& t, CVC4::parser::DeclarationCheck check] | LPAREN_TOK (INDEX_TOK {indexed = true;} | {indexed = false;}) symbol[name,CHECK_NONE,SYM_SORT] ( nonemptyNumeralList[numerals] - { // allow sygus inputs to elide the `_' - if( !indexed && !PARSER_STATE->sygus_v1() ) { + { + if (!indexed) + { std::stringstream ss; ss << "SMT-LIB requires use of an indexed sort here, e.g. (_ " << name << " ...)"; @@ -2513,7 +2242,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 @@ -2555,8 +2285,7 @@ GET_UNSAT_CORE_TOK : 'get-unsat-core'; EXIT_TOK : 'exit'; RESET_TOK : { PARSER_STATE->v2_5() }? 'reset'; RESET_ASSERTIONS_TOK : 'reset-assertions'; -LET_TOK : { !PARSER_STATE->sygus_v1() }? 'let'; -SYGUS_LET_TOK : { PARSER_STATE->sygus_v1() }? 'let'; +LET_TOK : 'let'; ATTRIBUTE_TOK : '!'; LPAREN_TOK : '('; RPAREN_TOK : ')'; @@ -2597,23 +2326,19 @@ INCLUDE_TOK : 'include'; GET_QE_TOK : 'get-qe'; GET_QE_DISJUNCT_TOK : 'get-qe-disjunct'; GET_ABDUCT_TOK : 'get-abduct'; +GET_INTERPOL_TOK : 'get-interpol'; DECLARE_HEAP : 'declare-heap'; // SyGuS commands -SYNTH_FUN_V1_TOK : { PARSER_STATE->sygus_v1() }?'synth-fun'; -SYNTH_FUN_TOK : { PARSER_STATE->sygus() && !PARSER_STATE->sygus_v1() }?'synth-fun'; -SYNTH_INV_V1_TOK : { PARSER_STATE->sygus_v1()}?'synth-inv'; -SYNTH_INV_TOK : { PARSER_STATE->sygus() && !PARSER_STATE->sygus_v1()}?'synth-inv'; +SYNTH_FUN_TOK : { PARSER_STATE->sygus() }?'synth-fun'; +SYNTH_INV_TOK : { PARSER_STATE->sygus()}?'synth-inv'; CHECK_SYNTH_TOK : { PARSER_STATE->sygus()}?'check-synth'; DECLARE_VAR_TOK : { PARSER_STATE->sygus()}?'declare-var'; -DECLARE_PRIMED_VAR_TOK : { PARSER_STATE->sygus_v1() }?'declare-primed-var'; CONSTRAINT_TOK : { PARSER_STATE->sygus()}?'constraint'; INV_CONSTRAINT_TOK : { PARSER_STATE->sygus()}?'inv-constraint'; SET_OPTIONS_TOK : { PARSER_STATE->sygus() }? 'set-options'; SYGUS_CONSTANT_TOK : { PARSER_STATE->sygus() }? 'Constant'; SYGUS_VARIABLE_TOK : { PARSER_STATE->sygus() }? 'Variable'; -SYGUS_INPUT_VARIABLE_TOK : { PARSER_STATE->sygus_v1() }? 'InputVariable'; -SYGUS_LOCAL_VARIABLE_TOK : { PARSER_STATE->sygus_v1() }? 'LocalVariable'; // attributes ATTRIBUTE_PATTERN_TOK : ':pattern'; @@ -2630,8 +2355,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..68b1945fc 100644 --- a/src/parser/smt2/smt2.cpp +++ b/src/parser/smt2/smt2.cpp @@ -2,9 +2,9 @@ /*! \file smt2.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Kshitij Bansal, Morgan Deters + ** Andrew Reynolds, Andres Noetzli, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -156,6 +156,8 @@ void Smt2::addStringOperators() { addOperator(api::STRING_CHARAT, "str.at"); addOperator(api::STRING_INDEXOF, "str.indexof"); addOperator(api::STRING_REPLACE, "str.replace"); + addOperator(api::STRING_REPLACE_RE, "str.replace_re"); + addOperator(api::STRING_REPLACE_RE_ALL, "str.replace_re_all"); if (!strictModeEnabled()) { addOperator(api::STRING_TOLOWER, "str.tolower"); @@ -315,6 +317,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; } @@ -560,16 +568,6 @@ Command* Smt2::setLogic(std::string name, bool fromCommand) } } - if (sygus_v1()) - { - // non-smt2-standard sygus logic names go here (http://sygus.seas.upenn.edu/files/sygus.pdf Section 3.2) - if(name == "Arrays") { - name = "A"; - }else if(name == "Reals") { - name = "LRA"; - } - } - d_logicSet = true; d_logic = name; @@ -634,6 +632,7 @@ Command* Smt2::setLogic(std::string name, bool fromCommand) if(d_logic.isTheoryEnabled(theory::THEORY_ARRAYS)) { addOperator(api::SELECT, "select"); addOperator(api::STORE, "store"); + addOperator(api::EQ_RANGE, "eqrange"); } if(d_logic.isTheoryEnabled(theory::THEORY_BV)) { @@ -743,13 +742,7 @@ Command* Smt2::setLogic(std::string name, bool fromCommand) bool Smt2::sygus() const { InputLanguage ilang = getLanguage(); - return ilang == language::input::LANG_SYGUS_V1 - || ilang == language::input::LANG_SYGUS_V2; -} - -bool Smt2::sygus_v1() const -{ - return getLanguage() == language::input::LANG_SYGUS_V1; + return ilang == language::input::LANG_SYGUS_V2; } bool Smt2::sygus_v2() const @@ -890,538 +883,6 @@ api::Term Smt2::mkAbstractValue(const std::string& name) return d_solver->mkAbstractValue(name.substr(1)); } -void Smt2::mkSygusConstantsForType(const api::Sort& type, - std::vector<api::Term>& ops) -{ - if( type.isInteger() ){ - ops.push_back(d_solver->mkReal(0)); - ops.push_back(d_solver->mkReal(1)); - }else if( type.isBitVector() ){ - uint32_t sz = type.getBVSize(); - ops.push_back(d_solver->mkBitVector(sz, 0)); - ops.push_back(d_solver->mkBitVector(sz, 1)); - }else if( type.isBoolean() ){ - ops.push_back(d_solver->mkTrue()); - ops.push_back(d_solver->mkFalse()); - } - //TODO : others? -} - -// This method adds N operators to ops[index], N names to cnames[index] and N type argument vectors to cargs[index] (where typically N=1) -// This method may also add new elements pairwise into datatypes/sorts/ops/cnames/cargs in the case of non-flat gterms. -void Smt2::processSygusGTerm( - CVC4::SygusGTerm& sgt, - int index, - std::vector<api::DatatypeDecl>& datatypes, - std::vector<api::Sort>& sorts, - std::vector<std::vector<ParseOp>>& ops, - std::vector<std::vector<std::string>>& cnames, - std::vector<std::vector<std::vector<api::Sort>>>& cargs, - std::vector<bool>& allow_const, - std::vector<std::vector<std::string>>& unresolved_gterm_sym, - const std::vector<api::Term>& sygus_vars, - std::map<api::Sort, api::Sort>& sygus_to_builtin, - std::map<api::Sort, api::Term>& sygus_to_builtin_expr, - api::Sort& ret, - bool isNested) -{ - if (sgt.d_gterm_type == SygusGTerm::gterm_op) - { - Debug("parser-sygus") << "Add " << sgt.d_op << " to datatype " - << index << std::endl; - api::Kind oldKind; - api::Kind newKind = api::UNDEFINED_KIND; - //convert to UMINUS if one child of MINUS - if (sgt.d_children.size() == 1 && sgt.d_op.d_kind == api::MINUS) - { - oldKind = api::MINUS; - newKind = api::UMINUS; - } - if (newKind != api::UNDEFINED_KIND) - { - Debug("parser-sygus") - << "Replace " << sgt.d_op.d_kind << " with " << newKind << std::endl; - sgt.d_op.d_kind = newKind; - std::string oldName = api::kindToString(oldKind); - std::string newName = api::kindToString(newKind); - size_t pos = 0; - if((pos = sgt.d_name.find(oldName, pos)) != std::string::npos){ - sgt.d_name.replace(pos, oldName.length(), newName); - } - } - ops[index].push_back(sgt.d_op); - cnames[index].push_back( sgt.d_name ); - cargs[index].push_back(std::vector<api::Sort>()); - for( unsigned i=0; i<sgt.d_children.size(); i++ ){ - std::stringstream ss; - ss << datatypes[index].getName() << "_" << ops[index].size() << "_arg_" << i; - std::string sub_dname = ss.str(); - //add datatype for child - api::Sort null_type; - pushSygusDatatypeDef( null_type, sub_dname, datatypes, sorts, ops, cnames, cargs, allow_const, unresolved_gterm_sym ); - int sub_dt_index = datatypes.size()-1; - //process child - api::Sort sub_ret; - processSygusGTerm( sgt.d_children[i], sub_dt_index, datatypes, sorts, ops, cnames, cargs, allow_const, unresolved_gterm_sym, - sygus_vars, sygus_to_builtin, sygus_to_builtin_expr, sub_ret, true ); - //process the nested gterm (either pop the last datatype, or flatten the argument) - api::Sort tt = processSygusNestedGTerm(sub_dt_index, - sub_dname, - datatypes, - sorts, - ops, - cnames, - cargs, - allow_const, - unresolved_gterm_sym, - sygus_to_builtin, - sygus_to_builtin_expr, - sub_ret); - cargs[index].back().push_back(tt); - } - } - else if (sgt.d_gterm_type == SygusGTerm::gterm_constant) - { - if( sgt.getNumChildren()!=0 ){ - parseError("Bad syntax for Sygus Constant."); - } - std::vector<api::Term> consts; - mkSygusConstantsForType( sgt.d_type, consts ); - Debug("parser-sygus") << "...made " << consts.size() << " constants." << std::endl; - for( unsigned i=0; i<consts.size(); i++ ){ - std::stringstream ss; - ss << consts[i]; - Debug("parser-sygus") << "...add for constant " << ss.str() << std::endl; - ParseOp constOp; - constOp.d_expr = consts[i]; - ops[index].push_back(constOp); - cnames[index].push_back( ss.str() ); - cargs[index].push_back(std::vector<api::Sort>()); - } - allow_const[index] = true; - } - else if (sgt.d_gterm_type == SygusGTerm::gterm_variable - || sgt.d_gterm_type == SygusGTerm::gterm_input_variable) - { - if( sgt.getNumChildren()!=0 ){ - parseError("Bad syntax for Sygus Variable."); - } - Debug("parser-sygus") << "...process " << sygus_vars.size() << " variables." << std::endl; - for( unsigned i=0; i<sygus_vars.size(); i++ ){ - if (sygus_vars[i].getSort() == sgt.d_type) - { - std::stringstream ss; - ss << sygus_vars[i]; - Debug("parser-sygus") << "...add for variable " << ss.str() << std::endl; - ParseOp varOp; - varOp.d_expr = sygus_vars[i]; - ops[index].push_back(varOp); - cnames[index].push_back( ss.str() ); - cargs[index].push_back(std::vector<api::Sort>()); - } - } - } - else if (sgt.d_gterm_type == SygusGTerm::gterm_nested_sort) - { - ret = sgt.d_type; - } - else if (sgt.d_gterm_type == SygusGTerm::gterm_unresolved) - { - if( isNested ){ - if( isUnresolvedType(sgt.d_name) ){ - ret = getSort(sgt.d_name); - }else{ - //nested, unresolved symbol...fail - std::stringstream ss; - ss << "Cannot handle nested unresolved symbol " << sgt.d_name << std::endl; - parseError(ss.str()); - } - }else{ - //will resolve when adding constructors - unresolved_gterm_sym[index].push_back(sgt.d_name); - } - } - else if (sgt.d_gterm_type == SygusGTerm::gterm_ignore) - { - // do nothing - } -} - -bool Smt2::pushSygusDatatypeDef( - api::Sort t, - std::string& dname, - std::vector<api::DatatypeDecl>& datatypes, - std::vector<api::Sort>& sorts, - std::vector<std::vector<ParseOp>>& ops, - std::vector<std::vector<std::string>>& cnames, - std::vector<std::vector<std::vector<api::Sort>>>& cargs, - std::vector<bool>& allow_const, - std::vector<std::vector<std::string>>& unresolved_gterm_sym) -{ - sorts.push_back(t); - datatypes.push_back(d_solver->mkDatatypeDecl(dname)); - ops.push_back(std::vector<ParseOp>()); - cnames.push_back(std::vector<std::string>()); - cargs.push_back(std::vector<std::vector<api::Sort>>()); - allow_const.push_back(false); - unresolved_gterm_sym.push_back(std::vector< std::string >()); - return true; -} - -bool Smt2::popSygusDatatypeDef( - std::vector<api::DatatypeDecl>& datatypes, - std::vector<api::Sort>& sorts, - std::vector<std::vector<ParseOp>>& ops, - std::vector<std::vector<std::string>>& cnames, - std::vector<std::vector<std::vector<api::Sort>>>& cargs, - std::vector<bool>& allow_const, - std::vector<std::vector<std::string>>& unresolved_gterm_sym) -{ - sorts.pop_back(); - datatypes.pop_back(); - ops.pop_back(); - cnames.pop_back(); - cargs.pop_back(); - allow_const.pop_back(); - unresolved_gterm_sym.pop_back(); - return true; -} - -api::Sort Smt2::processSygusNestedGTerm( - int sub_dt_index, - std::string& sub_dname, - std::vector<api::DatatypeDecl>& datatypes, - std::vector<api::Sort>& sorts, - std::vector<std::vector<ParseOp>>& ops, - std::vector<std::vector<std::string>>& cnames, - std::vector<std::vector<std::vector<api::Sort>>>& cargs, - std::vector<bool>& allow_const, - std::vector<std::vector<std::string>>& unresolved_gterm_sym, - std::map<api::Sort, api::Sort>& sygus_to_builtin, - std::map<api::Sort, CVC4::api::Term>& sygus_to_builtin_expr, - api::Sort sub_ret) -{ - api::Sort t = sub_ret; - Debug("parser-sygus") << "Argument is "; - if( t.isNull() ){ - //then, it is the datatype we constructed, which should have a single constructor - t = mkUnresolvedType(sub_dname); - Debug("parser-sygus") << "inline flattening of (auxiliary, local) datatype " << t << std::endl; - Debug("parser-sygus") << ": to compute type, construct ground term witnessing the grammar, #cons=" << cargs[sub_dt_index].size() << std::endl; - if( cargs[sub_dt_index].empty() ){ - parseError(std::string("Internal error : datatype for nested gterm does not have a constructor.")); - } - ParseOp op = ops[sub_dt_index][0]; - api::Sort curr_t; - if (!op.d_expr.isNull() - && (op.d_expr.isConst() || cargs[sub_dt_index][0].empty())) - { - api::Term sop = op.d_expr; - curr_t = sop.getSort(); - Debug("parser-sygus") - << ": it is constant/0-arg cons " << sop << " with type " - << sop.getSort() << ", debug=" << sop.isConst() << " " - << cargs[sub_dt_index][0].size() << std::endl; - // only cache if it is a singleton datatype (has unique expr) - if (ops[sub_dt_index].size() == 1) - { - sygus_to_builtin_expr[t] = sop; - // store that term sop has dedicated sygus type t - if (d_sygus_bound_var_type.find(sop) == d_sygus_bound_var_type.end()) - { - d_sygus_bound_var_type[sop] = t; - } - } - } - else - { - std::vector<api::Term> children; - for( unsigned i=0; i<cargs[sub_dt_index][0].size(); i++ ){ - std::map<api::Sort, CVC4::api::Term>::iterator it = - sygus_to_builtin_expr.find(cargs[sub_dt_index][0][i]); - if( it==sygus_to_builtin_expr.end() ){ - if( sygus_to_builtin.find( cargs[sub_dt_index][0][i] )==sygus_to_builtin.end() ){ - std::stringstream ss; - ss << "Missing builtin type for type " << cargs[sub_dt_index][0][i] << "!" << std::endl; - ss << "Builtin types are currently : " << std::endl; - for (std::map<api::Sort, api::Sort>::iterator itb = - sygus_to_builtin.begin(); - itb != sygus_to_builtin.end(); - ++itb) - { - ss << " " << itb->first << " -> " << itb->second << std::endl; - } - parseError(ss.str()); - } - api::Sort bt = sygus_to_builtin[cargs[sub_dt_index][0][i]]; - Debug("parser-sygus") << ": child " << i << " introduce type elem for " << cargs[sub_dt_index][0][i] << " " << bt << std::endl; - std::stringstream ss; - ss << t << "_x_" << i; - api::Term bv = bindBoundVar(ss.str(), bt); - children.push_back( bv ); - d_sygus_bound_var_type[bv] = cargs[sub_dt_index][0][i]; - }else{ - Debug("parser-sygus") << ": child " << i << " existing sygus to builtin expr : " << it->second << std::endl; - children.push_back( it->second ); - } - } - api::Term e = applyParseOp(op, children); - Debug("parser-sygus") << ": constructed " << e << ", which has type " - << e.getSort() << std::endl; - curr_t = e.getSort(); - sygus_to_builtin_expr[t] = e; - } - sorts[sub_dt_index] = curr_t; - sygus_to_builtin[t] = curr_t; - }else{ - Debug("parser-sygus") << "simple argument " << t << std::endl; - Debug("parser-sygus") << "...removing " << datatypes.back().getName() << std::endl; - //otherwise, datatype was unecessary - //pop argument datatype definition - popSygusDatatypeDef( datatypes, sorts, ops, cnames, cargs, allow_const, unresolved_gterm_sym ); - } - return t; -} - -void Smt2::setSygusStartIndex(const std::string& fun, - int startIndex, - std::vector<api::DatatypeDecl>& datatypes, - std::vector<api::Sort>& sorts, - std::vector<std::vector<ParseOp>>& ops) -{ - if( startIndex>0 ){ - api::DatatypeDecl tmp_dt = datatypes[0]; - api::Sort tmp_sort = sorts[0]; - std::vector<ParseOp> tmp_ops; - tmp_ops.insert( tmp_ops.end(), ops[0].begin(), ops[0].end() ); - datatypes[0] = datatypes[startIndex]; - sorts[0] = sorts[startIndex]; - ops[0].clear(); - ops[0].insert( ops[0].end(), ops[startIndex].begin(), ops[startIndex].end() ); - datatypes[startIndex] = tmp_dt; - sorts[startIndex] = tmp_sort; - ops[startIndex].clear(); - ops[startIndex].insert( ops[startIndex].begin(), tmp_ops.begin(), tmp_ops.end() ); - }else if( startIndex<0 ){ - std::stringstream ss; - ss << "warning: no symbol named Start for synth-fun " << fun << std::endl; - warning(ss.str()); - } -} - -void Smt2::mkSygusDatatype(api::DatatypeDecl& dt, - std::vector<ParseOp>& ops, - std::vector<std::string>& cnames, - std::vector<std::vector<api::Sort>>& cargs, - std::vector<std::string>& unresolved_gterm_sym, - std::map<api::Sort, api::Sort>& sygus_to_builtin) -{ - Debug("parser-sygus") << "Making sygus datatype " << dt.getName() << std::endl; - Debug("parser-sygus") << " add constructors..." << std::endl; - - Debug("parser-sygus") << "SMT2 sygus parser : Making constructors for sygus datatype " << dt.getName() << std::endl; - Debug("parser-sygus") << " add constructors..." << std::endl; - // size of cnames changes, this loop must check size - for (unsigned i = 0; i < cnames.size(); i++) - { - bool is_dup = false; - bool is_dup_op = false; - for (unsigned j = 0; j < i; j++) - { - if( ops[i]==ops[j] ){ - is_dup_op = true; - if( cargs[i].size()==cargs[j].size() ){ - is_dup = true; - for( unsigned k=0; k<cargs[i].size(); k++ ){ - if( cargs[i][k]!=cargs[j][k] ){ - is_dup = false; - break; - } - } - } - if( is_dup ){ - break; - } - } - } - Debug("parser-sygus") << "SYGUS CONS " << i << " : "; - if( is_dup ){ - Debug("parser-sygus") << "--> Duplicate gterm : " << ops[i] << std::endl; - ops.erase( ops.begin() + i, ops.begin() + i + 1 ); - cnames.erase( cnames.begin() + i, cnames.begin() + i + 1 ); - cargs.erase( cargs.begin() + i, cargs.begin() + i + 1 ); - i--; - } - else - { - std::shared_ptr<SygusPrintCallback> spc; - if (is_dup_op) - { - Debug("parser-sygus") << "--> Duplicate gterm operator : " << ops[i] - << std::endl; - // make into define-fun - std::vector<api::Sort> ltypes; - for (unsigned j = 0, size = cargs[i].size(); j < size; j++) - { - ltypes.push_back(sygus_to_builtin[cargs[i][j]]); - } - std::vector<api::Term> largs; - api::Term lbvl = makeSygusBoundVarList(dt, i, ltypes, largs); - - // make the let_body - std::vector<api::Term> largsApply = largs; - api::Term body = applyParseOp(ops[i], largsApply); - // replace by lambda - ParseOp pLam; - pLam.d_expr = d_solver->mkTerm(api::LAMBDA, lbvl, body); - ops[i] = pLam; - Debug("parser-sygus") << " ...replace op : " << ops[i] << std::endl; - // callback prints as the expression - spc = std::make_shared<printer::SygusExprPrintCallback>( - body.getExpr(), api::termVectorToExprs(largs)); - } - else - { - api::Term sop = ops[i].d_expr; - if (!sop.isNull() && sop.getSort().isBitVector() && sop.isConst()) - { - Debug("parser-sygus") << "--> Bit-vector constant " << sop << " (" - << cnames[i] << ")" << std::endl; - // Since there are multiple output formats for bit-vectors and - // we are required by sygus standards to print in the exact input - // format given by the user, we use a print callback to custom print - // the given name. - spc = std::make_shared<printer::SygusNamedPrintCallback>(cnames[i]); - } - else if (!sop.isNull() && sop.getKind() == api::CONSTANT) - { - Debug("parser-sygus") << "--> Defined function " << ops[i] - << std::endl; - // turn f into (lammbda (x) (f x)) - // in a degenerate case, ops[i] may be a defined constant, - // in which case we do not replace by a lambda. - if (sop.getSort().isFunction()) - { - std::vector<api::Sort> ftypes = - sop.getSort().getFunctionDomainSorts(); - std::vector<api::Term> largs; - api::Term lbvl = makeSygusBoundVarList(dt, i, ftypes, largs); - largs.insert(largs.begin(), sop); - api::Term body = d_solver->mkTerm(api::APPLY_UF, largs); - ops[i].d_expr = d_solver->mkTerm(api::LAMBDA, lbvl, body); - Debug("parser-sygus") << " ...replace op : " << ops[i] - << std::endl; - } - else - { - Debug("parser-sygus") << " ...replace op : " << ops[i] - << std::endl; - } - // keep a callback to say it should be printed with the defined name - spc = std::make_shared<printer::SygusNamedPrintCallback>(cnames[i]); - } - else - { - Debug("parser-sygus") << "--> Default case " << ops[i] << std::endl; - } - } - // must rename to avoid duplication - std::stringstream ss; - ss << dt.getName() << "_" << i << "_" << cnames[i]; - cnames[i] = ss.str(); - Debug("parser-sygus") << " construct the datatype " << cnames[i] << "..." - << std::endl; - - // Add the sygus constructor, either using the expression operator of - // ops[i], or the kind. - if (!ops[i].d_expr.isNull()) - { - dt.getDatatype().addSygusConstructor(ops[i].d_expr.getExpr(), - cnames[i], - api::sortVectorToTypes(cargs[i]), - spc); - } - else if (ops[i].d_kind != api::NULL_EXPR) - { - dt.getDatatype().addSygusConstructor(extToIntKind(ops[i].d_kind), - cnames[i], - api::sortVectorToTypes(cargs[i]), - spc); - } - else - { - std::stringstream ess; - ess << "unexpected parse operator for sygus constructor" << ops[i]; - parseError(ess.str()); - } - Debug("parser-sygus") << " finished constructing the datatype" - << std::endl; - } - } - - Debug("parser-sygus") << " add constructors for unresolved symbols..." << std::endl; - if( !unresolved_gterm_sym.empty() ){ - std::vector<api::Sort> types; - Debug("parser-sygus") << "...resolve " << unresolved_gterm_sym.size() << " symbols..." << std::endl; - for( unsigned i=0; i<unresolved_gterm_sym.size(); i++ ){ - Debug("parser-sygus") << " resolve : " << unresolved_gterm_sym[i] << std::endl; - if( isUnresolvedType(unresolved_gterm_sym[i]) ){ - Debug("parser-sygus") << " it is an unresolved type." << std::endl; - api::Sort t = getSort(unresolved_gterm_sym[i]); - if( std::find( types.begin(), types.end(), t )==types.end() ){ - types.push_back( t ); - //identity element - api::Sort bt = dt.getDatatype().getSygusType(); - Debug("parser-sygus") << ": make identity function for " << bt << ", argument type " << t << std::endl; - - std::stringstream ss; - ss << t << "_x"; - api::Term var = bindBoundVar(ss.str(), bt); - std::vector<api::Term> lchildren; - lchildren.push_back(d_solver->mkTerm(api::BOUND_VAR_LIST, var)); - lchildren.push_back(var); - api::Term id_op = d_solver->mkTerm(api::LAMBDA, lchildren); - - // empty sygus callback (should not be printed) - std::shared_ptr<SygusPrintCallback> sepc = - std::make_shared<printer::SygusEmptyPrintCallback>(); - - //make the sygus argument list - std::vector<api::Sort> id_carg; - id_carg.push_back( t ); - dt.getDatatype().addSygusConstructor(id_op.getExpr(), - unresolved_gterm_sym[i], - api::sortVectorToTypes(id_carg), - sepc); - - //add to operators - ParseOp idOp; - idOp.d_expr = id_op; - ops.push_back(idOp); - } - }else{ - std::stringstream ss; - ss << "Unhandled sygus constructor " << unresolved_gterm_sym[i]; - throw ParserException(ss.str()); - } - } - } -} - -api::Term Smt2::makeSygusBoundVarList(api::DatatypeDecl& dt, - unsigned i, - const std::vector<api::Sort>& ltypes, - std::vector<api::Term>& lvars) -{ - for (unsigned j = 0, size = ltypes.size(); j < size; j++) - { - std::stringstream ss; - ss << dt.getName() << "_x_" << i << "_" << j; - api::Term v = bindBoundVar(ss.str(), ltypes[j]); - lvars.push_back(v); - } - return d_solver->mkTerm(api::BOUND_VAR_LIST, lvars); -} void Smt2::addSygusConstructorTerm( api::DatatypeDecl& dt, @@ -1475,7 +936,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; } @@ -1529,7 +990,7 @@ void Smt2::parseOpApplyTypeAscription(ParseOp& p, api::Sort type) Debug("parser") << "parseOpApplyTypeAscription : " << p << " " << type << std::endl; // (as const (Array T1 T2)) - if (p.d_kind == api::STORE_ALL) + if (p.d_kind == api::CONST_ARRAY) { if (!type.isArray()) { @@ -1565,8 +1026,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) @@ -1584,18 +1044,9 @@ api::Term Smt2::parseOpToExpr(ParseOp& p) } else if (!isDeclared(p.d_name, SYM_VARIABLE)) { - if (sygus_v1() && p.d_name[0] == '-' - && p.d_name.find_first_not_of("0123456789", 1) == std::string::npos) - { - // allow unary minus in sygus version 1 - expr = d_solver->mkReal(p.d_name); - } - else - { - std::stringstream ss; - ss << "Symbol " << p.d_name << " is not declared."; - parseError(ss.str()); - } + std::stringstream ss; + ss << "Symbol " << p.d_name << " is not declared."; + parseError(ss.str()); } else { @@ -1696,7 +1147,7 @@ api::Term Smt2::applyParseOp(ParseOp& p, std::vector<api::Term>& args) // Second phase: apply the arguments to the parse op const Options& opts = d_solver->getExprManager()->getOptions(); // handle special cases - if (p.d_kind == api::STORE_ALL && !p.d_type.isNull()) + if (p.d_kind == api::CONST_ARRAY && !p.d_type.isNull()) { if (args.size() != 1) { @@ -1770,8 +1221,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; } @@ -1815,6 +1268,11 @@ api::Term Smt2::applyParseOp(ParseOp& p, std::vector<api::Term>& args) Debug("parser") << "applyParseOp: return uminus " << ret << std::endl; return ret; } + if (kind == api::EQ_RANGE && d_solver->getOption("arrays-exp") != "true") + { + parseError( + "eqrange predicate requires option --arrays-exp to be enabled."); + } api::Term ret = d_solver->mkTerm(kind, args); Debug("parser") << "applyParseOp: return default builtin " << ret << std::endl; diff --git a/src/parser/smt2/smt2.h b/src/parser/smt2/smt2.h index 35d088601..579fa90ce 100644 --- a/src/parser/smt2/smt2.h +++ b/src/parser/smt2/smt2.h @@ -2,9 +2,9 @@ /*! \file smt2.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Christopher L. Conway + ** Andrew Reynolds, Andres Noetzli, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -60,9 +60,6 @@ class Smt2 : public Parser */ std::unordered_map<std::string, api::Kind> d_indexedOpKindMap; std::pair<api::Term, std::string> d_lastNamedTerm; - // for sygus - std::vector<api::Term> d_sygusVars, d_sygusVarPrimed, d_sygusConstraints, - d_sygusFunSymbols; protected: Smt2(api::Solver* solver, @@ -98,6 +95,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; /** @@ -275,8 +279,6 @@ class Smt2 : public Parser } /** Are we using a sygus language? */ bool sygus() const; - /** Are we using the sygus version 1.0 format? */ - bool sygus_v1() const; /** Are we using the sygus version 2.0 format? */ bool sygus_v2() const; @@ -343,58 +345,6 @@ class Smt2 : public Parser */ api::Term mkAbstractValue(const std::string& name); - void mkSygusConstantsForType(const api::Sort& type, - std::vector<api::Term>& ops); - - void processSygusGTerm( - CVC4::SygusGTerm& sgt, - int index, - std::vector<api::DatatypeDecl>& datatypes, - std::vector<api::Sort>& sorts, - std::vector<std::vector<ParseOp>>& ops, - std::vector<std::vector<std::string>>& cnames, - std::vector<std::vector<std::vector<api::Sort>>>& cargs, - std::vector<bool>& allow_const, - std::vector<std::vector<std::string>>& unresolved_gterm_sym, - const std::vector<api::Term>& sygus_vars, - std::map<api::Sort, api::Sort>& sygus_to_builtin, - std::map<api::Sort, api::Term>& sygus_to_builtin_expr, - api::Sort& ret, - bool isNested = false); - - bool pushSygusDatatypeDef( - api::Sort t, - std::string& dname, - std::vector<api::DatatypeDecl>& datatypes, - std::vector<api::Sort>& sorts, - std::vector<std::vector<ParseOp>>& ops, - std::vector<std::vector<std::string>>& cnames, - std::vector<std::vector<std::vector<api::Sort>>>& cargs, - std::vector<bool>& allow_const, - std::vector<std::vector<std::string>>& unresolved_gterm_sym); - - bool popSygusDatatypeDef( - std::vector<api::DatatypeDecl>& datatypes, - std::vector<api::Sort>& sorts, - std::vector<std::vector<ParseOp>>& ops, - std::vector<std::vector<std::string>>& cnames, - std::vector<std::vector<std::vector<api::Sort>>>& cargs, - std::vector<bool>& allow_const, - std::vector<std::vector<std::string>>& unresolved_gterm_sym); - - void setSygusStartIndex(const std::string& fun, - int startIndex, - std::vector<api::DatatypeDecl>& datatypes, - std::vector<api::Sort>& sorts, - std::vector<std::vector<ParseOp>>& ops); - - void mkSygusDatatype(api::DatatypeDecl& dt, - std::vector<ParseOp>& ops, - std::vector<std::string>& cnames, - std::vector<std::vector<api::Sort>>& cargs, - std::vector<std::string>& unresolved_gterm_sym, - std::map<api::Sort, api::Sort>& sygus_to_builtin); - /** * Adds a constructor to sygus datatype dt whose sygus operator is term. * @@ -420,7 +370,6 @@ class Smt2 : public Parser void addSygusConstructorVariables(api::DatatypeDecl& dt, const std::vector<api::Term>& sygusVars, api::Sort type) const; - /** * Smt2 parser provides its own checkDeclaration, which does the * same as the base, but with some more helpful errors. @@ -435,11 +384,6 @@ class Smt2 : public Parser if (name.length() > 1 && name[0] == '-' && name.find_first_not_of("0123456789", 1) == std::string::npos) { - if (sygus_v1()) - { - // "-1" is allowed in SyGuS version 1.0 - return; - } std::stringstream ss; ss << notes << "You may have intended to apply unary minus: `(- " << name.substr(1) << ")'\n"; @@ -530,34 +474,6 @@ class Smt2 : public Parser api::Term applyParseOp(ParseOp& p, std::vector<api::Term>& args); //------------------------- end processing parse operators private: - std::map<api::Term, api::Sort> d_sygus_bound_var_type; - - api::Sort processSygusNestedGTerm( - int sub_dt_index, - std::string& sub_dname, - std::vector<api::DatatypeDecl>& datatypes, - std::vector<api::Sort>& sorts, - std::vector<std::vector<ParseOp>>& ops, - std::vector<std::vector<std::string>>& cnames, - std::vector<std::vector<std::vector<api::Sort>>>& cargs, - std::vector<bool>& allow_const, - std::vector<std::vector<std::string>>& unresolved_gterm_sym, - std::map<api::Sort, api::Sort>& sygus_to_builtin, - std::map<api::Sort, api::Term>& sygus_to_builtin_expr, - api::Sort sub_ret); - - /** make sygus bound var list - * - * This is used for converting non-builtin sygus operators to lambda - * expressions. It takes as input a datatype and constructor index (for - * naming) and a vector of type ltypes. - * It appends a bound variable to lvars for each type in ltypes, and returns - * a bound variable list whose children are lvars. - */ - api::Term makeSygusBoundVarList(api::DatatypeDecl& dt, - unsigned i, - const std::vector<api::Sort>& ltypes, - std::vector<api::Term>& lvars); /** Purify sygus grammar term * diff --git a/src/parser/smt2/smt2_input.cpp b/src/parser/smt2/smt2_input.cpp index c0bece257..521602e87 100644 --- a/src/parser/smt2/smt2_input.cpp +++ b/src/parser/smt2/smt2_input.cpp @@ -2,9 +2,9 @@ /*! \file smt2_input.cpp ** \verbatim ** Top contributors (to current version): - ** Christopher L. Conway, Morgan Deters, Andres Noetzli + ** Christopher L. Conway, Morgan Deters, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/smt2/smt2_input.h b/src/parser/smt2/smt2_input.h index 9d4ed2857..843cdf584 100644 --- a/src/parser/smt2/smt2_input.h +++ b/src/parser/smt2/smt2_input.h @@ -2,9 +2,9 @@ /*! \file smt2_input.h ** \verbatim ** Top contributors (to current version): - ** Christopher L. Conway, Tim King, Morgan Deters + ** Christopher L. Conway, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/smt2/sygus_input.cpp b/src/parser/smt2/sygus_input.cpp index a908bf4d5..fa0038bd5 100644 --- a/src/parser/smt2/sygus_input.cpp +++ b/src/parser/smt2/sygus_input.cpp @@ -2,9 +2,9 @@ /*! \file sygus_input.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/smt2/sygus_input.h b/src/parser/smt2/sygus_input.h index 39b161655..d2cc58e34 100644 --- a/src/parser/smt2/sygus_input.h +++ b/src/parser/smt2/sygus_input.h @@ -2,9 +2,9 @@ /*! \file sygus_input.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Mathias Preiner, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/tptp/Tptp.g b/src/parser/tptp/Tptp.g index c2f4675b1..bae02a5d2 100644 --- a/src/parser/tptp/Tptp.g +++ b/src/parser/tptp/Tptp.g @@ -2,9 +2,9 @@ /*! \file Tptp.g ** \verbatim ** Top contributors (to current version): - ** Francois Bobot, Morgan Deters, Andrew Reynolds + ** Haniel Barbosa, Francois Bobot, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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/parser/tptp/tptp.cpp b/src/parser/tptp/tptp.cpp index 51b852eac..403cab42b 100644 --- a/src/parser/tptp/tptp.cpp +++ b/src/parser/tptp/tptp.cpp @@ -2,9 +2,9 @@ /*! \file tptp.cpp ** \verbatim ** Top contributors (to current version): - ** Francois Bobot, Andrew Reynolds, Morgan Deters + ** Andrew Reynolds, Francois Bobot, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/tptp/tptp.h b/src/parser/tptp/tptp.h index 50557c95a..3d5419be9 100644 --- a/src/parser/tptp/tptp.h +++ b/src/parser/tptp/tptp.h @@ -2,9 +2,9 @@ /*! \file tptp.h ** \verbatim ** Top contributors (to current version): - ** Francois Bobot, Andrew Reynolds, Tim King + ** Andrew Reynolds, Francois Bobot, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/tptp/tptp_input.cpp b/src/parser/tptp/tptp_input.cpp index 741650150..cdd2ac7e5 100644 --- a/src/parser/tptp/tptp_input.cpp +++ b/src/parser/tptp/tptp_input.cpp @@ -2,9 +2,9 @@ /*! \file tptp_input.cpp ** \verbatim ** Top contributors (to current version): - ** Francois Bobot, Morgan Deters + ** Francois Bobot, Morgan Deters, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/parser/tptp/tptp_input.h b/src/parser/tptp/tptp_input.h index 1ca746298..9f8cd386f 100644 --- a/src/parser/tptp/tptp_input.h +++ b/src/parser/tptp/tptp_input.h @@ -2,9 +2,9 @@ /*! \file tptp_input.h ** \verbatim ** Top contributors (to current version): - ** Francois Bobot, Tim King + ** Francois Bobot, Mathias Preiner, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/assertion_pipeline.cpp b/src/preprocessing/assertion_pipeline.cpp index 7408f4ba3..caad369b7 100644 --- a/src/preprocessing/assertion_pipeline.cpp +++ b/src/preprocessing/assertion_pipeline.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andres Noetzli, Justin Xu, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/assertion_pipeline.h b/src/preprocessing/assertion_pipeline.h index b133bc490..5d8f64594 100644 --- a/src/preprocessing/assertion_pipeline.h +++ b/src/preprocessing/assertion_pipeline.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andres Noetzli, Justin Xu, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/ackermann.cpp b/src/preprocessing/passes/ackermann.cpp index 888456174..31c92a09f 100644 --- a/src/preprocessing/passes/ackermann.cpp +++ b/src/preprocessing/passes/ackermann.cpp @@ -2,9 +2,9 @@ /*! \file ackermann.cpp ** \verbatim ** Top contributors (to current version): - ** Yoni Zohar, Aina Niemetz, Clark Barrett, Ying Sheng + ** Ying Sheng, Yoni Zohar, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/ackermann.h b/src/preprocessing/passes/ackermann.h index 4aa26da85..1d2b6e9ce 100644 --- a/src/preprocessing/passes/ackermann.h +++ b/src/preprocessing/passes/ackermann.h @@ -2,9 +2,9 @@ /*! \file ackermann.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Yoni Zohar + ** Ying Sheng, Aina Niemetz, Yoni Zohar ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/apply_substs.cpp b/src/preprocessing/passes/apply_substs.cpp index 98313efda..71aa028d4 100644 --- a/src/preprocessing/passes/apply_substs.cpp +++ b/src/preprocessing/passes/apply_substs.cpp @@ -2,9 +2,9 @@ /*! \file apply_substs.cpp ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Andres Noetzli + ** Aina Niemetz, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/apply_substs.h b/src/preprocessing/passes/apply_substs.h index f20ffa61e..4f2dd24e5 100644 --- a/src/preprocessing/passes/apply_substs.h +++ b/src/preprocessing/passes/apply_substs.h @@ -2,9 +2,9 @@ /*! \file apply_substs.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz + ** Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bool_to_bv.cpp b/src/preprocessing/passes/bool_to_bv.cpp index e18e6f6c6..ad512bdfd 100644 --- a/src/preprocessing/passes/bool_to_bv.cpp +++ b/src/preprocessing/passes/bool_to_bv.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Makai Mann, Yoni Zohar, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bool_to_bv.h b/src/preprocessing/passes/bool_to_bv.h index 6e6d368eb..968672e86 100644 --- a/src/preprocessing/passes/bool_to_bv.h +++ b/src/preprocessing/passes/bool_to_bv.h @@ -2,9 +2,9 @@ /*! \file bool_to_bv.h ** \verbatim ** Top contributors (to current version): - ** Yoni Zohar, Makai Mann, Liana Hadarean + ** Makai Mann, Yoni Zohar, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_abstraction.cpp b/src/preprocessing/passes/bv_abstraction.cpp index d62c8a97e..5d6ed9b4f 100644 --- a/src/preprocessing/passes/bv_abstraction.cpp +++ b/src/preprocessing/passes/bv_abstraction.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_abstraction.h b/src/preprocessing/passes/bv_abstraction.h index b5840b355..aa1134a9b 100644 --- a/src/preprocessing/passes/bv_abstraction.h +++ b/src/preprocessing/passes/bv_abstraction.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_eager_atoms.cpp b/src/preprocessing/passes/bv_eager_atoms.cpp index a16a8347d..d4dd2b9b9 100644 --- a/src/preprocessing/passes/bv_eager_atoms.cpp +++ b/src/preprocessing/passes/bv_eager_atoms.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_eager_atoms.h b/src/preprocessing/passes/bv_eager_atoms.h index 4ed685855..cd84f1aaa 100644 --- a/src/preprocessing/passes/bv_eager_atoms.h +++ b/src/preprocessing/passes/bv_eager_atoms.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_gauss.cpp b/src/preprocessing/passes/bv_gauss.cpp index b08f69b50..68696015e 100644 --- a/src/preprocessing/passes/bv_gauss.cpp +++ b/src/preprocessing/passes/bv_gauss.cpp @@ -2,9 +2,9 @@ /*! \file bv_gauss.cpp ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Tim King + ** Aina Niemetz, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_gauss.h b/src/preprocessing/passes/bv_gauss.h index 7fb23814a..f09b2dbe4 100644 --- a/src/preprocessing/passes/bv_gauss.h +++ b/src/preprocessing/passes/bv_gauss.h @@ -2,9 +2,9 @@ /*! \file bv_gauss.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz + ** Aina Niemetz, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_intro_pow2.cpp b/src/preprocessing/passes/bv_intro_pow2.cpp index bfc02f332..a0f2ffdd5 100644 --- a/src/preprocessing/passes/bv_intro_pow2.cpp +++ b/src/preprocessing/passes/bv_intro_pow2.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_intro_pow2.h b/src/preprocessing/passes/bv_intro_pow2.h index 86d5ebfef..fcfef6f39 100644 --- a/src/preprocessing/passes/bv_intro_pow2.h +++ b/src/preprocessing/passes/bv_intro_pow2.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_to_bool.cpp b/src/preprocessing/passes/bv_to_bool.cpp index 33b41210a..f4d4d5b8c 100644 --- a/src/preprocessing/passes/bv_to_bool.cpp +++ b/src/preprocessing/passes/bv_to_bool.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Yoni Zohar, Liana Hadarean, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_to_bool.h b/src/preprocessing/passes/bv_to_bool.h index dc0494943..f0f4b3856 100644 --- a/src/preprocessing/passes/bv_to_bool.h +++ b/src/preprocessing/passes/bv_to_bool.h @@ -2,9 +2,9 @@ /*! \file bv_to_bool.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Yoni Zohar, Tim King + ** Liana Hadarean, Yoni Zohar, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/bv_to_int.cpp b/src/preprocessing/passes/bv_to_int.cpp index 0e4bc41c0..5b125b4b6 100644 --- a/src/preprocessing/passes/bv_to_int.cpp +++ b/src/preprocessing/passes/bv_to_int.cpp @@ -2,9 +2,9 @@ /*! \file bv_to_int.cpp ** \verbatim ** Top contributors (to current version): - ** Yoni Zohar and Ahmed Irfan + ** Yoni Zohar, Ahmed Irfan ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -184,43 +184,41 @@ Node BVToInt::eliminationPass(Node n) (d_eliminationCache.find(current) != d_eliminationCache.end()); bool inRebuildCache = (d_rebuildCache.find(current) != d_rebuildCache.end()); - if (!inRebuildCache) + if (!inEliminationCache) { - // current is not the elimination of any previously-visited node - if (!inEliminationCache) - { - // current hasn't been eliminated yet. - // eliminate operators from it - Node currentEliminated = - FixpointRewriteStrategy<RewriteRule<UdivZero>, - RewriteRule<SdivEliminate>, - RewriteRule<SremEliminate>, - RewriteRule<SmodEliminate>, - RewriteRule<RepeatEliminate>, - RewriteRule<ZeroExtendEliminate>, - RewriteRule<SignExtendEliminate>, - RewriteRule<RotateRightEliminate>, - RewriteRule<RotateLeftEliminate>, - RewriteRule<CompEliminate>, - RewriteRule<SleEliminate>, - RewriteRule<SltEliminate>, - RewriteRule<SgtEliminate>, - RewriteRule<SgeEliminate>, - RewriteRule<ShlByConst>, - RewriteRule<LshrByConst> >::apply(current); - // save in the cache - d_eliminationCache[current] = currentEliminated; - // put the eliminated node in the rebuild cache, but mark that it hasn't - // yet been rebuilt by assigning null. - d_rebuildCache[currentEliminated] = Node(); - // Push the eliminated node to the stack - toVisit.push_back(currentEliminated); - // Add the children to the stack for future processing. - toVisit.insert( - toVisit.end(), currentEliminated.begin(), currentEliminated.end()); - } + // current hasn't been eliminated yet. + // eliminate operators from it + Node currentEliminated = + FixpointRewriteStrategy<RewriteRule<UdivZero>, + RewriteRule<SdivEliminate>, + RewriteRule<SremEliminate>, + RewriteRule<SmodEliminate>, + RewriteRule<RepeatEliminate>, + RewriteRule<ZeroExtendEliminate>, + RewriteRule<SignExtendEliminate>, + RewriteRule<RotateRightEliminate>, + RewriteRule<RotateLeftEliminate>, + RewriteRule<CompEliminate>, + RewriteRule<SleEliminate>, + RewriteRule<SltEliminate>, + RewriteRule<SgtEliminate>, + RewriteRule<SgeEliminate>, + RewriteRule<ShlByConst>, + RewriteRule<LshrByConst> >::apply(current); + // save in the cache + d_eliminationCache[current] = currentEliminated; + // also assign the eliminated now to itself to avoid revisiting. + d_eliminationCache[currentEliminated] = currentEliminated; + // put the eliminated node in the rebuild cache, but mark that it hasn't + // yet been rebuilt by assigning null. + d_rebuildCache[currentEliminated] = Node(); + // Push the eliminated node to the stack + toVisit.push_back(currentEliminated); + // Add the children to the stack for future processing. + toVisit.insert( + toVisit.end(), currentEliminated.begin(), currentEliminated.end()); } - else + if (inRebuildCache) { // current was already added to the rebuild cache. if (d_rebuildCache[current].isNull()) diff --git a/src/preprocessing/passes/bv_to_int.h b/src/preprocessing/passes/bv_to_int.h index f0e0ea02e..5015d1e8e 100644 --- a/src/preprocessing/passes/bv_to_int.h +++ b/src/preprocessing/passes/bv_to_int.h @@ -2,9 +2,9 @@ /*! \file bv_to_int.h ** \verbatim ** Top contributors (to current version): - ** Yoni Zohar and Ahmed Irfan + ** Yoni Zohar ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/extended_rewriter_pass.cpp b/src/preprocessing/passes/extended_rewriter_pass.cpp index 8bf4cc816..39b3e1512 100644 --- a/src/preprocessing/passes/extended_rewriter_pass.cpp +++ b/src/preprocessing/passes/extended_rewriter_pass.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/extended_rewriter_pass.h b/src/preprocessing/passes/extended_rewriter_pass.h index dbaaa05ad..de6648d17 100644 --- a/src/preprocessing/passes/extended_rewriter_pass.h +++ b/src/preprocessing/passes/extended_rewriter_pass.h @@ -2,9 +2,9 @@ /*! \file extended_rewriter_pass.h ** \verbatim ** Top contributors (to current version): - ** Haniel Barbosa + ** Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/global_negate.cpp b/src/preprocessing/passes/global_negate.cpp index 59b5ddf6e..25bb0e532 100644 --- a/src/preprocessing/passes/global_negate.cpp +++ b/src/preprocessing/passes/global_negate.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Yoni Zohar ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/global_negate.h b/src/preprocessing/passes/global_negate.h index 89c3a3e3e..67cb0f770 100644 --- a/src/preprocessing/passes/global_negate.h +++ b/src/preprocessing/passes/global_negate.h @@ -2,9 +2,9 @@ /*! \file global_negate.h ** \verbatim ** Top contributors (to current version): - ** Yoni Zohar + ** Yoni Zohar, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/ho_elim.cpp b/src/preprocessing/passes/ho_elim.cpp index 65945f0d7..bb524315a 100644 --- a/src/preprocessing/passes/ho_elim.cpp +++ b/src/preprocessing/passes/ho_elim.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/ho_elim.h b/src/preprocessing/passes/ho_elim.h index f0de321c4..be088c46b 100644 --- a/src/preprocessing/passes/ho_elim.h +++ b/src/preprocessing/passes/ho_elim.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/int_to_bv.cpp b/src/preprocessing/passes/int_to_bv.cpp index 9fa9a0c05..e30c03f26 100644 --- a/src/preprocessing/passes/int_to_bv.cpp +++ b/src/preprocessing/passes/int_to_bv.cpp @@ -2,9 +2,9 @@ /*! \file int_to_bv.cpp ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andres Noetzli, Yoni Zohar, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -23,6 +23,7 @@ #include <vector> #include "expr/node.h" +#include "expr/node_traversal.h" #include "theory/rewriter.h" #include "theory/theory.h" @@ -36,107 +37,58 @@ using NodeMap = std::unordered_map<Node, Node, NodeHashFunction>; namespace { -// TODO: clean this up -struct intToBV_stack_element -{ - TNode d_node; - bool d_children_added; - intToBV_stack_element(TNode node) : d_node(node), d_children_added(false) {} -}; /* struct intToBV_stack_element */ - bool childrenTypesChanged(Node n, NodeMap& cache) { - bool result = false; for (Node child : n) { TypeNode originalType = child.getType(); TypeNode newType = cache[child].getType(); if (! newType.isSubtypeOf(originalType)) { - result = true; - break; + return true; } } - return result; + return false; } Node intToBVMakeBinary(TNode n, NodeMap& cache) { - // Do a topological sort of the subexpressions and substitute them - vector<intToBV_stack_element> toVisit; - toVisit.push_back(n); - - while (!toVisit.empty()) + for (TNode current : NodeDfsIterable(n, VisitOrder::POSTORDER, + [&cache](TNode nn) { return cache.count(nn) > 0; })) { - // The current node we are processing - intToBV_stack_element& stackHead = toVisit.back(); - TNode current = stackHead.d_node; - - NodeMap::iterator find = cache.find(current); - if (find != cache.end()) + Node result; + NodeManager* nm = NodeManager::currentNM(); + if (current.getNumChildren() == 0) { - toVisit.pop_back(); - continue; + result = current; } - if (stackHead.d_children_added) + else if (current.getNumChildren() > 2 + && (current.getKind() == kind::PLUS + || current.getKind() == kind::MULT)) { - // Children have been processed, so rebuild this node - Node result; - NodeManager* nm = NodeManager::currentNM(); - if (current.getNumChildren() > 2 - && (current.getKind() == kind::PLUS - || current.getKind() == kind::MULT)) - { - Assert(cache.find(current[0]) != cache.end()); - result = cache[current[0]]; - for (unsigned i = 1; i < current.getNumChildren(); ++i) - { - Assert(cache.find(current[i]) != cache.end()); - Node child = current[i]; - Node childRes = cache[current[i]]; - result = nm->mkNode(current.getKind(), result, childRes); - } - } - else + Assert(cache.find(current[0]) != cache.end()); + result = cache[current[0]]; + for (unsigned i = 1; i < current.getNumChildren(); ++i) { - NodeBuilder<> builder(current.getKind()); - if (current.getMetaKind() == kind::metakind::PARAMETERIZED) { - builder << current.getOperator(); - } - - for (unsigned i = 0; i < current.getNumChildren(); ++i) - { - Assert(cache.find(current[i]) != cache.end()); - builder << cache[current[i]]; - } - result = builder; + Assert(cache.find(current[i]) != cache.end()); + Node child = current[i]; + Node childRes = cache[current[i]]; + result = nm->mkNode(current.getKind(), result, childRes); } - cache[current] = result; - toVisit.pop_back(); } else { - // Mark that we have added the children if any - if (current.getNumChildren() > 0) - { - stackHead.d_children_added = true; - // We need to add the children - for (TNode::iterator child_it = current.begin(); - child_it != current.end(); - ++child_it) - { - TNode childNode = *child_it; - NodeMap::iterator childFind = cache.find(childNode); - if (childFind == cache.end()) - { - toVisit.push_back(childNode); - } - } + NodeBuilder<> builder(current.getKind()); + if (current.getMetaKind() == kind::metakind::PARAMETERIZED) { + builder << current.getOperator(); } - else + + for (unsigned i = 0; i < current.getNumChildren(); ++i) { - cache[current] = current; - toVisit.pop_back(); + Assert(cache.find(current[i]) != cache.end()); + builder << cache[current[i]]; } + result = builder; } + cache[current] = result; } return cache[n]; } @@ -147,30 +99,16 @@ Node intToBV(TNode n, NodeMap& cache) AlwaysAssert(size > 0); AlwaysAssert(!options::incrementalSolving()); - vector<intToBV_stack_element> toVisit; NodeMap binaryCache; Node n_binary = intToBVMakeBinary(n, binaryCache); - toVisit.push_back(TNode(n_binary)); - while (!toVisit.empty()) + for (TNode current : NodeDfsIterable(n_binary, VisitOrder::POSTORDER, + [&cache](TNode nn) { return cache.count(nn) > 0; })) { - // The current node we are processing - intToBV_stack_element& stackHead = toVisit.back(); - TNode current = stackHead.d_node; - - // If node is already in the cache we're done, pop from the stack - NodeMap::iterator find = cache.find(current); - if (find != cache.end()) - { - toVisit.pop_back(); - continue; - } - - // Not yet substituted, so process NodeManager* nm = NodeManager::currentNM(); - if (stackHead.d_children_added) + if (current.getNumChildren() > 0) { - // Children have been processed, so rebuild this node + // Not a leaf vector<Node> children; unsigned max = 0; for (unsigned i = 0; i < current.getNumChildren(); ++i) @@ -258,73 +196,51 @@ Node intToBV(TNode n, NodeMap& cache) result = Rewriter::rewrite(result); cache[current] = result; - toVisit.pop_back(); } else { - // Mark that we have added the children if any - if (current.getNumChildren() > 0) + // It's a leaf: could be a variable or a numeral + Node result = current; + if (current.isVar()) { - stackHead.d_children_added = true; - // We need to add the children - for (TNode::iterator child_it = current.begin(); - child_it != current.end(); - ++child_it) + if (current.getType() == nm->integerType()) { - TNode childNode = *child_it; - NodeMap::iterator childFind = cache.find(childNode); - if (childFind == cache.end()) - { - toVisit.push_back(childNode); - } + result = nm->mkSkolem("__intToBV_var", + nm->mkBitVectorType(size), + "Variable introduced in intToBV pass"); } } - else + else if (current.isConst()) { - // It's a leaf: could be a variable or a numeral - Node result = current; - if (current.isVar()) + switch (current.getKind()) { - if (current.getType() == nm->integerType()) + case kind::CONST_RATIONAL: { - result = nm->mkSkolem("__intToBV_var", - nm->mkBitVectorType(size), - "Variable introduced in intToBV pass"); - } - } - else if (current.isConst()) - { - switch (current.getKind()) - { - case kind::CONST_RATIONAL: - { - Rational constant = current.getConst<Rational>(); - if (constant.isIntegral()) { - AlwaysAssert(constant >= 0); - BitVector bv(size, constant.getNumerator()); - if (bv.toSignedInteger() != constant.getNumerator()) - { - throw TypeCheckingException( - current.toExpr(), - string("Not enough bits for constant in intToBV: ") - + current.toString()); - } - result = nm->mkConst(bv); + Rational constant = current.getConst<Rational>(); + if (constant.isIntegral()) { + AlwaysAssert(constant >= 0); + BitVector bv(size, constant.getNumerator()); + if (bv.toSignedInteger() != constant.getNumerator()) + { + throw TypeCheckingException( + current.toExpr(), + string("Not enough bits for constant in intToBV: ") + + current.toString()); } - break; + result = nm->mkConst(bv); } - default: break; + break; } + default: break; } - else - { - throw TypeCheckingException( - current.toExpr(), - string("Cannot translate to BV: ") + current.toString()); - } - cache[current] = result; - toVisit.pop_back(); } + else + { + throw TypeCheckingException( + current.toExpr(), + string("Cannot translate to BV: ") + current.toString()); + } + cache[current] = result; } } return cache[n_binary]; diff --git a/src/preprocessing/passes/int_to_bv.h b/src/preprocessing/passes/int_to_bv.h index 95f31621a..284cf7256 100644 --- a/src/preprocessing/passes/int_to_bv.h +++ b/src/preprocessing/passes/int_to_bv.h @@ -2,9 +2,9 @@ /*! \file int_to_bv.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/ite_removal.cpp b/src/preprocessing/passes/ite_removal.cpp index 6ad97f4a3..f021fff28 100644 --- a/src/preprocessing/passes/ite_removal.cpp +++ b/src/preprocessing/passes/ite_removal.cpp @@ -2,9 +2,9 @@ /*! \file ite_removal.cpp ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/ite_removal.h b/src/preprocessing/passes/ite_removal.h index 5620b4afb..950d7342a 100644 --- a/src/preprocessing/passes/ite_removal.h +++ b/src/preprocessing/passes/ite_removal.h @@ -2,9 +2,9 @@ /*! \file ite_removal.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/ite_simp.cpp b/src/preprocessing/passes/ite_simp.cpp index 7f7c4c95f..9a6a8ec61 100644 --- a/src/preprocessing/passes/ite_simp.cpp +++ b/src/preprocessing/passes/ite_simp.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Aina Niemetz, Tim King, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/ite_simp.h b/src/preprocessing/passes/ite_simp.h index 44976bded..cf122c4c9 100644 --- a/src/preprocessing/passes/ite_simp.h +++ b/src/preprocessing/passes/ite_simp.h @@ -2,9 +2,9 @@ /*! \file ite_simp.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz + ** Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/miplib_trick.cpp b/src/preprocessing/passes/miplib_trick.cpp index debb4d2ac..f64fce118 100644 --- a/src/preprocessing/passes/miplib_trick.cpp +++ b/src/preprocessing/passes/miplib_trick.cpp @@ -2,9 +2,9 @@ /*! \file miplib_trick.cpp ** \verbatim ** Top contributors (to current version): - ** Mathias Preiner, Tim King, Andres Noetzli + ** Mathias Preiner, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/miplib_trick.h b/src/preprocessing/passes/miplib_trick.h index f1748d635..d57658d47 100644 --- a/src/preprocessing/passes/miplib_trick.h +++ b/src/preprocessing/passes/miplib_trick.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/nl_ext_purify.cpp b/src/preprocessing/passes/nl_ext_purify.cpp index eb5728228..1f7e298ee 100644 --- a/src/preprocessing/passes/nl_ext_purify.cpp +++ b/src/preprocessing/passes/nl_ext_purify.cpp @@ -2,9 +2,9 @@ /*! \file nl_ext_purify.cpp ** \verbatim ** Top contributors (to current version): - ** Haniel Barbosa + ** Haniel Barbosa, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/nl_ext_purify.h b/src/preprocessing/passes/nl_ext_purify.h index 7744df824..a3004a7e8 100644 --- a/src/preprocessing/passes/nl_ext_purify.h +++ b/src/preprocessing/passes/nl_ext_purify.h @@ -2,9 +2,9 @@ /*! \file nl_ext_purify.h ** \verbatim ** Top contributors (to current version): - ** Haniel Barbosa + ** Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/non_clausal_simp.cpp b/src/preprocessing/passes/non_clausal_simp.cpp index 03f38370b..6d2482a0e 100644 --- a/src/preprocessing/passes/non_clausal_simp.cpp +++ b/src/preprocessing/passes/non_clausal_simp.cpp @@ -2,9 +2,9 @@ /*! \file non_clausal_simp.cpp ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Tim King, Andres Noetzli + ** Aina Niemetz, Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/non_clausal_simp.h b/src/preprocessing/passes/non_clausal_simp.h index cb4ece4a9..6e3645177 100644 --- a/src/preprocessing/passes/non_clausal_simp.h +++ b/src/preprocessing/passes/non_clausal_simp.h @@ -2,9 +2,9 @@ /*! \file non_clausal_simp.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz + ** Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/pseudo_boolean_processor.cpp b/src/preprocessing/passes/pseudo_boolean_processor.cpp index d852f2d86..1f9ca579c 100644 --- a/src/preprocessing/passes/pseudo_boolean_processor.cpp +++ b/src/preprocessing/passes/pseudo_boolean_processor.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/pseudo_boolean_processor.h b/src/preprocessing/passes/pseudo_boolean_processor.h index e73b721ff..fed566f78 100644 --- a/src/preprocessing/passes/pseudo_boolean_processor.h +++ b/src/preprocessing/passes/pseudo_boolean_processor.h @@ -2,9 +2,9 @@ /*! \file pseudo_boolean_processor.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Andres Noetzli + ** Tim King, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/quantifier_macros.cpp b/src/preprocessing/passes/quantifier_macros.cpp index bc2c136e4..a4d8454a0 100644 --- a/src/preprocessing/passes/quantifier_macros.cpp +++ b/src/preprocessing/passes/quantifier_macros.cpp @@ -2,9 +2,9 @@ /*! \file quantifier_macros.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Yoni Zohar, Morgan Deters + ** Andrew Reynolds, Yoni Zohar, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/quantifier_macros.h b/src/preprocessing/passes/quantifier_macros.h index 6b62c4d31..30a83e54a 100644 --- a/src/preprocessing/passes/quantifier_macros.h +++ b/src/preprocessing/passes/quantifier_macros.h @@ -2,9 +2,9 @@ /*! \file quantifier_macros.h ** \verbatim ** Top contributors (to current version): - ** Yoni Zohar, Andrew Reynolds + ** Yoni Zohar, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/quantifiers_preprocess.cpp b/src/preprocessing/passes/quantifiers_preprocess.cpp index eb6017402..3052e9629 100644 --- a/src/preprocessing/passes/quantifiers_preprocess.cpp +++ b/src/preprocessing/passes/quantifiers_preprocess.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Caleb Donovick ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/quantifiers_preprocess.h b/src/preprocessing/passes/quantifiers_preprocess.h index 991b3dd05..1e8b298f1 100644 --- a/src/preprocessing/passes/quantifiers_preprocess.h +++ b/src/preprocessing/passes/quantifiers_preprocess.h @@ -2,9 +2,9 @@ /*! \file quantifiers_preprocess.h ** \verbatim ** Top contributors (to current version): - ** Caleb Donovick + ** Caleb Donovick, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/real_to_int.cpp b/src/preprocessing/passes/real_to_int.cpp index 1c77f6f54..0e8ee3c4d 100644 --- a/src/preprocessing/passes/real_to_int.cpp +++ b/src/preprocessing/passes/real_to_int.cpp @@ -2,9 +2,9 @@ /*! \file real_to_int.cpp ** \verbatim ** Top contributors (to current version): - ** Haniel Barbosa + ** Haniel Barbosa, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/real_to_int.h b/src/preprocessing/passes/real_to_int.h index 7949fb051..d5c3be4e5 100644 --- a/src/preprocessing/passes/real_to_int.h +++ b/src/preprocessing/passes/real_to_int.h @@ -2,9 +2,9 @@ /*! \file real_to_int.h ** \verbatim ** Top contributors (to current version): - ** Haniel Barbosa + ** Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/rewrite.cpp b/src/preprocessing/passes/rewrite.cpp index deb58ae9f..e12691cc0 100644 --- a/src/preprocessing/passes/rewrite.cpp +++ b/src/preprocessing/passes/rewrite.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Caleb Donovick ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/rewrite.h b/src/preprocessing/passes/rewrite.h index e83cafb85..3bced24b1 100644 --- a/src/preprocessing/passes/rewrite.h +++ b/src/preprocessing/passes/rewrite.h @@ -2,9 +2,9 @@ /*! \file rewrite.h ** \verbatim ** Top contributors (to current version): - ** Caleb Donovick + ** Caleb Donovick, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/sep_skolem_emp.cpp b/src/preprocessing/passes/sep_skolem_emp.cpp index a81dbb4b5..b6f575789 100644 --- a/src/preprocessing/passes/sep_skolem_emp.cpp +++ b/src/preprocessing/passes/sep_skolem_emp.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Yoni Zohar, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/sep_skolem_emp.h b/src/preprocessing/passes/sep_skolem_emp.h index 1a5e36c40..8cbab3e29 100644 --- a/src/preprocessing/passes/sep_skolem_emp.h +++ b/src/preprocessing/passes/sep_skolem_emp.h @@ -2,9 +2,9 @@ /*! \file sep_skolem_emp.h ** \verbatim ** Top contributors (to current version): - ** Yoni Zohar + ** Yoni Zohar, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/sort_infer.cpp b/src/preprocessing/passes/sort_infer.cpp index d0612086c..92c2e55b1 100644 --- a/src/preprocessing/passes/sort_infer.cpp +++ b/src/preprocessing/passes/sort_infer.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/sort_infer.h b/src/preprocessing/passes/sort_infer.h index ae722529d..3a8646109 100644 --- a/src/preprocessing/passes/sort_infer.h +++ b/src/preprocessing/passes/sort_infer.h @@ -2,9 +2,9 @@ /*! \file sort_infer.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli + ** Andrew Reynolds, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/static_learning.cpp b/src/preprocessing/passes/static_learning.cpp index ec3982e03..314c34617 100644 --- a/src/preprocessing/passes/static_learning.cpp +++ b/src/preprocessing/passes/static_learning.cpp @@ -2,9 +2,9 @@ /*! \file static_learning.cpp ** \verbatim ** Top contributors (to current version): - ** Yoni Zohar + ** Yoni Zohar, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/static_learning.h b/src/preprocessing/passes/static_learning.h index f200755c5..16498f080 100644 --- a/src/preprocessing/passes/static_learning.h +++ b/src/preprocessing/passes/static_learning.h @@ -2,9 +2,9 @@ /*! \file static_learning.h ** \verbatim ** Top contributors (to current version): - ** Yoni Zohar + ** Yoni Zohar, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/sygus_inference.cpp b/src/preprocessing/passes/sygus_inference.cpp index 776e738d3..d8a587136 100644 --- a/src/preprocessing/passes/sygus_inference.cpp +++ b/src/preprocessing/passes/sygus_inference.cpp @@ -2,9 +2,9 @@ /*! \file sygus_inference.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/sygus_inference.h b/src/preprocessing/passes/sygus_inference.h index 91deb445c..6b84ea3fe 100644 --- a/src/preprocessing/passes/sygus_inference.h +++ b/src/preprocessing/passes/sygus_inference.h @@ -2,9 +2,9 @@ /*! \file sygus_inference.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/synth_rew_rules.cpp b/src/preprocessing/passes/synth_rew_rules.cpp index f1e9e39c5..699899c1e 100644 --- a/src/preprocessing/passes/synth_rew_rules.cpp +++ b/src/preprocessing/passes/synth_rew_rules.cpp @@ -2,9 +2,9 @@ /*! \file synth_rew_rules.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/synth_rew_rules.h b/src/preprocessing/passes/synth_rew_rules.h index 38ef98b35..80e09fd11 100644 --- a/src/preprocessing/passes/synth_rew_rules.h +++ b/src/preprocessing/passes/synth_rew_rules.h @@ -2,9 +2,9 @@ /*! \file synth_rew_rules.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/theory_preprocess.cpp b/src/preprocessing/passes/theory_preprocess.cpp index 1399363fa..5cc25b73f 100644 --- a/src/preprocessing/passes/theory_preprocess.cpp +++ b/src/preprocessing/passes/theory_preprocess.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/theory_preprocess.h b/src/preprocessing/passes/theory_preprocess.h index cfa9ab0b5..764685b85 100644 --- a/src/preprocessing/passes/theory_preprocess.h +++ b/src/preprocessing/passes/theory_preprocess.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/passes/unconstrained_simplifier.cpp b/src/preprocessing/passes/unconstrained_simplifier.cpp index 5d544ae57..7d1f66d65 100644 --- a/src/preprocessing/passes/unconstrained_simplifier.cpp +++ b/src/preprocessing/passes/unconstrained_simplifier.cpp @@ -2,9 +2,9 @@ /*! \file unconstrained_simplifier.cpp ** \verbatim ** Top contributors (to current version): - ** Clark Barrett, Andres Noetzli, Tim King + ** Clark Barrett, Andres Noetzli, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -75,6 +75,16 @@ void UnconstrainedSimplifier::visitAll(TNode assertion) { d_unconstrained.erase(current); } + else + { + // Also erase the children from the visited-once set when we visit a + // node a second time, otherwise variables in this node are not + // erased from the set of unconstrained variables. + for (TNode childNode : current) + { + toVisit.push_back(unc_preprocess_stack_element(childNode, current)); + } + } } ++find->second; continue; @@ -91,6 +101,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..c10730d60 100644 --- a/src/preprocessing/passes/unconstrained_simplifier.h +++ b/src/preprocessing/passes/unconstrained_simplifier.h @@ -2,9 +2,9 @@ /*! \file unconstrained_simplifier.h ** \verbatim ** Top contributors (to current version): - ** Clark Barrett, Andres Noetzli + ** Clark Barrett, Andres Noetzli, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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/preprocessing/preprocessing_pass.cpp b/src/preprocessing/preprocessing_pass.cpp index 84c3ca79b..965edcd2f 100644 --- a/src/preprocessing/preprocessing_pass.cpp +++ b/src/preprocessing/preprocessing_pass.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Justin Xu, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/preprocessing_pass.h b/src/preprocessing/preprocessing_pass.h index 4a2e71488..e81f71666 100644 --- a/src/preprocessing/preprocessing_pass.h +++ b/src/preprocessing/preprocessing_pass.h @@ -2,9 +2,9 @@ /*! \file preprocessing_pass.h ** \verbatim ** Top contributors (to current version): - ** Justin Xu + ** Justin Xu, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/preprocessing_pass_context.cpp b/src/preprocessing/preprocessing_pass_context.cpp index 75085d7c4..c7e7ae82c 100644 --- a/src/preprocessing/preprocessing_pass_context.cpp +++ b/src/preprocessing/preprocessing_pass_context.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Aina Niemetz, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/preprocessing_pass_context.h b/src/preprocessing/preprocessing_pass_context.h index f4317d786..deb600885 100644 --- a/src/preprocessing/preprocessing_pass_context.h +++ b/src/preprocessing/preprocessing_pass_context.h @@ -2,9 +2,9 @@ /*! \file preprocessing_pass_context.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Mathias Preiner, Justin Xu + ** Aina Niemetz, Mathias Preiner, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/preprocessing_pass_registry.cpp b/src/preprocessing/preprocessing_pass_registry.cpp index e264c17e5..59c03479e 100644 --- a/src/preprocessing/preprocessing_pass_registry.cpp +++ b/src/preprocessing/preprocessing_pass_registry.cpp @@ -2,9 +2,9 @@ /*! \file preprocessing_pass_registry.cpp ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli, Justin Xu, Yoni Zohar + ** Andres Noetzli, Yoni Zohar, Justin Xu ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/preprocessing_pass_registry.h b/src/preprocessing/preprocessing_pass_registry.h index 9cc109897..cf10ab902 100644 --- a/src/preprocessing/preprocessing_pass_registry.h +++ b/src/preprocessing/preprocessing_pass_registry.h @@ -2,9 +2,9 @@ /*! \file preprocessing_pass_registry.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli, Justin Xu, Yoni Zohar + ** Andres Noetzli, Justin Xu, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/util/ite_utilities.cpp b/src/preprocessing/util/ite_utilities.cpp index c609eebd7..45762341a 100644 --- a/src/preprocessing/util/ite_utilities.cpp +++ b/src/preprocessing/util/ite_utilities.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Aina Niemetz, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/preprocessing/util/ite_utilities.h b/src/preprocessing/util/ite_utilities.h index ad195e62e..d26dee206 100644 --- a/src/preprocessing/util/ite_utilities.h +++ b/src/preprocessing/util/ite_utilities.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Aina Niemetz, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/ast/ast_printer.cpp b/src/printer/ast/ast_printer.cpp index 2e32e9c12..1923594f3 100644 --- a/src/printer/ast/ast_printer.cpp +++ b/src/printer/ast/ast_printer.cpp @@ -2,9 +2,9 @@ /*! \file ast_printer.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Liana Hadarean + ** Morgan Deters, Tim King, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/ast/ast_printer.h b/src/printer/ast/ast_printer.h index fa109c779..2fd7da749 100644 --- a/src/printer/ast/ast_printer.h +++ b/src/printer/ast/ast_printer.h @@ -2,9 +2,9 @@ /*! \file ast_printer.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/cvc/cvc_printer.cpp b/src/printer/cvc/cvc_printer.cpp index 1178c7299..65117c9db 100644 --- a/src/printer/cvc/cvc_printer.cpp +++ b/src/printer/cvc/cvc_printer.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Dejan Jovanovic, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/cvc/cvc_printer.h b/src/printer/cvc/cvc_printer.h index 1694ea1ec..f5a06a082 100644 --- a/src/printer/cvc/cvc_printer.h +++ b/src/printer/cvc/cvc_printer.h @@ -2,9 +2,9 @@ /*! \file cvc_printer.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/dagification_visitor.cpp b/src/printer/dagification_visitor.cpp index 5463b1c22..50cf7b210 100644 --- a/src/printer/dagification_visitor.cpp +++ b/src/printer/dagification_visitor.cpp @@ -2,9 +2,9 @@ /*! \file dagification_visitor.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andrew Reynolds + ** Morgan Deters, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/dagification_visitor.h b/src/printer/dagification_visitor.h index 6df5f32b4..5ebbc6e18 100644 --- a/src/printer/dagification_visitor.h +++ b/src/printer/dagification_visitor.h @@ -2,9 +2,9 @@ /*! \file dagification_visitor.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/printer.cpp b/src/printer/printer.cpp index f8d62a8be..5d54759b9 100644 --- a/src/printer/printer.cpp +++ b/src/printer/printer.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Aina Niemetz, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -52,14 +52,6 @@ unique_ptr<Printer> Printer::makePrinter(OutputLanguage lang) case LANG_CVC4: return unique_ptr<Printer>(new printer::cvc::CvcPrinter()); - case LANG_Z3STR: - return unique_ptr<Printer>( - new printer::smt2::Smt2Printer(printer::smt2::z3str_variant)); - - case LANG_SYGUS_V1: - return unique_ptr<Printer>( - new printer::smt2::Smt2Printer(printer::smt2::sygus_variant)); - case LANG_SYGUS_V2: // sygus version 2.0 does not have discrepancies with smt2, hence we use // a normal smt2 variant here. @@ -122,9 +114,10 @@ Printer* Printer::getPrinter(OutputLanguage lang) lang = language::toOutputLanguage(options::inputLanguage()); } } - if(lang == language::output::LANG_AUTO) { - lang = language::output::LANG_CVC4; // default - } + if (lang == language::output::LANG_AUTO) + { + lang = language::output::LANG_SMTLIB_V2_6; // default + } } if(d_printers[lang] == NULL) { d_printers[lang] = makePrinter(lang); diff --git a/src/printer/printer.h b/src/printer/printer.h index 85b7d498f..b18e318ee 100644 --- a/src/printer/printer.h +++ b/src/printer/printer.h @@ -2,9 +2,9 @@ /*! \file printer.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andrew Reynolds + ** Tim King, Andrew Reynolds, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/smt2/smt2_printer.cpp b/src/printer/smt2/smt2_printer.cpp index 0c0c4c3a8..784e321a0 100644 --- a/src/printer/smt2/smt2_printer.cpp +++ b/src/printer/smt2/smt2_printer.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -21,6 +21,7 @@ #include <typeinfo> #include <vector> +#include "api/cvc4cpp.h" #include "expr/dtype.h" #include "expr/node_manager_attributes.h" #include "expr/node_visitor.h" @@ -146,31 +147,25 @@ void Smt2Printer::toStream(std::ostream& out, << n.getConst<FloatingPointSize>().significand() << ")"; break; - case kind::CONST_BITVECTOR: { + case kind::CONST_BITVECTOR: + { const BitVector& bv = n.getConst<BitVector>(); - const Integer& x = bv.getValue(); - unsigned width = bv.getSize(); - if (d_variant == sygus_variant || options::bvPrintConstsInBinary()) + if (options::bvPrintConstsAsIndexedSymbols()) { - out << "#b" << bv.toString(); + out << "(_ bv" << bv.getValue() << " " << bv.getSize() << ")"; } else { - out << "(_ "; - out << "bv" << x << " " << width; - out << ")"; + out << "#b" << bv.toString(); } - - // //out << "#b"; - - // while(n-- > 0) { - // out << (x.testBit(n) ? '1' : '0'); - // } break; } case kind::CONST_FLOATINGPOINT: - out << n.getConst<FloatingPoint>(); + { + out << n.getConst<FloatingPoint>().toString( + options::bvPrintConstsAsIndexedSymbols()); break; + } case kind::CONST_ROUNDINGMODE: switch (n.getConst<RoundingMode>()) { case roundNearestTiesToEven : out << "roundNearestTiesToEven"; break; @@ -292,26 +287,22 @@ void Smt2Printer::toStream(std::ostream& out, out << "(_ int2bv " << n.getConst<IntToBitVector>().d_size << ")"; break; case kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR_OP: - // out << "to_fp_bv " out << "(_ to_fp " << n.getConst<FloatingPointToFPIEEEBitVector>().t.exponent() << ' ' << n.getConst<FloatingPointToFPIEEEBitVector>().t.significand() << ")"; break; case kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT_OP: - // out << "to_fp_fp " out << "(_ to_fp " << n.getConst<FloatingPointToFPFloatingPoint>().t.exponent() << ' ' << n.getConst<FloatingPointToFPFloatingPoint>().t.significand() << ")"; break; case kind::FLOATINGPOINT_TO_FP_REAL_OP: - // out << "to_fp_real " out << "(_ to_fp " << n.getConst<FloatingPointToFPReal>().t.exponent() << ' ' << n.getConst<FloatingPointToFPReal>().t.significand() << ")"; break; case kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR_OP: - // out << "to_fp_signed " out << "(_ to_fp " << n.getConst<FloatingPointToFPSignedBitVector>().t.exponent() << ' ' << n.getConst<FloatingPointToFPSignedBitVector>().t.significand() @@ -598,40 +589,14 @@ void Smt2Printer::toStream(std::ostream& out, case kind::PARTIAL_SELECT_0: case kind::PARTIAL_SELECT_1: case kind::ARRAY_TYPE: - out << smtKindString(k, d_variant) << " "; - break; + case kind::EQ_RANGE: out << smtKindString(k, d_variant) << " "; break; // string theory case kind::STRING_CONCAT: - if(d_variant == z3str_variant) { - out << "Concat "; - for(unsigned i = 0; i < n.getNumChildren(); ++i) { - toStream(out, n[i], -1, types, TypeNode::null()); - if(i + 1 < n.getNumChildren()) { - out << ' '; - } - if(i + 2 < n.getNumChildren()) { - out << "(Concat "; - } - } - for(unsigned i = 0; i < n.getNumChildren() - 1; ++i) { - out << ")"; - } - return; - } out << "str.++ "; break; case kind::STRING_IN_REGEXP: { stringstream ss; - if(d_variant == z3str_variant && stringifyRegexp(n[1], ss)) { - out << "= "; - toStream(out, n[0], -1, types, TypeNode::null()); - out << " "; - Node str = NodeManager::currentNM()->mkConst(String(ss.str())); - toStream(out, str, -1, types, TypeNode::null()); - out << ")"; - return; - } out << smtKindString(k, d_variant) << " "; break; } @@ -642,6 +607,8 @@ void Smt2Printer::toStream(std::ostream& out, case kind::STRING_STRIDOF: case kind::STRING_STRREPL: case kind::STRING_STRREPLALL: + case kind::STRING_REPLACE_RE: + case kind::STRING_REPLACE_RE_ALL: case kind::STRING_TOLOWER: case kind::STRING_TOUPPER: case kind::STRING_REV: @@ -1077,6 +1044,8 @@ static string smtKindString(Kind k, Variant v) case kind::ARRAY_TYPE: return "Array"; case kind::PARTIAL_SELECT_0: return "partial_select_0"; case kind::PARTIAL_SELECT_1: return "partial_select_1"; + case kind::EQ_RANGE: + return "eqrange"; // bv theory case kind::BITVECTOR_CONCAT: return "concat"; @@ -1194,13 +1163,15 @@ static string smtKindString(Kind k, Variant v) //string theory case kind::STRING_CONCAT: return "str.++"; - case kind::STRING_LENGTH: return v == z3str_variant ? "Length" : "str.len"; + case kind::STRING_LENGTH: return "str.len"; case kind::STRING_SUBSTR: return "str.substr" ; case kind::STRING_STRCTN: return "str.contains" ; case kind::STRING_CHARAT: return "str.at" ; case kind::STRING_STRIDOF: return "str.indexof" ; case kind::STRING_STRREPL: return "str.replace" ; case kind::STRING_STRREPLALL: return "str.replace_all"; + case kind::STRING_REPLACE_RE: return "str.replace_re"; + case kind::STRING_REPLACE_RE_ALL: return "str.replace_re_all"; case kind::STRING_TOLOWER: return "str.tolower"; case kind::STRING_TOUPPER: return "str.toupper"; case kind::STRING_REV: return "str.rev"; @@ -1289,7 +1260,6 @@ void Smt2Printer::toStream(std::ostream& out, || tryToStream<EmptyCommand>(out, c) || tryToStream<EchoCommand>(out, c, d_variant) || tryToStream<SynthFunCommand>(out, c) - || tryToStream<DeclareSygusPrimedVarCommand>(out, c) || tryToStream<DeclareSygusFunctionCommand>(out, c) || tryToStream<DeclareSygusVarCommand>(out, c) || tryToStream<SygusConstraintCommand>(out, c) @@ -1672,8 +1642,8 @@ static void toStream(std::ostream& out, const DefineFunctionCommand* c) static void toStream(std::ostream& out, const DefineFunctionRecCommand* c) { - const vector<Expr>& funcs = c->getFunctions(); - const vector<vector<Expr> >& formals = c->getFormals(); + const vector<api::Term>& funcs = c->getFunctions(); + const vector<vector<api::Term> >& formals = c->getFormals(); out << "(define-fun"; if (funcs.size() > 1) { @@ -1696,10 +1666,10 @@ static void toStream(std::ostream& out, const DefineFunctionRecCommand* c) } out << funcs[i] << " ("; // print its type signature - vector<Expr>::const_iterator itf = formals[i].begin(); + vector<api::Term>::const_iterator itf = formals[i].begin(); for (;;) { - out << "(" << (*itf) << " " << (*itf).getType() << ")"; + out << "(" << (*itf) << " " << (*itf).getSort() << ")"; ++itf; if (itf != formals[i].end()) { @@ -1710,8 +1680,8 @@ static void toStream(std::ostream& out, const DefineFunctionRecCommand* c) break; } } - Type type = funcs[i].getType(); - type = static_cast<FunctionType>(type).getRangeType(); + api::Sort type = funcs[i].getSort(); + type = type.getFunctionCodomainSort(); out << ") " << type; if (funcs.size() > 1) { @@ -1722,7 +1692,7 @@ static void toStream(std::ostream& out, const DefineFunctionRecCommand* c) { out << ") ("; } - const vector<Expr>& formulas = c->getFormulas(); + const vector<api::Term>& formulas = c->getFormulas(); for (unsigned i = 0, size = formulas.size(); i < size; i++) { if (i > 0) @@ -1856,12 +1826,7 @@ static void toStream(std::ostream& out, const SetBenchmarkLogicCommand* c, Variant v) { - // Z3-str doesn't have string-specific logic strings(?), so comment it - if(v == z3str_variant) { - out << "; (set-logic " << c->getLogic() << ")"; - } else { - out << "(set-logic " << c->getLogic() << ")"; - } + out << "(set-logic " << c->getLogic() << ")"; } static void toStream(std::ostream& out, const SetInfoCommand* c, Variant v) @@ -2025,7 +1990,7 @@ static void toStream(std::ostream& out, const CommentCommand* c, Variant v) string s = c->getComment(); size_t pos = 0; while((pos = s.find_first_of('"', pos)) != string::npos) { - s.replace(pos, 1, (v == z3str_variant || v == smt2_0_variant) ? "\\\"" : "\"\""); + s.replace(pos, 1, v == smt2_0_variant ? "\\\"" : "\"\""); pos += 2; } out << "(set-info :notes \"" << s << "\")"; @@ -2039,7 +2004,7 @@ static void toStream(std::ostream& out, const EchoCommand* c, Variant v) // escape all double-quotes size_t pos = 0; while((pos = s.find('"', pos)) != string::npos) { - s.replace(pos, 1, (v == z3str_variant || v == smt2_0_variant) ? "\\\"" : "\"\""); + s.replace(pos, 1, v == smt2_0_variant ? "\\\"" : "\"\""); pos += 2; } out << "(echo \"" << s << "\")"; @@ -2159,12 +2124,6 @@ static void toStream(std::ostream& out, const DeclareSygusFunctionCommand* c) out << " (" << argTypes << ") " << ft.getRangeType() << ')'; } -static void toStream(std::ostream& out, const DeclareSygusPrimedVarCommand* c) -{ - out << '(' << c->getCommandName() << ' ' << CVC4::quoteSymbol(c->getSymbol()) - << ' ' << c->getType() << ')'; -} - static void toStream(std::ostream& out, const DeclareSygusVarCommand* c) { out << '(' << c->getCommandName() << ' ' << c->getVar() << ' ' << c->getType() @@ -2244,7 +2203,7 @@ static void errorToStream(std::ostream& out, std::string message, Variant v) { // escape all double-quotes size_t pos = 0; while((pos = message.find('"', pos)) != string::npos) { - message.replace(pos, 1, (v == z3str_variant || v == smt2_0_variant) ? "\\\"" : "\"\""); + message.replace(pos, 1, v == smt2_0_variant ? "\\\"" : "\"\""); pos += 2; } out << "(error \"" << message << "\")" << endl; @@ -2274,9 +2233,6 @@ static OutputLanguage variantToLanguage(Variant variant) switch(variant) { case smt2_0_variant: return language::output::LANG_SMTLIB_V2_0; - case z3str_variant: - return language::output::LANG_Z3STR; - case sygus_variant: return language::output::LANG_SYGUS_V1; case no_variant: default: return language::output::LANG_SMTLIB_V2_6; } diff --git a/src/printer/smt2/smt2_printer.h b/src/printer/smt2/smt2_printer.h index b34acacbb..398e510cb 100644 --- a/src/printer/smt2/smt2_printer.h +++ b/src/printer/smt2/smt2_printer.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -33,7 +33,6 @@ enum Variant smt2_0_variant, // old-style 2.0 syntax, when it makes a difference smt2_6_variant, // new-style 2.6 syntax, when it makes a difference, with // support for the string standard - z3str_variant, // old-style 2.0 and also z3str syntax sygus_variant // variant for sygus }; /* enum Variant */ class Smt2Printer : public CVC4::Printer { diff --git a/src/printer/sygus_print_callback.cpp b/src/printer/sygus_print_callback.cpp index 92a89a18e..a15bde3c3 100644 --- a/src/printer/sygus_print_callback.cpp +++ b/src/printer/sygus_print_callback.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/sygus_print_callback.h b/src/printer/sygus_print_callback.h index a53fbc85f..925c80ae8 100644 --- a/src/printer/sygus_print_callback.h +++ b/src/printer/sygus_print_callback.h @@ -2,9 +2,9 @@ /*! \file sygus_print_callback.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/tptp/tptp_printer.cpp b/src/printer/tptp/tptp_printer.cpp index d06b80e7b..f1c1089ad 100644 --- a/src/printer/tptp/tptp_printer.cpp +++ b/src/printer/tptp/tptp_printer.cpp @@ -2,9 +2,9 @@ /*! \file tptp_printer.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andrew Reynolds + ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/printer/tptp/tptp_printer.h b/src/printer/tptp/tptp_printer.h index 63272891e..d183a19d0 100644 --- a/src/printer/tptp/tptp_printer.h +++ b/src/printer/tptp/tptp_printer.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/arith_proof.cpp b/src/proof/arith_proof.cpp index 7b56c176f..635767b97 100644 --- a/src/proof/arith_proof.cpp +++ b/src/proof/arith_proof.cpp @@ -2,9 +2,9 @@ /*! \file arith_proof.cpp ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir, Guy Katz, Liana Hadarean + ** Alex Ozdemir, Liana Hadarean, Guy Katz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/arith_proof.h b/src/proof/arith_proof.h index b889614f1..832afcae0 100644 --- a/src/proof/arith_proof.h +++ b/src/proof/arith_proof.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Alex Ozdemir, Guy Katz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/arith_proof_recorder.cpp b/src/proof/arith_proof_recorder.cpp index c240f9582..01da402c9 100644 --- a/src/proof/arith_proof_recorder.cpp +++ b/src/proof/arith_proof_recorder.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/arith_proof_recorder.h b/src/proof/arith_proof_recorder.h index 3fff6968d..0669e5d16 100644 --- a/src/proof/arith_proof_recorder.h +++ b/src/proof/arith_proof_recorder.h @@ -2,9 +2,9 @@ /*! \file arith_proof_recorder.h ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir + ** Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/array_proof.cpp b/src/proof/array_proof.cpp index 32dcaf5b2..2d42a7489 100644 --- a/src/proof/array_proof.cpp +++ b/src/proof/array_proof.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Guy Katz, Yoni Zohar, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/array_proof.h b/src/proof/array_proof.h index 55cda0aba..ffcff165a 100644 --- a/src/proof/array_proof.h +++ b/src/proof/array_proof.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Mathias Preiner, Guy Katz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/bitvector_proof.cpp b/src/proof/bitvector_proof.cpp index fddcb9e78..98e3300f5 100644 --- a/src/proof/bitvector_proof.cpp +++ b/src/proof/bitvector_proof.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Guy Katz, Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/bitvector_proof.h b/src/proof/bitvector_proof.h index 8264d3bc4..9a9071e58 100644 --- a/src/proof/bitvector_proof.h +++ b/src/proof/bitvector_proof.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Alex Ozdemir, Mathias Preiner, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/clausal_bitvector_proof.cpp b/src/proof/clausal_bitvector_proof.cpp index 6a5009b1f..21e8056ca 100644 --- a/src/proof/clausal_bitvector_proof.cpp +++ b/src/proof/clausal_bitvector_proof.cpp @@ -2,9 +2,9 @@ /*! \file clausal_bitvector_proof.cpp ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir + ** Alex Ozdemir, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/clausal_bitvector_proof.h b/src/proof/clausal_bitvector_proof.h index 2047e325c..28a53c90c 100644 --- a/src/proof/clausal_bitvector_proof.h +++ b/src/proof/clausal_bitvector_proof.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/clause_id.h b/src/proof/clause_id.h index 4a9ebc74a..b2d36c9cb 100644 --- a/src/proof/clause_id.h +++ b/src/proof/clause_id.h @@ -2,9 +2,9 @@ /*! \file clause_id.h ** \verbatim ** Top contributors (to current version): - ** Paul Meng + ** Paul Meng, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/cnf_proof.cpp b/src/proof/cnf_proof.cpp index 21636650d..677bf2f8c 100644 --- a/src/proof/cnf_proof.cpp +++ b/src/proof/cnf_proof.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Andrew Reynolds, Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/cnf_proof.h b/src/proof/cnf_proof.h index e589950bc..56993583e 100644 --- a/src/proof/cnf_proof.h +++ b/src/proof/cnf_proof.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Guy Katz, Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/dimacs.cpp b/src/proof/dimacs.cpp index fd5b79383..d9d9f8c1c 100644 --- a/src/proof/dimacs.cpp +++ b/src/proof/dimacs.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/dimacs.h b/src/proof/dimacs.h index 5956c5d26..405b33208 100644 --- a/src/proof/dimacs.h +++ b/src/proof/dimacs.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/drat/drat_proof.cpp b/src/proof/drat/drat_proof.cpp index e35741cde..ee9c42d77 100644 --- a/src/proof/drat/drat_proof.cpp +++ b/src/proof/drat/drat_proof.cpp @@ -2,9 +2,9 @@ /*! \file drat_proof.cpp ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir + ** Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/drat/drat_proof.h b/src/proof/drat/drat_proof.h index 082107d0a..1213c80c7 100644 --- a/src/proof/drat/drat_proof.h +++ b/src/proof/drat/drat_proof.h @@ -2,9 +2,9 @@ /*! \file drat_proof.h ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir + ** Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/er/er_proof.cpp b/src/proof/er/er_proof.cpp index 9b036c3a6..54b0fd879 100644 --- a/src/proof/er/er_proof.cpp +++ b/src/proof/er/er_proof.cpp @@ -2,9 +2,9 @@ /*! \file er_proof.cpp ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir + ** Alex Ozdemir, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/er/er_proof.h b/src/proof/er/er_proof.h index 9fc40e64e..6f7239ef2 100644 --- a/src/proof/er/er_proof.h +++ b/src/proof/er/er_proof.h @@ -2,9 +2,9 @@ /*! \file er_proof.h ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir + ** Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/lemma_proof.cpp b/src/proof/lemma_proof.cpp index f4249f3d5..bdebb6cfc 100644 --- a/src/proof/lemma_proof.cpp +++ b/src/proof/lemma_proof.cpp @@ -2,9 +2,9 @@ /*! \file lemma_proof.cpp ** \verbatim ** Top contributors (to current version): - ** Guy Katz, Alex Ozdemir + ** Guy Katz, Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/lemma_proof.h b/src/proof/lemma_proof.h index 7dfce57cf..ffc6655a6 100644 --- a/src/proof/lemma_proof.h +++ b/src/proof/lemma_proof.h @@ -2,9 +2,9 @@ /*! \file lemma_proof.h ** \verbatim ** Top contributors (to current version): - ** Guy Katz, Alex Ozdemir + ** Guy Katz, Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/lfsc_proof_printer.cpp b/src/proof/lfsc_proof_printer.cpp index 1a18d06a6..464083841 100644 --- a/src/proof/lfsc_proof_printer.cpp +++ b/src/proof/lfsc_proof_printer.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andres Noetzli, Alex Ozdemir, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/lfsc_proof_printer.h b/src/proof/lfsc_proof_printer.h index f2f55aa94..62547676f 100644 --- a/src/proof/lfsc_proof_printer.h +++ b/src/proof/lfsc_proof_printer.h @@ -2,9 +2,9 @@ /*! \file lfsc_proof_printer.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli, Alex Ozdemir + ** Andres Noetzli, Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/lrat/lrat_proof.cpp b/src/proof/lrat/lrat_proof.cpp index 4a19f07be..69ffa623a 100644 --- a/src/proof/lrat/lrat_proof.cpp +++ b/src/proof/lrat/lrat_proof.cpp @@ -2,9 +2,9 @@ /*! \file lrat_proof.cpp ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir + ** Alex Ozdemir, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/lrat/lrat_proof.h b/src/proof/lrat/lrat_proof.h index f5a11fd4e..1c065a08e 100644 --- a/src/proof/lrat/lrat_proof.h +++ b/src/proof/lrat/lrat_proof.h @@ -2,9 +2,9 @@ /*! \file lrat_proof.h ** \verbatim ** Top contributors (to current version): - ** Alex Ozdemir + ** Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/proof.h b/src/proof/proof.h index 9e7e20a22..be5af32db 100644 --- a/src/proof/proof.h +++ b/src/proof/proof.h @@ -2,9 +2,9 @@ /*! \file proof.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Liana Hadarean, Morgan Deters + ** Tim King, Liana Hadarean, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/proof_manager.cpp b/src/proof/proof_manager.cpp index f9e3293fa..99e3010b4 100644 --- a/src/proof/proof_manager.cpp +++ b/src/proof/proof_manager.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Guy Katz, Liana Hadarean, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -565,6 +565,30 @@ void LFSCProof::toStream(std::ostream& out, const ProofLetMap& map) const Unreachable(); } +void collectAtoms(TNode node, std::set<Node>& seen, CnfProof* cnfProof) +{ + Debug("pf::pm::atoms") << "collectAtoms: Colleting atoms from " << node + << "\n"; + if (seen.find(node) != seen.end()) + { + Debug("pf::pm::atoms") << "collectAtoms:\t already seen\n"; + return; + } + // if I have a SAT literal for a node, save it, unless this node is a + // negation, in which case its underlying will be collected downstream + if (cnfProof->hasLiteral(node) && node.getKind() != kind::NOT) + { + Debug("pf::pm::atoms") << "collectAtoms: has SAT literal, save\n"; + seen.insert(node); + } + for (unsigned i = 0; i < node.getNumChildren(); ++i) + { + Debug("pf::pm::atoms") << push; + collectAtoms(node[i], seen, cnfProof); + Debug("pf::pm::atoms") << pop; + } +} + void LFSCProof::toStream(std::ostream& out) const { TimerStat::CodeTimer proofProductionTimer( @@ -683,10 +707,15 @@ void LFSCProof::toStream(std::ostream& out) const d_cnfProof->collectAtomsForClauses(used_lemmas, atoms); // collects the atoms in the assertions + Debug("pf::pm") << std::endl + << "LFSCProof::toStream: Colleting atoms from assertions " + << used_assertions << "\n" + << push; for (TNode used_assertion : used_assertions) { - utils::collectAtoms(used_assertion, atoms); + collectAtoms(used_assertion, atoms, d_cnfProof); } + Debug("pf::pm") << pop; std::set<Node>::iterator atomIt; Debug("pf::pm") << std::endl diff --git a/src/proof/proof_manager.h b/src/proof/proof_manager.h index a59f36858..45bde4dcb 100644 --- a/src/proof/proof_manager.h +++ b/src/proof/proof_manager.h @@ -2,9 +2,9 @@ /*! \file proof_manager.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Guy Katz, Morgan Deters + ** Liana Hadarean, Guy Katz, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/proof_output_channel.cpp b/src/proof/proof_output_channel.cpp index aa2175e66..1e6e759e3 100644 --- a/src/proof/proof_output_channel.cpp +++ b/src/proof/proof_output_channel.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Guy Katz, Tim King, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/proof_output_channel.h b/src/proof/proof_output_channel.h index ff84a3743..6a91bad7c 100644 --- a/src/proof/proof_output_channel.h +++ b/src/proof/proof_output_channel.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Guy Katz, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/proof_utils.cpp b/src/proof/proof_utils.cpp index 3342d421a..cad56db6a 100644 --- a/src/proof/proof_utils.cpp +++ b/src/proof/proof_utils.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Andrew Reynolds, Guy Katz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -21,19 +21,6 @@ namespace CVC4 { namespace utils { -void collectAtoms(TNode node, std::set<Node>& seen) { - if (seen.find(node) != seen.end()) - return; - if (theory::Theory::theoryOf(node) != theory::THEORY_BOOL || node.isVar()) { - seen.insert(node); - return; - } - - for (unsigned i = 0; i < node.getNumChildren(); ++i) { - collectAtoms(node[i], seen); - } -} - std::string toLFSCKind(Kind kind) { switch(kind) { // core kinds diff --git a/src/proof/proof_utils.h b/src/proof/proof_utils.h index 23f221cf6..e54edd8b7 100644 --- a/src/proof/proof_utils.h +++ b/src/proof/proof_utils.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Guy Katz, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -225,8 +225,5 @@ inline const bool getBit(Expr expr, unsigned i) { return (bit == 1u); } -void collectAtoms(TNode node, std::set<Node>& seen); - - } } diff --git a/src/proof/resolution_bitvector_proof.cpp b/src/proof/resolution_bitvector_proof.cpp index 120397d08..d48789f71 100644 --- a/src/proof/resolution_bitvector_proof.cpp +++ b/src/proof/resolution_bitvector_proof.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Alex Ozdemir, Liana Hadarean, Guy Katz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/resolution_bitvector_proof.h b/src/proof/resolution_bitvector_proof.h index 5fd11092f..a1b0b0d59 100644 --- a/src/proof/resolution_bitvector_proof.h +++ b/src/proof/resolution_bitvector_proof.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Alex Ozdemir, Mathias Preiner, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/sat_proof.h b/src/proof/sat_proof.h index ec0928c07..83e4d3930 100644 --- a/src/proof/sat_proof.h +++ b/src/proof/sat_proof.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Tim King, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/sat_proof_implementation.h b/src/proof/sat_proof_implementation.h index 8c65d42e7..897a5c452 100644 --- a/src/proof/sat_proof_implementation.h +++ b/src/proof/sat_proof_implementation.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Tim King, Guy Katz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/simplify_boolean_node.cpp b/src/proof/simplify_boolean_node.cpp index 0fd69fc20..5f1943654 100644 --- a/src/proof/simplify_boolean_node.cpp +++ b/src/proof/simplify_boolean_node.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Guy Katz, Liana Hadarean, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/simplify_boolean_node.h b/src/proof/simplify_boolean_node.h index fe8b7174b..bb4fe2e47 100644 --- a/src/proof/simplify_boolean_node.h +++ b/src/proof/simplify_boolean_node.h @@ -2,9 +2,9 @@ /*! \file simplify_boolean_node.h ** \verbatim ** Top contributors (to current version): - ** Guy Katz + ** Mathias Preiner, Guy Katz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/skolemization_manager.cpp b/src/proof/skolemization_manager.cpp index 44ca08fa6..1bb14598d 100644 --- a/src/proof/skolemization_manager.cpp +++ b/src/proof/skolemization_manager.cpp @@ -2,9 +2,9 @@ /*! \file skolemization_manager.cpp ** \verbatim ** Top contributors (to current version): - ** Paul Meng, Tim King + ** Paul Meng, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/skolemization_manager.h b/src/proof/skolemization_manager.h index cb23268f3..a2c61db4d 100644 --- a/src/proof/skolemization_manager.h +++ b/src/proof/skolemization_manager.h @@ -2,9 +2,9 @@ /*! \file skolemization_manager.h ** \verbatim ** Top contributors (to current version): - ** Guy Katz, Tim King + ** Guy Katz, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/theory_proof.cpp b/src/proof/theory_proof.cpp index f4a762cb0..66109bfac 100644 --- a/src/proof/theory_proof.cpp +++ b/src/proof/theory_proof.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Guy Katz, Liana Hadarean, Yoni Zohar ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/theory_proof.h b/src/proof/theory_proof.h index 85c8e5fee..dd5fe0326 100644 --- a/src/proof/theory_proof.h +++ b/src/proof/theory_proof.h @@ -2,9 +2,9 @@ /*! \file theory_proof.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Guy Katz, Yoni Zohar + ** Liana Hadarean, Guy Katz, Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/uf_proof.cpp b/src/proof/uf_proof.cpp index 225cb6aa4..74990ff44 100644 --- a/src/proof/uf_proof.cpp +++ b/src/proof/uf_proof.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Guy Katz, Yoni Zohar ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/uf_proof.h b/src/proof/uf_proof.h index 834f6ef9e..647359a87 100644 --- a/src/proof/uf_proof.h +++ b/src/proof/uf_proof.h @@ -2,9 +2,9 @@ /*! \file uf_proof.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Mathias Preiner, Tim King + ** Mathias Preiner, Liana Hadarean, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/unsat_core.cpp b/src/proof/unsat_core.cpp index 0776197cb..e54d976c9 100644 --- a/src/proof/unsat_core.cpp +++ b/src/proof/unsat_core.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Clark Barrett, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/unsat_core.h b/src/proof/unsat_core.h index 0217b6326..c0dd36ea5 100644 --- a/src/proof/unsat_core.h +++ b/src/proof/unsat_core.h @@ -2,9 +2,9 @@ /*! \file unsat_core.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andrew Reynolds, Liana Hadarean + ** Morgan Deters, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/proof/unsat_core.i b/src/proof/unsat_core.i index c37c8551d..780a75996 100644 --- a/src/proof/unsat_core.i +++ b/src/proof/unsat_core.i @@ -1,17 +1,37 @@ %{ #include "proof/unsat_core.h" +%} + +%ignore CVC4::operator<<(std::ostream&, const UnsatCore&); #ifdef SWIGJAVA -#include "bindings/java_iterator_adapter.h" -#include "bindings/java_stream_adapters.h" +%typemap(javabody) CVC4::UnsatCore %{ + private long swigCPtr; + protected boolean swigCMemOwn; + private ExprManager em; -#endif /* SWIGJAVA */ + protected $javaclassname(ExprManager em, long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + this.em = em; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + public JavaIteratorAdapter_UnsatCore iterator() { + return new JavaIteratorAdapter_UnsatCore(this.em, this); + } %} -%ignore CVC4::operator<<(std::ostream&, const UnsatCore&); +%typemap(javaout) CVC4::Expr { + return new Expr(this.em, $jnicall, true); +} -#ifdef SWIGJAVA +%ignore CVC4::UnsatCore::UnsatCore(); +%ignore CVC4::UnsatCore::UnsatCore(SmtEngine* smt, std::vector<Expr> core); // Instead of UnsatCore::begin() and end(), create an // iterator() method on the Java side that returns a Java-style @@ -20,12 +40,8 @@ %ignore CVC4::UnsatCore::end(); %ignore CVC4::UnsatCore::begin() const; %ignore CVC4::UnsatCore::end() const; -%extend CVC4::UnsatCore { - CVC4::JavaIteratorAdapter<CVC4::UnsatCore, CVC4::Expr> iterator() - { - return CVC4::JavaIteratorAdapter<CVC4::UnsatCore, CVC4::Expr>(*$self); - } +%extend CVC4::UnsatCore { std::string toString() { std::stringstream ss; @@ -37,36 +53,13 @@ // UnsatCore is "iterable" on the Java side %typemap(javainterfaces) CVC4::UnsatCore "java.lang.Iterable<edu.stanford.CVC4.Expr>"; -// the JavaIteratorAdapter should not be public, and implements Iterator -%typemap(javaclassmodifiers) CVC4::JavaIteratorAdapter<CVC4::UnsatCore, CVC4::Expr> "class"; -%typemap(javainterfaces) CVC4::JavaIteratorAdapter<CVC4::UnsatCore, CVC4::Expr> "java.util.Iterator<edu.stanford.CVC4.Expr>"; -// add some functions to the Java side (do it here because there's no way to do these in C++) -%typemap(javacode) CVC4::JavaIteratorAdapter<CVC4::UnsatCore, CVC4::Expr> " - public void remove() { - throw new java.lang.UnsupportedOperationException(); - } - - public edu.stanford.CVC4.Expr next() { - if(hasNext()) { - return getNext(); - } else { - throw new java.util.NoSuchElementException(); - } - } -" -// getNext() just allows C++ iterator access from Java-side next(), make it private -%javamethodmodifiers CVC4::JavaIteratorAdapter<CVC4::UnsatCore, CVC4::Expr>::getNext() "private"; - #endif /* SWIGJAVA */ %include "proof/unsat_core.h" #ifdef SWIGJAVA -%include <std_vector.i> - -%include "bindings/java_iterator_adapter.h" - +SWIG_JAVA_ITERATOR_ADAPTER(CVC4::UnsatCore, CVC4::Expr) %template(JavaIteratorAdapter_UnsatCore) CVC4::JavaIteratorAdapter<CVC4::UnsatCore, CVC4::Expr>; #endif /* SWIGJAVA */ diff --git a/src/prop/bv_sat_solver_notify.h b/src/prop/bv_sat_solver_notify.h index eca6bdfd6..6569c0394 100644 --- a/src/prop/bv_sat_solver_notify.h +++ b/src/prop/bv_sat_solver_notify.h @@ -2,9 +2,9 @@ /*! \file bv_sat_solver_notify.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Alex Ozdemir, Tim King + ** Liana Hadarean, Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/bvminisat/bvminisat.cpp b/src/prop/bvminisat/bvminisat.cpp index f1e2955da..c1aac33be 100644 --- a/src/prop/bvminisat/bvminisat.cpp +++ b/src/prop/bvminisat/bvminisat.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Dejan Jovanovic, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/bvminisat/bvminisat.h b/src/prop/bvminisat/bvminisat.h index f71dac3e5..01a0a518e 100644 --- a/src/prop/bvminisat/bvminisat.h +++ b/src/prop/bvminisat/bvminisat.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner, Liana Hadarean, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/cadical.cpp b/src/prop/cadical.cpp index 48116912b..ca447cea8 100644 --- a/src/prop/cadical.cpp +++ b/src/prop/cadical.cpp @@ -2,9 +2,9 @@ /*! \file cadical.cpp ** \verbatim ** Top contributors (to current version): - ** Mathias Preiner, Liana Hadarean + ** Mathias Preiner, Andres Noetzli, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/cadical.h b/src/prop/cadical.h index 1adbfc2d1..2545d0db0 100644 --- a/src/prop/cadical.h +++ b/src/prop/cadical.h @@ -2,9 +2,9 @@ /*! \file cadical.h ** \verbatim ** Top contributors (to current version): - ** Mathias Preiner, Liana Hadarean + ** Mathias Preiner, Aina Niemetz, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp index 73ae5c790..a6a4b6859 100644 --- a/src/prop/cnf_stream.cpp +++ b/src/prop/cnf_stream.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Liana Hadarean, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/cnf_stream.h b/src/prop/cnf_stream.h index 04ec91a68..40243e5b9 100644 --- a/src/prop/cnf_stream.h +++ b/src/prop/cnf_stream.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/cryptominisat.cpp b/src/prop/cryptominisat.cpp index 6ad67de04..cf23758f1 100644 --- a/src/prop/cryptominisat.cpp +++ b/src/prop/cryptominisat.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Mathias Preiner, Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/cryptominisat.h b/src/prop/cryptominisat.h index 25d6cce02..d60855654 100644 --- a/src/prop/cryptominisat.h +++ b/src/prop/cryptominisat.h @@ -2,9 +2,9 @@ /*! \file cryptominisat.h ** \verbatim ** Top contributors (to current version): - ** Mathias Preiner, Liana Hadarean, Dejan Jovanovic + ** Mathias Preiner, Liana Hadarean, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/minisat/minisat.cpp b/src/prop/minisat/minisat.cpp index 80d767b3d..a4d2dce8a 100644 --- a/src/prop/minisat/minisat.cpp +++ b/src/prop/minisat/minisat.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Dejan Jovanovic, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/minisat/minisat.h b/src/prop/minisat/minisat.h index f00bba000..947a27b3b 100644 --- a/src/prop/minisat/minisat.h +++ b/src/prop/minisat/minisat.h @@ -2,9 +2,9 @@ /*! \file minisat.h ** \verbatim ** Top contributors (to current version): - ** Mathias Preiner, Liana Hadarean, Tim King + ** Mathias Preiner, Liana Hadarean, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp index 3ea604f82..2bf425f2b 100644 --- a/src/prop/prop_engine.cpp +++ b/src/prop/prop_engine.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Dejan Jovanovic, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/prop_engine.h b/src/prop/prop_engine.h index 72ae52134..7f1d5ef65 100644 --- a/src/prop/prop_engine.h +++ b/src/prop/prop_engine.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Dejan Jovanovic, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/registrar.h b/src/prop/registrar.h index 0846b8829..51f08074e 100644 --- a/src/prop/registrar.h +++ b/src/prop/registrar.h @@ -2,9 +2,9 @@ /*! \file registrar.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Tim King, Morgan Deters + ** Mathias Preiner, Liana Hadarean, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/sat_solver.h b/src/prop/sat_solver.h index b9c518fd6..d4b08ab71 100644 --- a/src/prop/sat_solver.h +++ b/src/prop/sat_solver.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Liana Hadarean, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/sat_solver_factory.cpp b/src/prop/sat_solver_factory.cpp index 4a8d616ba..afd2a4c30 100644 --- a/src/prop/sat_solver_factory.cpp +++ b/src/prop/sat_solver_factory.cpp @@ -2,9 +2,9 @@ /*! \file sat_solver_factory.cpp ** \verbatim ** Top contributors (to current version): - ** Mathias Preiner, Liana Hadarean, Dejan Jovanovic + ** Mathias Preiner, Aina Niemetz, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/sat_solver_factory.h b/src/prop/sat_solver_factory.h index 04b5d73a6..c9ed207f9 100644 --- a/src/prop/sat_solver_factory.h +++ b/src/prop/sat_solver_factory.h @@ -2,9 +2,9 @@ /*! \file sat_solver_factory.h ** \verbatim ** Top contributors (to current version): - ** Mathias Preiner, Liana Hadarean, Morgan Deters + ** Mathias Preiner, Liana Hadarean, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/sat_solver_types.cpp b/src/prop/sat_solver_types.cpp index 078c5d54d..881086bf2 100644 --- a/src/prop/sat_solver_types.cpp +++ b/src/prop/sat_solver_types.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/sat_solver_types.h b/src/prop/sat_solver_types.h index 51d0c4cd5..83e9366fe 100644 --- a/src/prop/sat_solver_types.h +++ b/src/prop/sat_solver_types.h @@ -2,9 +2,9 @@ /*! \file sat_solver_types.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Liana Hadarean, Kshitij Bansal + ** Dejan Jovanovic, Alex Ozdemir, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/theory_proxy.cpp b/src/prop/theory_proxy.cpp index 38c99f551..41da4546e 100644 --- a/src/prop/theory_proxy.cpp +++ b/src/prop/theory_proxy.cpp @@ -2,9 +2,9 @@ /*! \file theory_proxy.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Liana Hadarean + ** Tim King, Kshitij Bansal, Guy Katz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/prop/theory_proxy.h b/src/prop/theory_proxy.h index 089d2082d..7fd735bf2 100644 --- a/src/prop/theory_proxy.h +++ b/src/prop/theory_proxy.h @@ -2,9 +2,9 @@ /*! \file theory_proxy.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Dejan Jovanovic + ** Dejan Jovanovic, Tim King, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/command.cpp b/src/smt/command.cpp index 20f2dcff9..095c59374 100644 --- a/src/smt/command.cpp +++ b/src/smt/command.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -23,6 +23,7 @@ #include <utility> #include <vector> +#include "api/cvc4cpp.h" #include "base/check.h" #include "base/output.h" #include "expr/expr_iomanip.h" @@ -134,7 +135,13 @@ std::ostream& operator<<(std::ostream& out, CommandPrintSuccess cps) /* class Command */ /* -------------------------------------------------------------------------- */ -Command::Command() : d_commandStatus(NULL), d_muted(false) {} +Command::Command() : d_commandStatus(nullptr), d_muted(false) {} + +Command::Command(api::Solver* solver) + : d_solver(solver), d_commandStatus(nullptr), d_muted(false) +{ +} + Command::Command(const Command& cmd) { d_commandStatus = @@ -599,48 +606,6 @@ std::string DeclareSygusVarCommand::getCommandName() const } /* -------------------------------------------------------------------------- */ -/* class DeclareSygusPrimedVarCommand */ -/* -------------------------------------------------------------------------- */ - -DeclareSygusPrimedVarCommand::DeclareSygusPrimedVarCommand( - const std::string& id, Type t) - : DeclarationDefinitionCommand(id), d_type(t) -{ -} - -Type DeclareSygusPrimedVarCommand::getType() const { return d_type; } - -void DeclareSygusPrimedVarCommand::invoke(SmtEngine* smtEngine) -{ - try - { - smtEngine->declareSygusPrimedVar(d_symbol, d_type); - d_commandStatus = CommandSuccess::instance(); - } - catch (exception& e) - { - d_commandStatus = new CommandFailure(e.what()); - } -} - -Command* DeclareSygusPrimedVarCommand::exportTo( - ExprManager* exprManager, ExprManagerMapCollection& variableMap) -{ - return new DeclareSygusPrimedVarCommand( - d_symbol, d_type.exportTo(exprManager, variableMap)); -} - -Command* DeclareSygusPrimedVarCommand::clone() const -{ - return new DeclareSygusPrimedVarCommand(d_symbol, d_type); -} - -std::string DeclareSygusPrimedVarCommand::getCommandName() const -{ - return "declare-primed-var"; -} - -/* -------------------------------------------------------------------------- */ /* class DeclareSygusFunctionCommand */ /* -------------------------------------------------------------------------- */ @@ -1266,22 +1231,27 @@ std::string DefineTypeCommand::getCommandName() const { return "define-sort"; } DefineFunctionCommand::DefineFunctionCommand(const std::string& id, Expr func, - Expr formula) + Expr formula, + bool global) : DeclarationDefinitionCommand(id), d_func(func), d_formals(), - d_formula(formula) + d_formula(formula), + d_global(global) { } DefineFunctionCommand::DefineFunctionCommand(const std::string& id, Expr func, const std::vector<Expr>& formals, - Expr formula) + Expr formula, + bool global) : DeclarationDefinitionCommand(id), d_func(func), d_formals(formals), - d_formula(formula) + d_formula(formula), + d_global(global) + { } @@ -1298,7 +1268,7 @@ void DefineFunctionCommand::invoke(SmtEngine* smtEngine) { if (!d_func.isNull()) { - smtEngine->defineFunction(d_func, d_formals, d_formula); + smtEngine->defineFunction(d_func, d_formals, d_formula, d_global); } d_commandStatus = CommandSuccess::instance(); } @@ -1319,12 +1289,13 @@ Command* DefineFunctionCommand::exportTo(ExprManager* exprManager, back_inserter(formals), ExportTransformer(exprManager, variableMap)); Expr formula = d_formula.exportTo(exprManager, variableMap); - return new DefineFunctionCommand(d_symbol, func, formals, formula); + return new DefineFunctionCommand(d_symbol, func, formals, formula, d_global); } Command* DefineFunctionCommand::clone() const { - return new DefineFunctionCommand(d_symbol, d_func, d_formals, d_formula); + return new DefineFunctionCommand( + d_symbol, d_func, d_formals, d_formula, d_global); } std::string DefineFunctionCommand::getCommandName() const @@ -1340,8 +1311,9 @@ DefineNamedFunctionCommand::DefineNamedFunctionCommand( const std::string& id, Expr func, const std::vector<Expr>& formals, - Expr formula) - : DefineFunctionCommand(id, func, formals, formula) + Expr formula, + bool global) + : DefineFunctionCommand(id, func, formals, formula, global) { } @@ -1365,12 +1337,14 @@ Command* DefineNamedFunctionCommand::exportTo( back_inserter(formals), ExportTransformer(exprManager, variableMap)); Expr formula = d_formula.exportTo(exprManager, variableMap); - return new DefineNamedFunctionCommand(d_symbol, func, formals, formula); + return new DefineNamedFunctionCommand( + d_symbol, func, formals, formula, d_global); } Command* DefineNamedFunctionCommand::clone() const { - return new DefineNamedFunctionCommand(d_symbol, d_func, d_formals, d_formula); + return new DefineNamedFunctionCommand( + d_symbol, d_func, d_formals, d_formula, d_global); } /* -------------------------------------------------------------------------- */ @@ -1378,7 +1352,12 @@ Command* DefineNamedFunctionCommand::clone() const /* -------------------------------------------------------------------------- */ DefineFunctionRecCommand::DefineFunctionRecCommand( - Expr func, const std::vector<Expr>& formals, Expr formula) + api::Solver* solver, + api::Term func, + const std::vector<api::Term>& formals, + api::Term formula, + bool global) + : Command(solver), d_global(global) { d_funcs.push_back(func); d_formals.push_back(formals); @@ -1386,27 +1365,31 @@ DefineFunctionRecCommand::DefineFunctionRecCommand( } DefineFunctionRecCommand::DefineFunctionRecCommand( - const std::vector<Expr>& funcs, - const std::vector<std::vector<Expr>>& formals, - const std::vector<Expr>& formulas) + api::Solver* solver, + const std::vector<api::Term>& funcs, + const std::vector<std::vector<api::Term>>& formals, + const std::vector<api::Term>& formulas, + bool global) + : Command(solver), + d_funcs(funcs), + d_formals(formals), + d_formulas(formulas), + d_global(global) { - d_funcs.insert(d_funcs.end(), funcs.begin(), funcs.end()); - d_formals.insert(d_formals.end(), formals.begin(), formals.end()); - d_formulas.insert(d_formulas.end(), formulas.begin(), formulas.end()); } -const std::vector<Expr>& DefineFunctionRecCommand::getFunctions() const +const std::vector<api::Term>& DefineFunctionRecCommand::getFunctions() const { return d_funcs; } -const std::vector<std::vector<Expr>>& DefineFunctionRecCommand::getFormals() - const +const std::vector<std::vector<api::Term>>& +DefineFunctionRecCommand::getFormals() const { return d_formals; } -const std::vector<Expr>& DefineFunctionRecCommand::getFormulas() const +const std::vector<api::Term>& DefineFunctionRecCommand::getFormulas() const { return d_formulas; } @@ -1415,7 +1398,7 @@ void DefineFunctionRecCommand::invoke(SmtEngine* smtEngine) { try { - smtEngine->defineFunctionsRec(d_funcs, d_formals, d_formulas); + d_solver->defineFunsRec(d_funcs, d_formals, d_formulas, d_global); d_commandStatus = CommandSuccess::instance(); } catch (exception& e) @@ -1427,35 +1410,13 @@ void DefineFunctionRecCommand::invoke(SmtEngine* smtEngine) Command* DefineFunctionRecCommand::exportTo( ExprManager* exprManager, ExprManagerMapCollection& variableMap) { - std::vector<Expr> funcs; - for (unsigned i = 0, size = d_funcs.size(); i < size; i++) - { - Expr func = d_funcs[i].exportTo( - exprManager, variableMap, /* flags = */ ExprManager::VAR_FLAG_DEFINED); - funcs.push_back(func); - } - std::vector<std::vector<Expr>> formals; - for (unsigned i = 0, size = d_formals.size(); i < size; i++) - { - std::vector<Expr> formals_c; - transform(d_formals[i].begin(), - d_formals[i].end(), - back_inserter(formals_c), - ExportTransformer(exprManager, variableMap)); - formals.push_back(formals_c); - } - std::vector<Expr> formulas; - for (unsigned i = 0, size = d_formulas.size(); i < size; i++) - { - Expr formula = d_formulas[i].exportTo(exprManager, variableMap); - formulas.push_back(formula); - } - return new DefineFunctionRecCommand(funcs, formals, formulas); + Unimplemented(); } Command* DefineFunctionRecCommand::clone() const { - return new DefineFunctionRecCommand(d_funcs, d_formals, d_formulas); + return new DefineFunctionRecCommand( + d_solver, d_funcs, d_formals, d_formulas, d_global); } std::string DefineFunctionRecCommand::getCommandName() const @@ -2130,6 +2091,90 @@ std::string GetSynthSolutionCommand::getCommandName() const return "get-instantiations"; } +GetInterpolCommand::GetInterpolCommand(api::Solver* solver, + const std::string& name, + api::Term conj) + : Command(solver), d_name(name), d_conj(conj), d_resultStatus(false) +{ +} +GetInterpolCommand::GetInterpolCommand(api::Solver* solver, + const std::string& name, + api::Term conj, + const Type& gtype) + : Command(solver), + d_name(name), + d_conj(conj), + d_sygus_grammar_type(gtype), + d_resultStatus(false) +{ +} + +api::Term GetInterpolCommand::getConjecture() const { return d_conj; } +Type GetInterpolCommand::getGrammarType() const { return d_sygus_grammar_type; } +api::Term GetInterpolCommand::getResult() const { return d_result; } + +void GetInterpolCommand::invoke(SmtEngine* smtEngine) +{ + try + { + if (d_sygus_grammar_type.isNull()) + { + d_resultStatus = d_solver->getInterpolant(d_conj, d_result); + } + else + { + d_resultStatus = + d_solver->getInterpolant(d_conj, d_sygus_grammar_type, d_result); + } + d_commandStatus = CommandSuccess::instance(); + } + catch (exception& e) + { + d_commandStatus = new CommandFailure(e.what()); + } +} + +void GetInterpolCommand::printResult(std::ostream& out, + uint32_t verbosity) const +{ + if (!ok()) + { + this->Command::printResult(out, verbosity); + } + else + { + expr::ExprDag::Scope scope(out, false); + if (d_resultStatus) + { + out << "(define-fun " << d_name << " () Bool " << d_result << ")" + << std::endl; + } + else + { + out << "none" << std::endl; + } + } +} + +Command* GetInterpolCommand::exportTo(ExprManager* exprManager, + ExprManagerMapCollection& variableMap) +{ + Unimplemented(); +} + +Command* GetInterpolCommand::clone() const +{ + GetInterpolCommand* c = new GetInterpolCommand(d_solver, d_name, d_conj); + c->d_result = d_result; + c->d_resultStatus = d_resultStatus; + return c; +} + +std::string GetInterpolCommand::getCommandName() const +{ + return "get-interpol"; +} + GetAbductCommand::GetAbductCommand() {} GetAbductCommand::GetAbductCommand(const std::string& name, Expr conj) : d_name(name), d_conj(conj), d_resultStatus(false) diff --git a/src/smt/command.h b/src/smt/command.h index 63f1f0f33..a6a0faaae 100644 --- a/src/smt/command.h +++ b/src/smt/command.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -28,6 +28,7 @@ #include <string> #include <vector> +#include "api/cvc4cpp.h" #include "expr/datatype.h" #include "expr/expr.h" #include "expr/type.h" @@ -39,6 +40,11 @@ namespace CVC4 { +namespace api { +class Solver; +class Term; +} // namespace api + class SmtEngine; class Command; class CommandStatus; @@ -186,27 +192,11 @@ class CVC4_PUBLIC CommandRecoverableFailure : public CommandStatus class CVC4_PUBLIC Command { - protected: - /** - * This field contains a command status if the command has been - * invoked, or NULL if it has not. This field is either a - * dynamically-allocated pointer, or it's a pointer to the singleton - * CommandSuccess instance. Doing so is somewhat asymmetric, but - * it avoids the need to dynamically allocate memory in the common - * case of a successful command. - */ - const CommandStatus* d_commandStatus; - - /** - * True if this command is "muted"---i.e., don't print "success" on - * successful execution. - */ - bool d_muted; - public: typedef CommandPrintSuccess printsuccess; Command(); + Command(api::Solver* solver); Command(const Command& cmd); virtual ~Command(); @@ -281,6 +271,25 @@ class CVC4_PUBLIC Command Expr operator()(Expr e) { return e.exportTo(d_exprManager, d_variableMap); } Type operator()(Type t) { return t.exportTo(d_exprManager, d_variableMap); } }; /* class Command::ExportTransformer */ + + /** The solver instance that this command is associated with. */ + api::Solver* d_solver; + + /** + * This field contains a command status if the command has been + * invoked, or NULL if it has not. This field is either a + * dynamically-allocated pointer, or it's a pointer to the singleton + * CommandSuccess instance. Doing so is somewhat asymmetric, but + * it avoids the need to dynamically allocate memory in the common + * case of a successful command. + */ + const CommandStatus* d_commandStatus; + + /** + * True if this command is "muted"---i.e., don't print "success" on + * successful execution. + */ + bool d_muted; }; /* class Command */ /** @@ -436,17 +445,16 @@ class CVC4_PUBLIC DefineTypeCommand : public DeclarationDefinitionCommand class CVC4_PUBLIC DefineFunctionCommand : public DeclarationDefinitionCommand { - protected: - Expr d_func; - std::vector<Expr> d_formals; - Expr d_formula; - public: - DefineFunctionCommand(const std::string& id, Expr func, Expr formula); + DefineFunctionCommand(const std::string& id, + Expr func, + Expr formula, + bool global); DefineFunctionCommand(const std::string& id, Expr func, const std::vector<Expr>& formals, - Expr formula); + Expr formula, + bool global); Expr getFunction() const; const std::vector<Expr>& getFormals() const; @@ -457,6 +465,19 @@ class CVC4_PUBLIC DefineFunctionCommand : public DeclarationDefinitionCommand ExprManagerMapCollection& variableMap) override; Command* clone() const override; std::string getCommandName() const override; + + protected: + /** The function we are defining */ + Expr d_func; + /** The formal arguments for the function we are defining */ + std::vector<Expr> d_formals; + /** The formula corresponding to the body of the function we are defining */ + Expr d_formula; + /** + * Stores whether this definition is global (i.e. should persist when + * popping the user context. + */ + bool d_global; }; /* class DefineFunctionCommand */ /** @@ -470,7 +491,8 @@ class CVC4_PUBLIC DefineNamedFunctionCommand : public DefineFunctionCommand DefineNamedFunctionCommand(const std::string& id, Expr func, const std::vector<Expr>& formals, - Expr formula); + Expr formula, + bool global); void invoke(SmtEngine* smtEngine) override; Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) override; @@ -485,16 +507,20 @@ class CVC4_PUBLIC DefineNamedFunctionCommand : public DefineFunctionCommand class CVC4_PUBLIC DefineFunctionRecCommand : public Command { public: - DefineFunctionRecCommand(Expr func, - const std::vector<Expr>& formals, - Expr formula); - DefineFunctionRecCommand(const std::vector<Expr>& funcs, - const std::vector<std::vector<Expr> >& formals, - const std::vector<Expr>& formula); - - const std::vector<Expr>& getFunctions() const; - const std::vector<std::vector<Expr> >& getFormals() const; - const std::vector<Expr>& getFormulas() const; + DefineFunctionRecCommand(api::Solver* solver, + api::Term func, + const std::vector<api::Term>& formals, + api::Term formula, + bool global); + DefineFunctionRecCommand(api::Solver* solver, + const std::vector<api::Term>& funcs, + const std::vector<std::vector<api::Term> >& formals, + const std::vector<api::Term>& formula, + bool global); + + const std::vector<api::Term>& getFunctions() const; + const std::vector<std::vector<api::Term> >& getFormals() const; + const std::vector<api::Term>& getFormulas() const; void invoke(SmtEngine* smtEngine) override; Command* exportTo(ExprManager* exprManager, @@ -504,11 +530,16 @@ class CVC4_PUBLIC DefineFunctionRecCommand : public Command protected: /** functions we are defining */ - std::vector<Expr> d_funcs; + std::vector<api::Term> d_funcs; /** formal arguments for each of the functions we are defining */ - std::vector<std::vector<Expr> > d_formals; + std::vector<std::vector<api::Term> > d_formals; /** formulas corresponding to the bodies of the functions we are defining */ - std::vector<Expr> d_formulas; + std::vector<api::Term> d_formulas; + /** + * Stores whether this definition is global (i.e. should persist when + * popping the user context. + */ + bool d_global; }; /* class DefineFunctionRecCommand */ /** @@ -645,38 +676,6 @@ class CVC4_PUBLIC DeclareSygusVarCommand : public DeclarationDefinitionCommand Type d_type; }; -/** Declares a sygus primed variable, for invariant problems - * - * We do not actually build expressions for the declared variables because they - * are unnecessary for building SyGuS problems. - */ -class CVC4_PUBLIC DeclareSygusPrimedVarCommand - : public DeclarationDefinitionCommand -{ - public: - DeclareSygusPrimedVarCommand(const std::string& id, Type type); - /** returns the declared primed variable's type */ - Type getType() const; - - /** invokes this command - * - * The type of the primed variable is communicated to the SMT engine for - * debugging purposes when a synthesis conjecture is built later on. - */ - void invoke(SmtEngine* smtEngine) override; - /** exports command to given expression manager */ - Command* exportTo(ExprManager* exprManager, - ExprManagerMapCollection& variableMap) override; - /** creates a copy of this command */ - Command* clone() const override; - /** returns this command's name */ - std::string getCommandName() const override; - - protected: - /** the type of the declared primed variable */ - Type d_type; -}; - /** Declares a sygus universal function variable */ class CVC4_PUBLIC DeclareSygusFunctionCommand : public DeclarationDefinitionCommand @@ -1040,6 +1039,58 @@ class CVC4_PUBLIC GetSynthSolutionCommand : public Command SmtEngine* d_smtEngine; }; /* class GetSynthSolutionCommand */ +/** The command (get-interpol s B) + * + * This command asks for an interpolant from the current set of assertions and + * conjecture (goal) B. + * + * The symbol s is the name for the interpolation predicate. If we successfully + * find a predicate P, then the output response of this command is: (define-fun + * s () Bool P) + */ +class CVC4_PUBLIC GetInterpolCommand : public Command +{ + public: + GetInterpolCommand(api::Solver* solver, + const std::string& name, + api::Term conj); + /** The argument gtype is the grammar of the interpolation query */ + GetInterpolCommand(api::Solver* solver, + const std::string& name, + api::Term conj, + const Type& gtype); + + /** Get the conjecture of the interpolation query */ + api::Term getConjecture() const; + /** Get the grammar sygus datatype type given for the interpolation query */ + Type getGrammarType() const; + /** Get the result of the query, which is the solution to the interpolation + * query. */ + api::Term getResult() const; + + void invoke(SmtEngine* smtEngine) override; + void printResult(std::ostream& out, uint32_t verbosity = 2) const override; + Command* exportTo(ExprManager* exprManager, + ExprManagerMapCollection& variableMap) override; + Command* clone() const override; + std::string getCommandName() const override; + + protected: + /** The name of the interpolation predicate */ + std::string d_name; + /** The conjecture of the interpolation query */ + api::Term d_conj; + /** + * The (optional) grammar of the interpolation query, expressed as a sygus + * datatype type. + */ + Type d_sygus_grammar_type; + /** the return status of the command */ + bool d_resultStatus; + /** the return expression of the command */ + api::Term d_result; +}; /* class GetInterpolCommand */ + /** The command (get-abduct s B (G)?) * * This command asks for an abduct from the current set of assertions and diff --git a/src/smt/command_list.cpp b/src/smt/command_list.cpp index 43bb6b268..a88efbbec 100644 --- a/src/smt/command_list.cpp +++ b/src/smt/command_list.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/command_list.h b/src/smt/command_list.h index 0b1aaecf2..cdc8e4c22 100644 --- a/src/smt/command_list.h +++ b/src/smt/command_list.h @@ -2,9 +2,9 @@ /*! \file command_list.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/defined_function.h b/src/smt/defined_function.h index b141ef9cb..afac2df58 100644 --- a/src/smt/defined_function.h +++ b/src/smt/defined_function.h @@ -2,7 +2,7 @@ /*! \file defined_function.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. diff --git a/src/smt/dump.cpp b/src/smt/dump.cpp index 823e1900d..d8d486e12 100644 --- a/src/smt/dump.cpp +++ b/src/smt/dump.cpp @@ -2,9 +2,9 @@ /*! \file dump.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Clark Barrett, Tim King + ** Andres Noetzli, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/dump.h b/src/smt/dump.h index fc2452423..050935422 100644 --- a/src/smt/dump.h +++ b/src/smt/dump.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andres Noetzli, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/logic_exception.h b/src/smt/logic_exception.h index e5da2a6e8..109d49c06 100644 --- a/src/smt/logic_exception.h +++ b/src/smt/logic_exception.h @@ -2,9 +2,9 @@ /*! \file logic_exception.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/logic_request.cpp b/src/smt/logic_request.cpp index c24378cb1..486ac829d 100644 --- a/src/smt/logic_request.cpp +++ b/src/smt/logic_request.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner, Martin Brain, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/logic_request.h b/src/smt/logic_request.h index 432d5469c..b1822d0a1 100644 --- a/src/smt/logic_request.h +++ b/src/smt/logic_request.h @@ -2,9 +2,9 @@ /*! \file logic_request.h ** \verbatim ** Top contributors (to current version): - ** Martin Brain, Tim King, Mathias Preiner + ** Martin Brain, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/managed_ostreams.cpp b/src/smt/managed_ostreams.cpp index 7615325b7..12f98aa95 100644 --- a/src/smt/managed_ostreams.cpp +++ b/src/smt/managed_ostreams.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/managed_ostreams.h b/src/smt/managed_ostreams.h index bc12bbe39..577ef3226 100644 --- a/src/smt/managed_ostreams.h +++ b/src/smt/managed_ostreams.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/model.cpp b/src/smt/model.cpp index c6048da15..6f6a09f38 100644 --- a/src/smt/model.cpp +++ b/src/smt/model.cpp @@ -2,9 +2,9 @@ /*! \file model.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Andrew Reynolds + ** Morgan Deters, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/model.h b/src/smt/model.h index 3ff63e915..1f7c5daae 100644 --- a/src/smt/model.h +++ b/src/smt/model.h @@ -2,9 +2,9 @@ /*! \file model.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/model_blocker.cpp b/src/smt/model_blocker.cpp index 6e73a61b3..7a34cd928 100644 --- a/src/smt/model_blocker.cpp +++ b/src/smt/model_blocker.cpp @@ -2,9 +2,9 @@ /*! \file model_blocker.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/model_blocker.h b/src/smt/model_blocker.h index 7fc4788bb..ef4c6e700 100644 --- a/src/smt/model_blocker.h +++ b/src/smt/model_blocker.h @@ -2,9 +2,9 @@ /*! \file model_blocker.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/model_core_builder.cpp b/src/smt/model_core_builder.cpp index 3007821e5..08f0b29c3 100644 --- a/src/smt/model_core_builder.cpp +++ b/src/smt/model_core_builder.cpp @@ -2,9 +2,9 @@ /*! \file model_core_builder.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Mathias Preiner, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/model_core_builder.h b/src/smt/model_core_builder.h index 2390d61ca..2897ce728 100644 --- a/src/smt/model_core_builder.h +++ b/src/smt/model_core_builder.h @@ -2,9 +2,9 @@ /*! \file model_core_builder.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/process_assertions.cpp b/src/smt/process_assertions.cpp index 0e2701a1a..44944d0c2 100644 --- a/src/smt/process_assertions.cpp +++ b/src/smt/process_assertions.cpp @@ -2,9 +2,9 @@ /*! \file process_assertions.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andrew Reynolds, Tim King + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/process_assertions.h b/src/smt/process_assertions.h index ddf5a6cba..4850d5589 100644 --- a/src/smt/process_assertions.h +++ b/src/smt/process_assertions.h @@ -2,9 +2,9 @@ /*! \file process_assertions.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/set_defaults.cpp b/src/smt/set_defaults.cpp index e06363883..a7e8e6212 100644 --- a/src/smt/set_defaults.cpp +++ b/src/smt/set_defaults.cpp @@ -2,9 +2,9 @@ /*! \file set_defaults.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -266,12 +266,35 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic) << std::endl; } } + // !!!!!!!!!!!!!!!! temporary, to support CI check for old proof system + if (options::proof()) + { + options::proofNew.set(false); + } + + if (options::arraysExp()) + { + if (!logic.isQuantified()) + { + logic = logic.getUnlockedCopy(); + logic.enableQuantifiers(); + logic.lock(); + } + // Allows to answer sat more often by default. + if (!options::fmfBound.wasSetByUser()) + { + options::fmfBound.set(true); + Trace("smt") << "turning on fmf-bound, for arrays-exp" << std::endl; + } + } // sygus inference may require datatypes if (!smte.isInternalSubsolver()) { - if (options::produceAbducts() || options::sygusInference() - || options::sygusRewSynthInput() || options::sygusInst()) + if (options::produceAbducts() + || options::produceInterpols() != options::ProduceInterpols::NONE + || options::sygusInference() || options::sygusRewSynthInput() + || options::sygusInst()) { // since we are trying to recast as sygus, we assume the input is sygus is_sygus = true; @@ -295,6 +318,7 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic) if ((options::checkModels() || options::checkSynthSol() || options::produceAbducts() + || options::produceInterpols() != options::ProduceInterpols::NONE || options::modelCoresMode() != options::ModelCoresMode::NONE || options::blockModelsMode() != options::BlockModelsMode::NONE) && !options::produceAssertions()) @@ -357,6 +381,18 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic) } } + + if (options::solveBVAsInt() > 0) + { + /** + * Operations on 1 bits are better handled as Boolean operations + * than as integer operations. + * Therefore, we enable bv-to-bool, which runs before + * the translation to integers. + */ + options::bitvectorToBool.set(true); + } + // Disable options incompatible with unsat cores and proofs or output an // error if enabled explicitly if (options::unsatCores() || options::proof()) @@ -413,16 +449,6 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic) options::preSkolemQuant.set(false); } - if (options::solveBVAsInt() > 0) - { - /** - * Operations on 1 bits are better handled as Boolean operations - * than as integer operations. - * Therefore, we enable bv-to-bool, which runs before - * the translation to integers. - */ - options::bitvectorToBool.set(true); - } if (options::bitvectorToBool()) { @@ -538,18 +564,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 +623,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()) { @@ -875,6 +901,16 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic) } if (options::ufHo()) { + // if higher-order, disable proof production + if (options::proofNew()) + { + if (options::proofNew.wasSetByUser()) + { + Warning() << "SmtEngine: turning off proof production (not yet " + "supported with --uf-ho)\n"; + } + options::proofNew.set(false); + } // if higher-order, then current variants of model-based instantiation // cannot be used if (options::mbqiMode() != options::MbqiMode::NONE) @@ -1106,6 +1142,16 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic) { options::cegqiPreRegInst.set(true); } + // not compatible with proofs + if (options::proofNew()) + { + if (options::proofNew.wasSetByUser()) + { + Notice() << "SmtEngine: setting proof-new to false to support SyGuS" + << std::endl; + } + options::proofNew.set(false); + } } // counterexample-guided instantiation for non-sygus // enable if any possible quantifiers with arithmetic, datatypes or bitvectors @@ -1161,11 +1207,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()) { @@ -1402,12 +1445,6 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic) disableModels = true; sOptNoModel = "minisat-elimination"; } - else if (logic.isTheoryEnabled(THEORY_ARITH) && !logic.isLinear() - && !options::nlExt()) - { - disableModels = true; - sOptNoModel = "nonlinear arithmetic without nl-ext"; - } else if (options::globalNegate()) { disableModels = true; @@ -1465,6 +1502,11 @@ void setDefaults(SmtEngine& smte, LogicInfo& logic) "division. " "Try --bv-div-zero-const to interpret division by zero as a constant."); } + // !!!!!!!!!!!!!!!! temporary, until proof-new is functional + if (options::proofNew()) + { + throw OptionException("--proof-new is not yet supported."); + } } } // namespace smt diff --git a/src/smt/set_defaults.h b/src/smt/set_defaults.h index 8871b0b38..f3ec21c9b 100644 --- a/src/smt/set_defaults.h +++ b/src/smt/set_defaults.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp index 3c0a2cd8f..bb4d82fe0 100644 --- a/src/smt/smt_engine.cpp +++ b/src/smt/smt_engine.cpp @@ -2,9 +2,9 @@ /*! \file smt_engine.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andrew Reynolds, Tim King + ** Andrew Reynolds, Morgan Deters, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -29,6 +29,7 @@ #include <utility> #include <vector> +#include "api/cvc4cpp.h" #include "base/check.h" #include "base/configuration.h" #include "base/configuration_private.h" @@ -759,6 +760,7 @@ void SmtEngine::finishInit() // In the case of incremental solving, we appear to need these to // ensure the relevant Nodes remain live. d_assertionList = new (true) AssertionList(getUserContext()); + d_globalDefineFunRecLemmas.reset(new std::vector<Node>()); } // dump out a set-logic command only when raw-benchmark is disabled to avoid @@ -847,6 +849,8 @@ SmtEngine::~SmtEngine() d_assignments->deleteSelf(); } + d_globalDefineFunRecLemmas.reset(); + if(d_assertionList != NULL) { d_assertionList->deleteSelf(); } @@ -903,6 +907,7 @@ void SmtEngine::setLogic(const LogicInfo& logic) "finished initializing."); } d_logic = logic; + d_userLogic = logic; setLogicInternal(); } @@ -929,6 +934,14 @@ void SmtEngine::setLogic(const char* logic) { setLogic(string(logic)); } LogicInfo SmtEngine::getLogicInfo() const { return d_logic; } +LogicInfo SmtEngine::getUserLogicInfo() const +{ + // Lock the logic to make sure that this logic can be queried. We create a + // copy of the user logic here to keep this method const. + LogicInfo res = d_userLogic; + res.lock(); + return res; +} void SmtEngine::setFilename(std::string filename) { d_filename = filename; } std::string SmtEngine::getFilename() const { return d_filename; } void SmtEngine::setLogicInternal() @@ -937,6 +950,7 @@ void SmtEngine::setLogicInternal() << "setting logic in SmtEngine but the engine has already" " finished initializing for this run"; d_logic.lock(); + d_userLogic.lock(); } void SmtEngine::setProblemExtended() @@ -1022,72 +1036,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) @@ -1141,7 +1193,8 @@ void SmtEngine::debugCheckFunctionBody(Expr formula, void SmtEngine::defineFunction(Expr func, const std::vector<Expr>& formals, - Expr formula) + Expr formula, + bool global) { SmtScope smts(this); finalOptionsAreSet(); @@ -1153,7 +1206,7 @@ void SmtEngine::defineFunction(Expr func, ss << language::SetLanguage( language::SetLanguage::getLanguage(Dump.getStream())) << func; - DefineFunctionCommand c(ss.str(), func, formals, formula); + DefineFunctionCommand c(ss.str(), func, formals, formula, global); addToModelCommandAndDump( c, ExprManager::VAR_FLAG_DEFINED, true, "declarations"); @@ -1182,13 +1235,22 @@ void SmtEngine::defineFunction(Expr func, // Otherwise, (check-sat) (get-value ((! foo :named bar))) breaks // d_haveAdditions = true; Debug("smt") << "definedFunctions insert " << funcNode << " " << formNode << endl; - d_definedFunctions->insert(funcNode, def); + + if (global) + { + d_definedFunctions->insertAtContextLevelZero(funcNode, def); + } + else + { + d_definedFunctions->insert(funcNode, def); + } } void SmtEngine::defineFunctionsRec( const std::vector<Expr>& funcs, - const std::vector<std::vector<Expr> >& formals, - const std::vector<Expr>& formulas) + const std::vector<std::vector<Expr>>& formals, + const std::vector<Expr>& formulas, + bool global) { SmtScope smts(this); finalOptionsAreSet(); @@ -1216,7 +1278,16 @@ void SmtEngine::defineFunctionsRec( if (Dump.isOn("raw-benchmark")) { - Dump("raw-benchmark") << DefineFunctionRecCommand(funcs, formals, formulas); + std::vector<api::Term> tFuncs = api::exprVectorToTerms(d_solver, funcs); + std::vector<std::vector<api::Term>> tFormals; + for (const std::vector<Expr>& formal : formals) + { + tFormals.emplace_back(api::exprVectorToTerms(d_solver, formal)); + } + std::vector<api::Term> tFormulas = + api::exprVectorToTerms(d_solver, formulas); + Dump("raw-benchmark") << DefineFunctionRecCommand( + d_solver, tFuncs, tFormals, tFormulas, global); } ExprManager* em = getExprManager(); @@ -1256,17 +1327,28 @@ void SmtEngine::defineFunctionsRec( // notice we don't call assertFormula directly, since this would // duplicate the output on raw-benchmark. Expr e = d_private->substituteAbstractValues(Node::fromExpr(lem)).toExpr(); - if (d_assertionList != NULL) + if (d_assertionList != nullptr) { d_assertionList->push_back(e); } - d_private->addFormula(e.getNode(), false, true, false, maybeHasFv); + if (global && d_globalDefineFunRecLemmas != nullptr) + { + // Global definitions are asserted at check-sat-time because we have to + // make sure that they are always present + Assert(!language::isInputLangSygus(options::inputLanguage())); + d_globalDefineFunRecLemmas->emplace_back(Node::fromExpr(e)); + } + else + { + d_private->addFormula(e.getNode(), false, true, false, maybeHasFv); + } } } void SmtEngine::defineFunctionRec(Expr func, const std::vector<Expr>& formals, - Expr formula) + Expr formula, + bool global) { std::vector<Expr> funcs; funcs.push_back(func); @@ -1274,7 +1356,7 @@ void SmtEngine::defineFunctionRec(Expr func, formals_multi.push_back(formals); std::vector<Expr> formulas; formulas.push_back(formula); - defineFunctionsRec(funcs, formals_multi, formulas); + defineFunctionsRec(funcs, formals_multi, formulas, global); } bool SmtEngine::isDefinedFunction( Expr func ){ @@ -1614,6 +1696,17 @@ Result SmtEngine::checkSatisfiability(const vector<Expr>& assumptions, d_private->addFormula(e.getNode(), inUnsatCore, true, true); } + if (d_globalDefineFunRecLemmas != nullptr) + { + // Global definitions are asserted at check-sat-time because we have to + // make sure that they are always present (they are essentially level + // zero assertions) + for (const Node& lemma : *d_globalDefineFunRecLemmas) + { + d_private->addFormula(lemma, false, true, false, false); + } + } + r = check(); if ((options::solveRealAsInt() || options::solveIntAsBV() > 0) @@ -1780,15 +1873,6 @@ void SmtEngine::declareSygusVar(const std::string& id, Expr var, Type type) // don't need to set that the conjecture is stale } -void SmtEngine::declareSygusPrimedVar(const std::string& id, Type type) -{ - SmtScope smts(this); - finalOptionsAreSet(); - // do nothing (the command is spurious) - Trace("smt") << "SmtEngine::declareSygusPrimedVar: " << id << "\n"; - // don't need to set that the conjecture is stale -} - void SmtEngine::declareSygusFunctionVar(const std::string& id, Expr var, Type type) @@ -2850,6 +2934,12 @@ void SmtEngine::checkSynthSolution() } } +void SmtEngine::checkInterpol(Expr interpol, + const std::vector<Expr>& easserts, + const Node& conj) +{ +} + void SmtEngine::checkAbduct(Expr a) { Assert(a.getType().isBoolean()); @@ -3068,6 +3158,19 @@ Expr SmtEngine::doQuantifierElimination(const Expr& e, bool doFull, bool strict) } } +bool SmtEngine::getInterpol(const Expr& conj, + const Type& grammarType, + Expr& interpol) +{ + return false; +} + +bool SmtEngine::getInterpol(const Expr& conj, Expr& interpol) +{ + Type grammarType; + return getInterpol(conj, grammarType, interpol); +} + bool SmtEngine::getAbduct(const Expr& conj, const Type& grammarType, Expr& abd) { SmtScope smts(this); diff --git a/src/smt/smt_engine.h b/src/smt/smt_engine.h index 672bec821..afb39b41b 100644 --- a/src/smt/smt_engine.h +++ b/src/smt/smt_engine.h @@ -2,9 +2,9 @@ /*! \file smt_engine.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andrew Reynolds, Haniel Barbosa + ** Morgan Deters, Andrew Reynolds, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -65,6 +65,12 @@ class StatisticsRegistry; /* -------------------------------------------------------------------------- */ +namespace api { +class Solver; +} // namespace api + +/* -------------------------------------------------------------------------- */ + namespace context { class Context; class UserContext; @@ -126,6 +132,7 @@ namespace theory { class CVC4_PUBLIC SmtEngine { + friend class ::CVC4::api::Solver; // TODO (Issue #1096): Remove this friend relationship. friend class ::CVC4::preprocessing::PreprocessingPassContext; friend class ::CVC4::smt::SmtEnginePrivate; @@ -141,6 +148,29 @@ 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, + // immediately after a successful call to get-interpol + SMT_MODE_INTERPOL + }; + /** Construct an SmtEngine with the given expression manager. */ SmtEngine(ExprManager* em); /** Destruct the SMT engine. */ @@ -162,6 +192,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 @@ -183,12 +216,18 @@ class CVC4_PUBLIC SmtEngine /** Get the logic information currently set. */ LogicInfo getLogicInfo() const; + /** Get the logic information set by the user. */ + LogicInfo getUserLogicInfo() const; + /** * Set information about the script executing. * @throw OptionException, ModalException */ 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; @@ -263,15 +302,18 @@ class CVC4_PUBLIC SmtEngine * (lambda (formals) formula) * This adds func to the list of defined functions, which indicates that * all occurrences of func should be expanded during expandDefinitions. - * This method expects input such that: - * - func : a variable of function type that expects the arguments in - * formals, - * - formals : a list of BOUND_VARIABLE expressions, - * - formula does not contain func. + * + * @param func a variable of function type that expects the arguments in + * formal + * @param formals a list of BOUND_VARIABLE expressions + * @param formula The body of the function, must not contain func + * @param global True if this definition is global (i.e. should persist when + * popping the user context) */ void defineFunction(Expr func, const std::vector<Expr>& formals, - Expr formula); + Expr formula, + bool global = false); /** Return true if given expression is a defined function. */ bool isDefinedFunction(Expr func); @@ -290,17 +332,22 @@ class CVC4_PUBLIC SmtEngine * - func[i] : a variable of function type that expects the arguments in * formals[i], and * - formals[i] : a list of BOUND_VARIABLE expressions. + * + * @param global True if this definition is global (i.e. should persist when + * popping the user context) */ void defineFunctionsRec(const std::vector<Expr>& funcs, - const std::vector<std::vector<Expr> >& formals, - const std::vector<Expr>& formulas); + const std::vector<std::vector<Expr>>& formals, + const std::vector<Expr>& formulas, + bool global = false); /** * Define function recursive * Same as above, but for a single function. */ void defineFunctionRec(Expr func, const std::vector<Expr>& formals, - Expr formula); + Expr formula, + bool global = false); /** * Add a formula to the current context: preprocess, do per-theory * setup, use processAssertionList(), asserting to T-solver for @@ -359,16 +406,6 @@ class CVC4_PUBLIC SmtEngine void declareSygusVar(const std::string& id, Expr var, Type type); /** - * Store information for debugging sygus invariants setup. - * - * Since in SyGuS the commands "declare-primed-var" are not necessary for - * building invariant constraints, we only use them to check that the number - * of variables declared corresponds to the number of arguments of the - * invariant-to-synthesize. - */ - void declareSygusPrimedVar(const std::string& id, Type type); - - /** * Add a function variable declaration. * * Is SyGuS semantics declared functions are treated in the same manner as @@ -584,6 +621,23 @@ class CVC4_PUBLIC SmtEngine Expr doQuantifierElimination(const Expr& e, bool doFull, bool strict = true); /** + * This method asks this SMT engine to find an interpolant with respect to + * the current assertion stack (call it A) and the conjecture (call it B). If + * this method returns true, then interpolant is set to a formula I such that + * A ^ ~I and I ^ ~B are both unsatisfiable. + * + * The argument grammarType is a sygus datatype type that encodes the syntax + * restrictions on the shapes of possible solutions. + * + * This method invokes a separate copy of the SMT engine for solving the + * corresponding sygus problem for generating such a solution. + */ + bool getInterpol(const Expr& conj, const Type& grammarType, Expr& interpol); + + /** Same as above, but without user-provided grammar restrictions */ + bool getInterpol(const Expr& conj, Expr& interpol); + + /** * This method asks this SMT engine to find an abduct with respect to the * current assertion stack (call it A) and the conjecture (call it B). * If this method returns true, then abd is set to a formula C such that @@ -835,34 +889,14 @@ class CVC4_PUBLIC SmtEngine typedef context::CDList<Expr> AssertionList; /** The type of our internal assignment set */ typedef context::CDHashSet<Node, NodeHashFunction> AssignmentSet; - /** 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; + /** Set solver instance that owns this SmtEngine. */ + void setSolver(api::Solver* solver) { d_solver = solver; } + /** Get a pointer to the TheoryEngine owned by this SmtEngine. */ TheoryEngine* getTheoryEngine() { return d_theoryEngine.get(); } @@ -920,6 +954,18 @@ class CVC4_PUBLIC SmtEngine * unsatisfiable. If not, then the found solutions are wrong. */ void checkSynthSolution(); + + /** + * Check that a solution to an interpolation problem is indeed a solution. + * + * The check is made by determining that the assertions imply the solution of + * the interpolation problem (interpol), and the solution implies the goal + * (conj). If these criteria are not met, an internal error is thrown. + */ + void checkInterpol(Expr interpol, + const std::vector<Expr>& easserts, + const Node& conj); + /** * Check that a solution to an abduction conjecture is indeed a solution. * @@ -1043,6 +1089,7 @@ class CVC4_PUBLIC SmtEngine void debugCheckFunctionBody(Expr formula, const std::vector<Expr>& formals, Expr func); + /** * Get abduct internal. * @@ -1070,6 +1117,9 @@ class CVC4_PUBLIC SmtEngine /* Members -------------------------------------------------------------- */ + /** Solver instance that owns this SmtEngine instance. */ + api::Solver* d_solver = nullptr; + /** Expr manager context */ std::unique_ptr<context::Context> d_context; /** User level context */ @@ -1133,11 +1183,17 @@ class CVC4_PUBLIC SmtEngine /** * The assertion list (before any conversion) for supporting - * getAssertions(). Only maintained if in interactive mode. + * getAssertions(). Only maintained if in incremental mode. */ AssertionList* d_assertionList; /** + * List of lemmas generated for global recursive function definitions. We + * assert this list of definitions in each check-sat call. + */ + std::unique_ptr<std::vector<Node>> d_globalDefineFunRecLemmas; + + /** * The list of assumptions from the previous call to checkSatisfiability. * Note that if the last call to checkSatisfiability was an entailment check, * i.e., a call to checkEntailed(a1, ..., an), then d_assumptions contains @@ -1179,10 +1235,14 @@ class CVC4_PUBLIC SmtEngine std::vector<Command*> d_defineCommands; /** - * The logic we're in. + * The logic we're in. This logic may be an extension of the logic set by the + * user. */ LogicInfo d_logic; + /** The logic set by the user. */ + LogicInfo d_userLogic; + /** * Keep a copy of the original option settings (for reset()). */ diff --git a/src/smt/smt_engine.i b/src/smt/smt_engine.i index 635e593bb..95a5f4f3b 100644 --- a/src/smt/smt_engine.i +++ b/src/smt/smt_engine.i @@ -3,51 +3,33 @@ %} #ifdef SWIGJAVA + %typemap(javacode) CVC4::SmtEngine %{ // a ref is kept here to keep Java GC from collecting the EM // before the SmtEngine - private Object emRef; - static final native Object mkRef(Object obj); - static final native void dlRef(Object obj); + private ExprManager em; %} -%native (mkRef) jobject SmtEngine::mkRef(jobject); -%native (dlRef) void SmtEngine::dlRef(jobject); -%{ -extern "C" { -SWIGEXPORT jobject JNICALL Java_edu_stanford_CVC4_SmtEngine_mkRef(JNIEnv* jenv, jclass jcls, jobject o) { - if(o == NULL) { - return NULL; - } - return jenv->NewGlobalRef(o); + +%typemap(javaconstruct) SmtEngine { + this($imcall, true); + this.em = em; // keep ref to expr manager in SWIG proxy class } -SWIGEXPORT void JNICALL Java_edu_stanford_CVC4_SmtEngine_dlRef(JNIEnv* jenv, jclass jcls, jobject o) { - if(o != NULL) { - jenv->DeleteGlobalRef(o); - } + +%typemap(javaout) CVC4::Expr { + return new Expr(this.em, $jnicall, true); } + +%typemap(javaout) CVC4::UnsatCore { + return new UnsatCore(this.em, $jnicall, true); } -%} -%typemap(javaconstruct) SmtEngine { - this($imcall, true); - emRef = mkRef(em); // keep ref to expr manager in SWIG proxy class - } -%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") CVC4::SmtEngine { - dlRef(emRef); - emRef = null; - if (swigCPtr != 0) { - if (swigCMemOwn) { - swigCMemOwn = false; - CVC4JNI.delete_SmtEngine(swigCPtr); - } - swigCPtr = 0; - } - } - -%template(Map_ExprExpr) std::map<CVC4::Expr, CVC4::Expr>; + +// %template(Map_ExprExpr) std::map<CVC4::Expr, CVC4::Expr>; +%ignore CVC4::SmtEngine::getSynthSolutions(std::map<Expr, Expr>& sol_map); #endif // SWIGJAVA %ignore CVC4::SmtEngine::setLogic(const char*); +%ignore CVC4::SmtEngine::setReplayStream(ExprStream* exprStream); %ignore CVC4::smt::currentProofManager(); %include "smt/smt_engine.h" diff --git a/src/smt/smt_engine_scope.cpp b/src/smt/smt_engine_scope.cpp index 55af4bfd2..7c438073a 100644 --- a/src/smt/smt_engine_scope.cpp +++ b/src/smt/smt_engine_scope.cpp @@ -2,9 +2,9 @@ /*! \file smt_engine_scope.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli, Tim King + ** Andres Noetzli, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/smt_engine_scope.h b/src/smt/smt_engine_scope.h index d72d58caa..012c2ec31 100644 --- a/src/smt/smt_engine_scope.h +++ b/src/smt/smt_engine_scope.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andres Noetzli, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/smt_engine_stats.cpp b/src/smt/smt_engine_stats.cpp index c45f77b9b..964237499 100644 --- a/src/smt/smt_engine_stats.cpp +++ b/src/smt/smt_engine_stats.cpp @@ -2,7 +2,7 @@ /*! \file smt_engine_stats.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Tim King, Andres Noetzli, Morgan Deters ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. diff --git a/src/smt/smt_engine_stats.h b/src/smt/smt_engine_stats.h index cebf85d95..3ea46eaa4 100644 --- a/src/smt/smt_engine_stats.h +++ b/src/smt/smt_engine_stats.h @@ -2,7 +2,7 @@ /*! \file smt_engine_stats.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Morgan Deters, Andrew Reynolds, Liana Hadarean ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. diff --git a/src/smt/smt_statistics_registry.cpp b/src/smt/smt_statistics_registry.cpp index 1912b0eb2..7191da012 100644 --- a/src/smt/smt_statistics_registry.cpp +++ b/src/smt/smt_statistics_registry.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/smt_statistics_registry.h b/src/smt/smt_statistics_registry.h index 1a0993d1d..c54e881f5 100644 --- a/src/smt/smt_statistics_registry.h +++ b/src/smt/smt_statistics_registry.h @@ -2,9 +2,9 @@ /*! \file smt_statistics_registry.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/term_formula_removal.cpp b/src/smt/term_formula_removal.cpp index 1ae125e03..89091d309 100644 --- a/src/smt/term_formula_removal.cpp +++ b/src/smt/term_formula_removal.cpp @@ -2,9 +2,9 @@ /*! \file term_formula_removal.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Dejan Jovanovic, Morgan Deters + ** Andrew Reynolds, Morgan Deters, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -89,8 +89,8 @@ Node RemoveTermFormulas::run(TNode node, std::vector<Node>& output, if (node.getKind() == kind::ITE && !nodeType.isBoolean()) { // Here, we eliminate the ITE if we are not Boolean and if we do not contain - // a bound variable. - if (!inQuant || !expr::hasBoundVar(node)) + // a free variable. + if (!inQuant || !expr::hasFreeVar(node)) { skolem = getSkolemForNode(node); if (skolem.isNull()) @@ -111,7 +111,7 @@ Node RemoveTermFormulas::run(TNode node, std::vector<Node>& output, else if (node.getKind() == kind::LAMBDA) { // if a lambda, do lambda-lifting - if (!inQuant) + if (!inQuant || !expr::hasFreeVar(node)) { skolem = getSkolemForNode(node); if (skolem.isNull()) @@ -143,7 +143,7 @@ Node RemoveTermFormulas::run(TNode node, std::vector<Node>& output, // If a witness choice // For details on this operator, see // http://planetmath.org/hilbertsvarepsilonoperator. - if (!inQuant) + if (!inQuant || !expr::hasFreeVar(node)) { skolem = getSkolemForNode(node); if (skolem.isNull()) diff --git a/src/smt/term_formula_removal.h b/src/smt/term_formula_removal.h index 3b72b46a5..9ec12cb12 100644 --- a/src/smt/term_formula_removal.h +++ b/src/smt/term_formula_removal.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt/update_ostream.h b/src/smt/update_ostream.h index 53d5e5ce0..51fbc66e1 100644 --- a/src/smt/update_ostream.h +++ b/src/smt/update_ostream.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt_util/boolean_simplification.cpp b/src/smt_util/boolean_simplification.cpp index 199841279..657ed1f51 100644 --- a/src/smt_util/boolean_simplification.cpp +++ b/src/smt_util/boolean_simplification.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt_util/boolean_simplification.h b/src/smt_util/boolean_simplification.h index f1bfe6e33..57857baaa 100644 --- a/src/smt_util/boolean_simplification.h +++ b/src/smt_util/boolean_simplification.h @@ -2,9 +2,9 @@ /*! \file boolean_simplification.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Andres Noetzli + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt_util/nary_builder.cpp b/src/smt_util/nary_builder.cpp index 6c655ad41..612937b43 100644 --- a/src/smt_util/nary_builder.cpp +++ b/src/smt_util/nary_builder.cpp @@ -2,9 +2,9 @@ /*! \file nary_builder.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/smt_util/nary_builder.h b/src/smt_util/nary_builder.h index 889591909..0573b0712 100644 --- a/src/smt_util/nary_builder.h +++ b/src/smt_util/nary_builder.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/approx_simplex.cpp b/src/theory/arith/approx_simplex.cpp index 6b277a10a..a006d43b3 100644 --- a/src/theory/arith/approx_simplex.cpp +++ b/src/theory/arith/approx_simplex.cpp @@ -2,9 +2,9 @@ /*! \file approx_simplex.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andres Noetzli + ** Tim King, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/approx_simplex.h b/src/theory/arith/approx_simplex.h index 2914c2da8..e72b25274 100644 --- a/src/theory/arith/approx_simplex.h +++ b/src/theory/arith/approx_simplex.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arith_ite_utils.cpp b/src/theory/arith/arith_ite_utils.cpp index 3930d7359..4892389f2 100644 --- a/src/theory/arith/arith_ite_utils.cpp +++ b/src/theory/arith/arith_ite_utils.cpp @@ -2,9 +2,9 @@ /*! \file arith_ite_utils.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Aina Niemetz, Kshitij Bansal + ** Tim King, Aina Niemetz, Piotr Trojanek ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arith_ite_utils.h b/src/theory/arith/arith_ite_utils.h index a9e7aa92c..f86328d5d 100644 --- a/src/theory/arith/arith_ite_utils.h +++ b/src/theory/arith/arith_ite_utils.h @@ -2,9 +2,9 @@ /*! \file arith_ite_utils.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Aina Niemetz + ** Tim King, Mathias Preiner, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arith_msum.cpp b/src/theory/arith/arith_msum.cpp index 7f13ce07d..5c654a90b 100644 --- a/src/theory/arith/arith_msum.cpp +++ b/src/theory/arith/arith_msum.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arith_msum.h b/src/theory/arith/arith_msum.h index 8a9dbf791..4458bdecd 100644 --- a/src/theory/arith/arith_msum.h +++ b/src/theory/arith/arith_msum.h @@ -2,9 +2,9 @@ /*! \file arith_msum.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arith_rewriter.cpp b/src/theory/arith/arith_rewriter.cpp index 222b63db5..188ef47e6 100644 --- a/src/theory/arith/arith_rewriter.cpp +++ b/src/theory/arith/arith_rewriter.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -25,6 +25,7 @@ #include "theory/arith/arith_utilities.h" #include "theory/arith/normal_form.h" #include "theory/theory.h" +#include "util/iand.h" namespace CVC4 { namespace theory { @@ -101,8 +102,8 @@ RewriteResponse ArithRewriter::preRewriteTerm(TNode t){ case kind::PLUS: return preRewritePlus(t); case kind::MULT: - case kind::NONLINEAR_MULT: - return preRewriteMult(t); + case kind::NONLINEAR_MULT: return preRewriteMult(t); + case kind::IAND: return RewriteResponse(REWRITE_DONE, t); case kind::EXPONENTIAL: case kind::SINE: case kind::COSINE: @@ -165,8 +166,8 @@ RewriteResponse ArithRewriter::postRewriteTerm(TNode t){ case kind::PLUS: return postRewritePlus(t); case kind::MULT: - case kind::NONLINEAR_MULT: - return postRewriteMult(t); + case kind::NONLINEAR_MULT: return postRewriteMult(t); + case kind::IAND: return postRewriteIAnd(t); case kind::EXPONENTIAL: case kind::SINE: case kind::COSINE: @@ -371,6 +372,47 @@ RewriteResponse ArithRewriter::postRewriteMult(TNode t){ return RewriteResponse(REWRITE_DONE, res.getNode()); } +RewriteResponse ArithRewriter::postRewriteIAnd(TNode t) +{ + Assert(t.getKind() == kind::IAND); + NodeManager* nm = NodeManager::currentNM(); + // if constant, we eliminate + if (t[0].isConst() && t[1].isConst()) + { + size_t bsize = t.getOperator().getConst<IntAnd>().d_size; + Node iToBvop = nm->mkConst(IntToBitVector(bsize)); + Node arg1 = nm->mkNode(kind::INT_TO_BITVECTOR, iToBvop, t[0]); + Node arg2 = nm->mkNode(kind::INT_TO_BITVECTOR, iToBvop, t[1]); + Node bvand = nm->mkNode(kind::BITVECTOR_AND, arg1, arg2); + Node ret = nm->mkNode(kind::BITVECTOR_TO_NAT, bvand); + return RewriteResponse(REWRITE_AGAIN_FULL, ret); + } + else if (t[0] > t[1]) + { + // ((_ iand k) x y) ---> ((_ iand k) y x) if x > y by node ordering + Node ret = nm->mkNode(kind::IAND, t.getOperator(), t[1], t[0]); + return RewriteResponse(REWRITE_AGAIN, ret); + } + else if (t[0] == t[1]) + { + // ((_ iand k) x x) ---> x + return RewriteResponse(REWRITE_DONE, t[0]); + } + // simplifications involving constants + for (unsigned i = 0; i < 2; i++) + { + if (!t[i].isConst()) + { + continue; + } + if (t[i].getConst<Rational>().sgn() == 0) + { + // ((_ iand k) 0 y) ---> 0 + return RewriteResponse(REWRITE_DONE, t[i]); + } + } + return RewriteResponse(REWRITE_DONE, t); +} RewriteResponse ArithRewriter::preRewriteTranscendental(TNode t) { return RewriteResponse(REWRITE_DONE, t); diff --git a/src/theory/arith/arith_rewriter.h b/src/theory/arith/arith_rewriter.h index 600f38d4f..1dc756514 100644 --- a/src/theory/arith/arith_rewriter.h +++ b/src/theory/arith/arith_rewriter.h @@ -2,9 +2,9 @@ /*! \file arith_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Tim King, Morgan Deters + ** Dejan Jovanovic, Tim King, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -52,7 +52,9 @@ class ArithRewriter : public TheoryRewriter static RewriteResponse preRewriteMult(TNode t); static RewriteResponse postRewriteMult(TNode t); - + + static RewriteResponse postRewriteIAnd(TNode t); + static RewriteResponse preRewriteTranscendental(TNode t); static RewriteResponse postRewriteTranscendental(TNode t); diff --git a/src/theory/arith/arith_static_learner.cpp b/src/theory/arith/arith_static_learner.cpp index 810eded82..9bd5ad774 100644 --- a/src/theory/arith/arith_static_learner.cpp +++ b/src/theory/arith/arith_static_learner.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Dejan Jovanovic, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arith_static_learner.h b/src/theory/arith/arith_static_learner.h index bc77f8ec0..5abada539 100644 --- a/src/theory/arith/arith_static_learner.h +++ b/src/theory/arith/arith_static_learner.h @@ -2,9 +2,9 @@ /*! \file arith_static_learner.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Dejan Jovanovic, Morgan Deters + ** Tim King, Dejan Jovanovic, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arith_utilities.cpp b/src/theory/arith/arith_utilities.cpp index cb8524a58..3d708c94e 100644 --- a/src/theory/arith/arith_utilities.cpp +++ b/src/theory/arith/arith_utilities.cpp @@ -2,9 +2,9 @@ /*! \file arith_utilities.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arith_utilities.h b/src/theory/arith/arith_utilities.h index 2d466f52f..bfc1fbf88 100644 --- a/src/theory/arith/arith_utilities.h +++ b/src/theory/arith/arith_utilities.h @@ -2,9 +2,9 @@ /*! \file arith_utilities.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Andrew Reynolds, Morgan Deters + ** Tim King, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arithvar.cpp b/src/theory/arith/arithvar.cpp index 2eb349984..7f2535004 100644 --- a/src/theory/arith/arithvar.cpp +++ b/src/theory/arith/arithvar.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arithvar.h b/src/theory/arith/arithvar.h index 9ab452947..7e0894afa 100644 --- a/src/theory/arith/arithvar.h +++ b/src/theory/arith/arithvar.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/arithvar_node_map.h b/src/theory/arith/arithvar_node_map.h index 03b061504..a6569bded 100644 --- a/src/theory/arith/arithvar_node_map.h +++ b/src/theory/arith/arithvar_node_map.h @@ -2,9 +2,9 @@ /*! \file arithvar_node_map.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/attempt_solution_simplex.cpp b/src/theory/arith/attempt_solution_simplex.cpp index 983fa2b30..91e922fa1 100644 --- a/src/theory/arith/attempt_solution_simplex.cpp +++ b/src/theory/arith/attempt_solution_simplex.cpp @@ -2,9 +2,9 @@ /*! \file attempt_solution_simplex.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/attempt_solution_simplex.h b/src/theory/arith/attempt_solution_simplex.h index 1fd8ee146..4c05372ad 100644 --- a/src/theory/arith/attempt_solution_simplex.h +++ b/src/theory/arith/attempt_solution_simplex.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/bound_counts.h b/src/theory/arith/bound_counts.h index 43fa4e437..a9466ef45 100644 --- a/src/theory/arith/bound_counts.h +++ b/src/theory/arith/bound_counts.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/callbacks.cpp b/src/theory/arith/callbacks.cpp index 158a81e8d..758a337ba 100644 --- a/src/theory/arith/callbacks.cpp +++ b/src/theory/arith/callbacks.cpp @@ -2,9 +2,9 @@ /*! \file callbacks.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/callbacks.h b/src/theory/arith/callbacks.h index ee39c76f9..f947ca03b 100644 --- a/src/theory/arith/callbacks.h +++ b/src/theory/arith/callbacks.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Mathias Preiner, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/congruence_manager.cpp b/src/theory/arith/congruence_manager.cpp index 5a6bf6f31..858098b70 100644 --- a/src/theory/arith/congruence_manager.cpp +++ b/src/theory/arith/congruence_manager.cpp @@ -2,9 +2,9 @@ /*! \file congruence_manager.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Paul Meng, Dejan Jovanovic + ** Tim King, Dejan Jovanovic, Paul Meng ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -21,7 +21,6 @@ #include "smt/smt_statistics_registry.h" #include "theory/arith/arith_utilities.h" #include "theory/arith/constraint.h" -#include "theory/quantifiers/equality_infer.h" #include "options/arith_options.h" namespace CVC4 { @@ -37,8 +36,6 @@ ArithCongruenceManager::ArithCongruenceManager( : d_inConflict(c), d_raiseConflict(raiseConflict), d_notify(*this), - d_eq_infer(), - d_eqi_counter(0, c), d_keepAlive(c), d_propagatations(c), d_explanationMap(c), @@ -50,11 +47,7 @@ ArithCongruenceManager::ArithCongruenceManager( d_ee.addFunctionKind(kind::NONLINEAR_MULT); d_ee.addFunctionKind(kind::EXPONENTIAL); d_ee.addFunctionKind(kind::SINE); - //module to infer additional equalities based on normalization - if( options::sNormInferEq() ){ - d_eq_infer.reset(new quantifiers::EqualityInference(c, true)); - d_true = NodeManager::currentNM()->mkConst( true ); - } + d_ee.addFunctionKind(kind::IAND); } ArithCongruenceManager::~ArithCongruenceManager() {} @@ -116,12 +109,10 @@ void ArithCongruenceManager::ArithCongruenceNotify::eqNotifyConstantTermMerge(TN d_acm.propagate(t1.eqNode(t2)); } void ArithCongruenceManager::ArithCongruenceNotify::eqNotifyNewClass(TNode t) { - d_acm.eqNotifyNewClass(t); } void ArithCongruenceManager::ArithCongruenceNotify::eqNotifyPreMerge(TNode t1, TNode t2) { } void ArithCongruenceManager::ArithCongruenceNotify::eqNotifyPostMerge(TNode t1, TNode t2) { - d_acm.eqNotifyPostMerge(t1,t2); } void ArithCongruenceManager::ArithCongruenceNotify::eqNotifyDisequal(TNode t1, TNode t2, TNode reason) { } @@ -360,19 +351,6 @@ Node ArithCongruenceManager::explainInternal(TNode internal){ } } -void ArithCongruenceManager::eqNotifyNewClass(TNode t) { - if( d_eq_infer ){ - d_eq_infer->eqNotifyNewClass(t); - fixpointInfer(); - } -} -void ArithCongruenceManager::eqNotifyPostMerge(TNode t1, TNode t2) { - if( d_eq_infer ){ - d_eq_infer->eqNotifyMerge(t1, t2); - fixpointInfer(); - } -} - Node ArithCongruenceManager::explain(TNode external){ Trace("arith-ee") << "Ask for explanation of " << external << std::endl; Node internal = externalToInternal(external); @@ -470,53 +448,6 @@ void ArithCongruenceManager::addSharedTerm(Node x){ d_ee.addTriggerTerm(x, THEORY_ARITH); } -bool ArithCongruenceManager::fixpointInfer() { - if( d_eq_infer ){ - while(! inConflict() && d_eqi_counter.get()<d_eq_infer->getNumPendingMerges() ) { - Trace("snorm-infer-eq-debug") << "Processing " << d_eqi_counter.get() << " / " << d_eq_infer->getNumPendingMerges() << std::endl; - Node eq = d_eq_infer->getPendingMerge( d_eqi_counter.get() ); - Trace("snorm-infer-eq") << "ArithCongruenceManager : Infer by normalization : " << eq << std::endl; - if( !d_ee.areEqual( eq[0], eq[1] ) ){ - Node eq_exp = d_eq_infer->getPendingMergeExplanation( d_eqi_counter.get() ); - Trace("snorm-infer-eq") << " explanation : " << eq_exp << std::endl; - //regress explanation - std::vector<TNode> assumptions; - if( eq_exp.getKind()==kind::AND ){ - for( unsigned i=0; i<eq_exp.getNumChildren(); i++ ){ - explain( eq_exp[i], assumptions ); - } - }else if( eq_exp.getKind()==kind::EQUAL ){ - explain( eq_exp, assumptions ); - }else{ - //eq_exp should be true - Assert(eq_exp == d_true); - } - Node req_exp; - if( assumptions.empty() ){ - req_exp = d_true; - }else{ - std::set<TNode> assumptionSet; - assumptionSet.insert(assumptions.begin(), assumptions.end()); - if( assumptionSet.size()==1 ){ - req_exp = assumptions[0]; - }else{ - NodeBuilder<> conjunction(kind::AND); - enqueueIntoNB(assumptionSet, conjunction); - req_exp = conjunction; - } - } - Trace("snorm-infer-eq") << " regressed explanation : " << req_exp << std::endl; - d_ee.assertEquality( eq, true, req_exp ); - d_keepAlive.push_back( req_exp ); - }else{ - Trace("snorm-infer-eq") << "...already equal." << std::endl; - } - d_eqi_counter = d_eqi_counter.get() + 1; - } - } - return inConflict(); -} - }/* CVC4::theory::arith namespace */ }/* CVC4::theory namespace */ }/* CVC4 namespace */ diff --git a/src/theory/arith/congruence_manager.h b/src/theory/arith/congruence_manager.h index bccd2e943..96f82b059 100644 --- a/src/theory/arith/congruence_manager.h +++ b/src/theory/arith/congruence_manager.h @@ -2,9 +2,9 @@ /*! \file congruence_manager.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Mathias Preiner, Paul Meng + ** Tim King, Mathias Preiner, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -78,12 +78,6 @@ private: }; ArithCongruenceNotify d_notify; - /** module for shostak normalization, d_eqi_counter is how many pending merges - * in d_eq_infer we have processed */ - std::unique_ptr<quantifiers::EqualityInference> d_eq_infer; - context::CDO<unsigned> d_eqi_counter; - Node d_true; - context::CDList<Node> d_keepAlive; /** Store the propagations. */ @@ -140,9 +134,6 @@ private: void enqueueIntoNB(const std::set<TNode> all, NodeBuilder<>& nb); Node explainInternal(TNode internal); - - void eqNotifyNewClass(TNode t); - void eqNotifyPostMerge(TNode t1, TNode t2); public: ArithCongruenceManager(context::Context* satContext, ConstraintDatabase&, SetupLiteralCallBack, const ArithVariables&, RaiseEqualityEngineConflict raiseConflict); @@ -176,9 +167,6 @@ public: void addSharedTerm(Node x); - - /** process inferred equalities based on Shostak normalization */ - bool fixpointInfer(); eq::EqualityEngine * getEqualityEngine() { return &d_ee; } diff --git a/src/theory/arith/constraint.cpp b/src/theory/arith/constraint.cpp index 11c6c15a7..abfaca954 100644 --- a/src/theory/arith/constraint.cpp +++ b/src/theory/arith/constraint.cpp @@ -2,9 +2,9 @@ /*! \file constraint.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Alex Ozdemir, Aina Niemetz + ** Tim King, Alex Ozdemir, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/constraint.h b/src/theory/arith/constraint.h index 17b4fa4e3..873b33ced 100644 --- a/src/theory/arith/constraint.h +++ b/src/theory/arith/constraint.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Alex Ozdemir, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/constraint_forward.h b/src/theory/arith/constraint_forward.h index 5f3f2251d..986104539 100644 --- a/src/theory/arith/constraint_forward.h +++ b/src/theory/arith/constraint_forward.h @@ -2,9 +2,9 @@ /*! \file constraint_forward.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/cut_log.cpp b/src/theory/arith/cut_log.cpp index 43ef97123..7eb173f4f 100644 --- a/src/theory/arith/cut_log.cpp +++ b/src/theory/arith/cut_log.cpp @@ -2,9 +2,9 @@ /*! \file cut_log.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/cut_log.h b/src/theory/arith/cut_log.h index a5a729f58..691b4d7fd 100644 --- a/src/theory/arith/cut_log.h +++ b/src/theory/arith/cut_log.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/delta_rational.cpp b/src/theory/arith/delta_rational.cpp index 35640ac1a..c983b5e76 100644 --- a/src/theory/arith/delta_rational.cpp +++ b/src/theory/arith/delta_rational.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/delta_rational.h b/src/theory/arith/delta_rational.h index 7fd4e2031..1394bef8a 100644 --- a/src/theory/arith/delta_rational.h +++ b/src/theory/arith/delta_rational.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Dejan Jovanovic, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/dio_solver.cpp b/src/theory/arith/dio_solver.cpp index 438e11511..7b33d24f7 100644 --- a/src/theory/arith/dio_solver.cpp +++ b/src/theory/arith/dio_solver.cpp @@ -2,9 +2,9 @@ /*! \file dio_solver.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Dejan Jovanovic + ** Tim King, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/dio_solver.h b/src/theory/arith/dio_solver.h index fa6c08696..1e5f4a97f 100644 --- a/src/theory/arith/dio_solver.h +++ b/src/theory/arith/dio_solver.h @@ -2,9 +2,9 @@ /*! \file dio_solver.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/dual_simplex.cpp b/src/theory/arith/dual_simplex.cpp index bcb90f8ae..643161758 100644 --- a/src/theory/arith/dual_simplex.cpp +++ b/src/theory/arith/dual_simplex.cpp @@ -2,9 +2,9 @@ /*! \file dual_simplex.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andres Noetzli + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/dual_simplex.h b/src/theory/arith/dual_simplex.h index ab04bc616..5abce830b 100644 --- a/src/theory/arith/dual_simplex.h +++ b/src/theory/arith/dual_simplex.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/error_set.cpp b/src/theory/arith/error_set.cpp index 12e352e4d..236c09fde 100644 --- a/src/theory/arith/error_set.cpp +++ b/src/theory/arith/error_set.cpp @@ -2,9 +2,9 @@ /*! \file error_set.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/error_set.h b/src/theory/arith/error_set.h index 5599cd268..795c86f3b 100644 --- a/src/theory/arith/error_set.h +++ b/src/theory/arith/error_set.h @@ -2,9 +2,9 @@ /*! \file error_set.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters + ** Tim King, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/fc_simplex.cpp b/src/theory/arith/fc_simplex.cpp index 125a24f5e..2135944ab 100644 --- a/src/theory/arith/fc_simplex.cpp +++ b/src/theory/arith/fc_simplex.cpp @@ -2,9 +2,9 @@ /*! \file fc_simplex.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andres Noetzli + ** Tim King, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/fc_simplex.h b/src/theory/arith/fc_simplex.h index cfeef1d26..7451d5c48 100644 --- a/src/theory/arith/fc_simplex.h +++ b/src/theory/arith/fc_simplex.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/infer_bounds.cpp b/src/theory/arith/infer_bounds.cpp index 5ce617061..3714f3eb6 100644 --- a/src/theory/arith/infer_bounds.cpp +++ b/src/theory/arith/infer_bounds.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/infer_bounds.h b/src/theory/arith/infer_bounds.h index bce9a07db..e9ea01071 100644 --- a/src/theory/arith/infer_bounds.h +++ b/src/theory/arith/infer_bounds.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/kinds b/src/theory/arith/kinds index 409534050..e563d8f66 100644 --- a/src/theory/arith/kinds +++ b/src/theory/arith/kinds @@ -133,4 +133,18 @@ nullaryoperator PI "pi" typerule PI ::CVC4::theory::arith::RealNullaryOperatorTypeRule +# Integer AND, which is parameterized by a (positive) bitwidth k. +# ((_ iand k) i1 i2) is equivalent to: +# (bv2int (bvand ((_ int2bv k) i1) ((_ int2bv k) i2))) +# for all integers i1, i2. +constant IAND_OP \ + ::CVC4::IntAnd \ + "::CVC4::UnsignedHashFunction< ::CVC4::IntAnd >" \ + "util/iand.h" \ + "operator for integer AND; payload is an instance of the CVC4::IntAnd class" +parameterized IAND IAND_OP 2 "integer version of AND operator; first parameter is an IAND_OP, second and third are integer terms" + +typerule IAND_OP ::CVC4::theory::arith::IAndOpTypeRule +typerule IAND ::CVC4::theory::arith::IAndTypeRule + endtheory diff --git a/src/theory/arith/linear_equality.cpp b/src/theory/arith/linear_equality.cpp index 8c7d22088..7eb2f3f9e 100644 --- a/src/theory/arith/linear_equality.cpp +++ b/src/theory/arith/linear_equality.cpp @@ -2,9 +2,9 @@ /*! \file linear_equality.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters + ** Tim King, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/linear_equality.h b/src/theory/arith/linear_equality.h index 1f5bb9ea4..f19b3d6ef 100644 --- a/src/theory/arith/linear_equality.h +++ b/src/theory/arith/linear_equality.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/matrix.cpp b/src/theory/arith/matrix.cpp index c6332fd23..14593f550 100644 --- a/src/theory/arith/matrix.cpp +++ b/src/theory/arith/matrix.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/matrix.h b/src/theory/arith/matrix.h index c845ccb05..22a669f9b 100644 --- a/src/theory/arith/matrix.h +++ b/src/theory/arith/matrix.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/nl_constraint.cpp b/src/theory/arith/nl/nl_constraint.cpp index 8fb4535ea..ae678ccdf 100644 --- a/src/theory/arith/nl_constraint.cpp +++ b/src/theory/arith/nl/nl_constraint.cpp @@ -2,9 +2,9 @@ /*! \file nl_constraint.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..113c573d8 100644 --- a/src/theory/arith/nl_constraint.h +++ b/src/theory/arith/nl/nl_constraint.h @@ -2,9 +2,9 @@ /*! \file nl_constraint.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King + ** Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..0497b5822 100644 --- a/src/theory/arith/nl_lemma_utils.cpp +++ b/src/theory/arith/nl/nl_lemma_utils.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -12,13 +12,20 @@ ** \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 { + +std::ostream& operator<<(std::ostream& out, NlLemma& n) +{ + out << n.d_lemma; + return out; +} bool SortNlModel::operator()(Node i, Node j) { @@ -58,6 +65,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..eaa9adcc3 100644 --- a/src/theory/arith/nl_lemma_utils.h +++ b/src/theory/arith/nl/nl_lemma_utils.h @@ -2,9 +2,9 @@ /*! \file nl_lemma_utils.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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,20 +22,29 @@ namespace CVC4 { namespace theory { namespace arith { +namespace nl { class NlModel; /** - * A side effect of adding a lemma in the non-linear solver. This is used - * to specify how the state of the non-linear solver should update. This - * includes: + * The data structure for a single lemma to process by the non-linear solver, + * including the lemma itself and whether it should be preprocessed (see + * OutputChannel::lemma). + * + * This also includes data structures that encapsulate the side effect of adding + * this lemma in the non-linear solver. This is used to specify how the state of + * the non-linear solver should update. This includes: * - A set of secant points to record (for transcendental secant plane * inferences). */ -struct NlLemmaSideEffect +struct NlLemma { - NlLemmaSideEffect() {} - ~NlLemmaSideEffect() {} + NlLemma(Node lem) : d_lemma(lem), d_preprocess(false) {} + ~NlLemma() {} + /** The lemma */ + Node d_lemma; + /** Whether to preprocess the lemma */ + bool d_preprocess; /** secant points to add * * A member (tf, d, c) in this vector indicates that point c should be added @@ -47,6 +56,10 @@ struct NlLemmaSideEffect */ std::vector<std::tuple<Node, unsigned, Node> > d_secantPoint; }; +/** + * Writes a non-linear lemma to a stream. + */ +std::ostream& operator<<(std::ostream& out, NlLemma& n); struct SortNlModel { @@ -98,6 +111,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..d471bf0f6 100644 --- a/src/theory/arith/nl_model.cpp +++ b/src/theory/arith/nl/nl_model.cpp @@ -2,9 +2,9 @@ /*! \file nl_model.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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) { @@ -210,13 +211,12 @@ int NlModel::compareValue(Node i, Node j, bool isAbsolute) const } bool NlModel::checkModel(const std::vector<Node>& assertions, - const std::vector<Node>& false_asserts, unsigned d, - std::vector<Node>& lemmas, + std::vector<NlLemma>& lemmas, std::vector<Node>& gs) { Trace("nl-ext-cm-debug") << " solve for equalities..." << std::endl; - for (const Node& atom : false_asserts) + for (const Node& atom : assertions) { // see if it corresponds to a univariate polynomial equation of degree two if (atom.getKind() == EQUAL) @@ -320,7 +320,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 +350,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()) { @@ -477,7 +477,7 @@ void NlModel::addTautology(Node n) bool NlModel::solveEqualitySimple(Node eq, unsigned d, - std::vector<Node>& lemmas) + std::vector<NlLemma>& lemmas) { Node seq = eq; if (!d_check_model_vars.empty()) @@ -488,6 +488,7 @@ bool NlModel::solveEqualitySimple(Node eq, { if (seq.getConst<bool>()) { + // already true d_check_model_solved[eq] = Node::null(); return true; } @@ -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..fdce446fc 100644 --- a/src/theory/arith/nl_model.h +++ b/src/theory/arith/nl/nl_model.h @@ -2,9 +2,9 @@ /*! \file nl_model.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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> @@ -23,11 +23,13 @@ #include "context/context.h" #include "expr/kind.h" #include "expr/node.h" +#include "theory/arith/nl/nl_lemma_utils.h" #include "theory/theory_model.h" namespace CVC4 { namespace theory { namespace arith { +namespace nl { class NonlinearExtension; @@ -149,9 +151,8 @@ class NlModel * d is a degree indicating how precise our computations are. */ bool checkModel(const std::vector<Node>& assertions, - const std::vector<Node>& false_asserts, unsigned d, - std::vector<Node>& lemmas, + std::vector<NlLemma>& lemmas, std::vector<Node>& gs); /** * Set that we have used an approximation during this check. This flag is @@ -232,7 +233,7 @@ class NlModel * For instance, if eq reduces to a univariate quadratic equation with no * root, we send a conflict clause of the form a*x^2 + b*x + c != 0. */ - bool solveEqualitySimple(Node eq, unsigned d, std::vector<Node>& lemmas); + bool solveEqualitySimple(Node eq, unsigned d, std::vector<NlLemma>& lemmas); /** simple check model for transcendental functions for literal * @@ -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..1cd0a848d 100644 --- a/src/theory/arith/nl_monomial.cpp +++ b/src/theory/arith/nl/nl_monomial.cpp @@ -2,9 +2,9 @@ /*! \file nl_monomial.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tim King, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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) @@ -275,7 +276,7 @@ Node MonomialDb::getContainsDiff(Node a, Node b) const { std::map<Node, std::map<Node, Node> >::const_iterator it = d_m_contain_mult.find(a); - if (it == d_m_contain_umult.end()) + if (it == d_m_contain_mult.end()) { return Node::null(); } @@ -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..e84233e8e 100644 --- a/src/theory/arith/nl_monomial.h +++ b/src/theory/arith/nl/nl_monomial.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..fee89caf6 100644 --- a/src/theory/arith/nl_solver.cpp +++ b/src/theory/arith/nl/nl_solver.cpp @@ -2,9 +2,9 @@ /*! \file nl_solver.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tim King, Ahmed Irfan ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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) { @@ -164,9 +165,9 @@ void NlSolver::setMonomialFactor(Node a, Node b, const NodeMultiset& common) } } -std::vector<Node> NlSolver::checkSplitZero() +std::vector<NlLemma> NlSolver::checkSplitZero() { - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; for (unsigned i = 0; i < d_ms_vars.size(); i++) { Node v = d_ms_vars[i]; @@ -259,7 +260,7 @@ int NlSolver::compareSign(Node oa, unsigned a_index, int status, std::vector<Node>& exp, - std::vector<Node>& lem) + std::vector<NlLemma>& lem) { Trace("nl-ext-debug") << "Process " << a << " at index " << a_index << ", status is " << status << std::endl; @@ -310,7 +311,7 @@ bool NlSolver::compareMonomial( Node b, NodeMultiset& b_exp_proc, std::vector<Node>& exp, - std::vector<Node>& lem, + std::vector<NlLemma>& lem, std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers) { Trace("nl-ext-comp-debug") @@ -414,7 +415,7 @@ bool NlSolver::compareMonomial( NodeMultiset& b_exp_proc, int status, std::vector<Node>& exp, - std::vector<Node>& lem, + std::vector<NlLemma>& lem, std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers) { Trace("nl-ext-comp-debug") @@ -627,9 +628,9 @@ bool NlSolver::compareMonomial( return false; } -std::vector<Node> NlSolver::checkMonomialSign() +std::vector<NlLemma> NlSolver::checkMonomialSign() { - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; std::map<Node, int> signs; Trace("nl-ext") << "Get monomial sign lemmas..." << std::endl; for (unsigned j = 0; j < d_ms.size(); j++) @@ -666,7 +667,7 @@ std::vector<Node> NlSolver::checkMonomialSign() return lemmas; } -std::vector<Node> NlSolver::checkMonomialMagnitude(unsigned c) +std::vector<NlLemma> NlSolver::checkMonomialMagnitude(unsigned c) { // ensure information is setup if (c == 0) @@ -680,7 +681,7 @@ std::vector<Node> NlSolver::checkMonomialMagnitude(unsigned c) } unsigned r = 1; - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; // if (x,y,L) in cmp_infers, then x > y inferred as conclusion of L // in lemmas std::map<int, std::map<Node, std::map<Node, Node> > > cmp_infers; @@ -802,7 +803,7 @@ std::vector<Node> NlSolver::checkMonomialMagnitude(unsigned c) Trace("nl-ext-comp") << "Compute redundancies for " << lemmas.size() << " lemmas." << std::endl; // naive - std::vector<Node> r_lemmas; + std::unordered_set<Node, NodeHashFunction> r_lemmas; for (std::map<int, std::map<Node, std::map<Node, Node> > >::iterator itb = cmp_infers.begin(); itb != cmp_infers.end(); @@ -827,7 +828,7 @@ std::vector<Node> NlSolver::checkMonomialMagnitude(unsigned c) std::vector<Node> exp; if (cmp_holds(itc3->first, itc2->first, itb->second, exp, visited)) { - r_lemmas.push_back(itc2->second); + r_lemmas.insert(itc2->second); Trace("nl-ext-comp") << "...inference of " << itc->first << " > " << itc2->first << " was redundant." << std::endl; @@ -838,11 +839,10 @@ std::vector<Node> NlSolver::checkMonomialMagnitude(unsigned c) } } } - std::vector<Node> nr_lemmas; + std::vector<NlLemma> nr_lemmas; for (unsigned i = 0; i < lemmas.size(); i++) { - if (std::find(r_lemmas.begin(), r_lemmas.end(), lemmas[i]) - == r_lemmas.end()) + if (r_lemmas.find(lemmas[i].d_lemma) == r_lemmas.end()) { nr_lemmas.push_back(lemmas[i]); } @@ -854,9 +854,9 @@ std::vector<Node> NlSolver::checkMonomialMagnitude(unsigned c) return nr_lemmas; } -std::vector<Node> NlSolver::checkTangentPlanes() +std::vector<NlLemma> NlSolver::checkTangentPlanes() { - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; Trace("nl-ext") << "Get monomial tangent plane lemmas..." << std::endl; NodeManager* nm = NodeManager::currentNM(); const std::map<Node, std::vector<Node> >& ccMap = @@ -1012,8 +1012,8 @@ std::vector<Node> NlSolver::checkTangentPlanes() return lemmas; } -std::vector<Node> NlSolver::checkMonomialInferBounds( - std::vector<Node>& nt_lemmas, +std::vector<NlLemma> NlSolver::checkMonomialInferBounds( + std::vector<NlLemma>& nt_lemmas, const std::vector<Node>& asserts, const std::vector<Node>& false_asserts) { @@ -1027,7 +1027,7 @@ std::vector<Node> NlSolver::checkMonomialInferBounds( const std::map<Node, std::map<Node, ConstraintInfo> >& cim = d_cdb.getConstraints(); - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; NodeManager* nm = NodeManager::currentNM(); // register constraints Trace("nl-ext-debug") << "Register bound constraints..." << std::endl; @@ -1270,10 +1270,10 @@ std::vector<Node> NlSolver::checkMonomialInferBounds( return lemmas; } -std::vector<Node> NlSolver::checkFactoring( +std::vector<NlLemma> NlSolver::checkFactoring( const std::vector<Node>& asserts, const std::vector<Node>& false_asserts) { - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; NodeManager* nm = NodeManager::currentNM(); Trace("nl-ext") << "Get factoring lemmas..." << std::endl; for (const Node& lit : asserts) @@ -1400,7 +1400,7 @@ std::vector<Node> NlSolver::checkFactoring( return lemmas; } -Node NlSolver::getFactorSkolem(Node n, std::vector<Node>& lemmas) +Node NlSolver::getFactorSkolem(Node n, std::vector<NlLemma>& lemmas) { std::map<Node, Node>::iterator itf = d_factor_skolem.find(n); if (itf == d_factor_skolem.end()) @@ -1415,9 +1415,9 @@ Node NlSolver::getFactorSkolem(Node n, std::vector<Node>& lemmas) return itf->second; } -std::vector<Node> NlSolver::checkMonomialInferResBounds() +std::vector<NlLemma> NlSolver::checkMonomialInferResBounds() { - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; NodeManager* nm = NodeManager::currentNM(); Trace("nl-ext") << "Get monomial resolution inferred bound lemmas..." << std::endl; @@ -1580,6 +1580,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..b5176a4dd 100644 --- a/src/theory/arith/nl_solver.h +++ b/src/theory/arith/nl/nl_solver.h @@ -2,9 +2,9 @@ /*! \file nl_solver.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King + ** Andrew Reynolds, Tim King, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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; @@ -78,7 +79,7 @@ class NlSolver * t = 0 V t != 0 * where t is a term that exists in the current context. */ - std::vector<Node> checkSplitZero(); + std::vector<NlLemma> checkSplitZero(); /** check monomial sign * @@ -95,7 +96,7 @@ class NlSolver * x < 0 => x*y*y < 0 * x = 0 => x*y*z = 0 */ - std::vector<Node> checkMonomialSign(); + std::vector<NlLemma> checkMonomialSign(); /** check monomial magnitude * @@ -117,7 +118,7 @@ class NlSolver * against 1, 1 : compare non-linear monomials against variables, 2 : compare * non-linear monomials against other non-linear monomials. */ - std::vector<Node> checkMonomialMagnitude(unsigned c); + std::vector<NlLemma> checkMonomialMagnitude(unsigned c); /** check monomial inferred bounds * @@ -136,8 +137,8 @@ class NlSolver * ...where (y > z + w) and x*y are a constraint and term * that occur in the current context. */ - std::vector<Node> checkMonomialInferBounds( - std::vector<Node>& nt_lemmas, + std::vector<NlLemma> checkMonomialInferBounds( + std::vector<NlLemma>& nt_lemmas, const std::vector<Node>& asserts, const std::vector<Node>& false_asserts); @@ -153,8 +154,8 @@ class NlSolver * ...where k is fresh and x*z + y*z > t is a * constraint that occurs in the current context. */ - std::vector<Node> checkFactoring(const std::vector<Node>& asserts, - const std::vector<Node>& false_asserts); + std::vector<NlLemma> checkFactoring(const std::vector<Node>& asserts, + const std::vector<Node>& false_asserts); /** check monomial infer resolution bounds * @@ -170,7 +171,7 @@ class NlSolver * ...where s <= x*z and x*y <= t are constraints * that occur in the current context. */ - std::vector<Node> checkMonomialInferResBounds(); + std::vector<NlLemma> checkMonomialInferResBounds(); /** check tangent planes * @@ -196,7 +197,7 @@ class NlSolver * ( ( x>2 ^ y>5) ^ (x<2 ^ y<5) ) => x*y > 5*x + 2*y - 10 * ( ( x>2 ^ y<5) ^ (x<2 ^ y>5) ) => x*y < 5*x + 2*y - 10 */ - std::vector<Node> checkTangentPlanes(); + std::vector<NlLemma> checkTangentPlanes(); //-------------------------------------------- end lemma schemas private: @@ -294,7 +295,7 @@ class NlSolver unsigned a_index, int status, std::vector<Node>& exp, - std::vector<Node>& lem); + std::vector<NlLemma>& lem); /** compare monomials a and b * * Initially, a call to this function is such that : @@ -337,7 +338,7 @@ class NlSolver Node b, NodeMultiset& b_exp_proc, std::vector<Node>& exp, - std::vector<Node>& lem, + std::vector<NlLemma>& lem, std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers); /** helper function for above * @@ -355,12 +356,13 @@ class NlSolver NodeMultiset& b_exp_proc, int status, std::vector<Node>& exp, - std::vector<Node>& lem, + std::vector<NlLemma>& lem, std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers); /** Get factor skolem for n, add resulting lemmas to lemmas */ - Node getFactorSkolem(Node n, std::vector<Node>& lemmas); + Node getFactorSkolem(Node n, std::vector<NlLemma>& 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..5ded7d3d0 100644 --- a/src/theory/arith/nonlinear_extension.cpp +++ b/src/theory/arith/nl/nonlinear_extension.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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,10 +28,12 @@ using namespace CVC4::kind; namespace CVC4 { namespace theory { namespace arith { +namespace nl { NonlinearExtension::NonlinearExtension(TheoryArith& containing, eq::EqualityEngine* ee) : d_lemmas(containing.getUserContext()), + d_lemmasPp(containing.getUserContext()), d_containing(containing), d_ee(ee), d_needsLastCall(false), @@ -49,27 +51,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 +91,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 +102,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 +133,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]); } } @@ -130,23 +144,22 @@ std::pair<bool, Node> NonlinearExtension::isExtfReduced( return std::make_pair(true, Node::null()); } -void NonlinearExtension::sendLemmas(const std::vector<Node>& out, - bool preprocess, - std::map<Node, NlLemmaSideEffect>& lemSE) +void NonlinearExtension::sendLemmas(const std::vector<NlLemma>& out) { - std::map<Node, NlLemmaSideEffect>::iterator its; - for (const Node& lem : out) + for (const NlLemma& nlem : out) { + Node lem = nlem.d_lemma; + bool preprocess = nlem.d_preprocess; Trace("nl-ext-lemma") << "NonlinearExtension::Lemma : " << lem << std::endl; d_containing.getOutputChannel().lemma(lem, false, preprocess); // process the side effect - its = lemSE.find(lem); - if (its != lemSE.end()) + processSideEffect(nlem); + // add to cache if not preprocess + if (preprocess) { - processSideEffect(its->second); + d_lemmasPp.insert(lem); } - // add to cache if not preprocess - if (!preprocess) + else { d_lemmas.insert(lem); } @@ -155,36 +168,37 @@ void NonlinearExtension::sendLemmas(const std::vector<Node>& out, } } -void NonlinearExtension::processSideEffect(const NlLemmaSideEffect& se) +void NonlinearExtension::processSideEffect(const NlLemma& se) { d_trSlv.processSideEffect(se); } -unsigned NonlinearExtension::filterLemma(Node lem, std::vector<Node>& out) +unsigned NonlinearExtension::filterLemma(NlLemma lem, std::vector<NlLemma>& out) { Trace("nl-ext-lemma-debug") - << "NonlinearExtension::Lemma pre-rewrite : " << lem << std::endl; - lem = Rewriter::rewrite(lem); - if (d_lemmas.find(lem) != d_lemmas.end() - || std::find(out.begin(), out.end(), lem) != out.end()) + << "NonlinearExtension::Lemma pre-rewrite : " << lem.d_lemma << std::endl; + lem.d_lemma = Rewriter::rewrite(lem.d_lemma); + // get the proper cache + NodeSet& lcache = lem.d_preprocess ? d_lemmasPp : d_lemmas; + if (lcache.find(lem.d_lemma) != lcache.end()) { Trace("nl-ext-lemma-debug") - << "NonlinearExtension::Lemma duplicate : " << lem << std::endl; + << "NonlinearExtension::Lemma duplicate : " << lem.d_lemma << std::endl; return 0; } out.push_back(lem); return 1; } -unsigned NonlinearExtension::filterLemmas(std::vector<Node>& lemmas, - std::vector<Node>& out) +unsigned NonlinearExtension::filterLemmas(std::vector<NlLemma>& lemmas, + std::vector<NlLemma>& out) { if (options::nlExtEntailConflicts()) { // check if any are entailed to be false - for (const Node& lem : lemmas) + for (const NlLemma& lem : lemmas) { - Node ch_lemma = lem.negate(); + Node ch_lemma = lem.d_lemma.negate(); ch_lemma = Rewriter::rewrite(ch_lemma); Trace("nl-ext-et-debug") << "Check entailment of " << ch_lemma << "..." << std::endl; @@ -194,8 +208,8 @@ unsigned NonlinearExtension::filterLemmas(std::vector<Node>& lemmas, << et.second << std::endl; if (et.first) { - Trace("nl-ext-et") << "*** Lemma entailed to be in conflict : " << lem - << std::endl; + Trace("nl-ext-et") << "*** Lemma entailed to be in conflict : " + << lem.d_lemma << std::endl; // return just this lemma if (filterLemma(lem, out) > 0) { @@ -207,7 +221,7 @@ unsigned NonlinearExtension::filterLemmas(std::vector<Node>& lemmas, } unsigned sum = 0; - for (const Node& lem : lemmas) + for (const NlLemma& lem : lemmas) { sum += filterLemma(lem, out); } @@ -337,9 +351,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) @@ -357,7 +372,7 @@ std::vector<Node> NonlinearExtension::checkModelEval( bool NonlinearExtension::checkModel(const std::vector<Node>& assertions, const std::vector<Node>& false_asserts, - std::vector<Node>& lemmas, + std::vector<NlLemma>& lemmas, std::vector<Node>& gs) { Trace("nl-ext-cm") << "--- check-model ---" << std::endl; @@ -365,45 +380,47 @@ bool NonlinearExtension::checkModel(const std::vector<Node>& assertions, // get the presubstitution Trace("nl-ext-cm-debug") << " apply pre-substitution..." << std::endl; std::vector<Node> passertions = assertions; - - // preprocess the assertions with the trancendental solver - if (!d_trSlv.preprocessAssertionsCheckModel(passertions)) + if (options::nlExt()) { - return false; + // preprocess the assertions with the trancendental solver + if (!d_trSlv.preprocessAssertionsCheckModel(passertions)) + { + return false; + } } Trace("nl-ext-cm") << "-----" << std::endl; unsigned tdegree = d_trSlv.getTaylorDegree(); - bool ret = - d_model.checkModel(passertions, false_asserts, tdegree, lemmas, gs); + bool ret = d_model.checkModel(passertions, tdegree, lemmas, gs); return ret; } int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions, const std::vector<Node>& false_asserts, const std::vector<Node>& xts, - std::vector<Node>& lems, - std::vector<Node>& lemsPp, - std::vector<Node>& wlems, - std::map<Node, NlLemmaSideEffect>& lemSE) + std::vector<NlLemma>& lems, + std::vector<NlLemma>& wlems) { - // initialize the non-linear solver - d_nlSlv.initLastCall(assertions, false_asserts, xts); - // initialize the trancendental function solver - std::vector<Node> lemmas; - d_trSlv.initLastCall(assertions, false_asserts, xts, lemmas, lemsPp); - - // process lemmas that may have been generated by the transcendental solver - filterLemmas(lemmas, lems); - if (!lems.empty() || !lemsPp.empty()) + std::vector<NlLemma> lemmas; + if (options::nlExt()) + { + // initialize the non-linear solver + d_nlSlv.initLastCall(assertions, false_asserts, xts); + // initialize the trancendental function solver + d_trSlv.initLastCall(assertions, false_asserts, xts, lemmas); + // process lemmas that may have been generated by the transcendental solver + filterLemmas(lemmas, lems); + } + if (!lems.empty()) { Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas during registration." << std::endl; - return lems.size() + lemsPp.size(); + return lems.size(); } //----------------------------------- possibly split on zero - if (options::nlExtSplitZero()) { + if (options::nlExt() && options::nlExtSplitZero()) + { Trace("nl-ext") << "Get zero split lemmas..." << std::endl; lemmas = d_nlSlv.checkSplitZero(); filterLemmas(lemmas, lems); @@ -415,87 +432,35 @@ int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions, } } - //-----------------------------------initial lemmas for transcendental functions - lemmas = d_trSlv.checkTranscendentalInitialRefine(); - filterLemmas(lemmas, lems); - if (!lems.empty()) + //-----------------------------------initial lemmas for transcendental + if (options::nlExt()) { - Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas." - << std::endl; - return lems.size(); - } - - //-----------------------------------lemmas based on sign (comparison to zero) - lemmas = d_nlSlv.checkMonomialSign(); - filterLemmas(lemmas, lems); - if (!lems.empty()) - { - Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas." - << std::endl; - return lems.size(); - } - - //-----------------------------------monotonicity of transdental functions - lemmas = d_trSlv.checkTranscendentalMonotonic(); - filterLemmas(lemmas, lems); - if (!lems.empty()) - { - Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas." - << std::endl; - return lems.size(); - } - - //-----------------------------------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(); + // functions + lemmas = d_trSlv.checkTranscendentalInitialRefine(); filterLemmas(lemmas, lems); if (!lems.empty()) { - Trace("nl-ext") << " ...finished with " << lems.size() - << " new lemmas (out of possible " << nlem << ")." + Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas." << std::endl; return lems.size(); } } - //-----------------------------------inferred bounds lemmas - // e.g. x >= t => y*x >= y*t - std::vector< Node > nt_lemmas; - lemmas = - d_nlSlv.checkMonomialInferBounds(nt_lemmas, assertions, false_asserts); - // Trace("nl-ext") << "Bound lemmas : " << lemmas.size() << ", " << - // nt_lemmas.size() << std::endl; prioritize lemmas that do not - // introduce new monomials - filterLemmas(lemmas, lems); - - if (options::nlExtTangentPlanes() && options::nlExtTangentPlanesInterleave()) + // main calls to nlExt + if (options::nlExt()) { - lemmas = d_nlSlv.checkTangentPlanes(); + //---------------------------------lemmas based on sign (comparison to zero) + lemmas = d_nlSlv.checkMonomialSign(); filterLemmas(lemmas, lems); - } - - if (!lems.empty()) - { - Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas." - << std::endl; - return lems.size(); - } - - // from inferred bound inferences : now do ones that introduce new terms - filterLemmas(nt_lemmas, lems); - if (!lems.empty()) - { - Trace("nl-ext") << " ...finished with " << lems.size() - << " new (monomial-introducing) lemmas." << std::endl; - return lems.size(); - } + if (!lems.empty()) + { + Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas." + << std::endl; + return lems.size(); + } - //------------------------------------factoring lemmas - // x*y + x*z >= t => exists k. k = y + z ^ x*k >= t - if( options::nlExtFactor() ){ - lemmas = d_nlSlv.checkFactoring(assertions, false_asserts); + //-----------------------------------monotonicity of transdental functions + lemmas = d_trSlv.checkTranscendentalMonotonic(); filterLemmas(lemmas, lems); if (!lems.empty()) { @@ -503,39 +468,106 @@ int NonlinearExtension::checkLastCall(const std::vector<Node>& assertions, << std::endl; return lems.size(); } - } - //------------------------------------resolution bound inferences - // e.g. ( y>=0 ^ s <= x*z ^ x*y <= t ) => y*s <= z*t - if (options::nlExtResBound()) { - lemmas = d_nlSlv.checkMonomialInferResBounds(); + //------------------------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(); + filterLemmas(lemmas, lems); + if (!lems.empty()) + { + Trace("nl-ext") << " ...finished with " << lems.size() + << " new lemmas (out of possible " << nlem << ")." + << std::endl; + return lems.size(); + } + } + + //-----------------------------------inferred bounds lemmas + // e.g. x >= t => y*x >= y*t + std::vector<NlLemma> nt_lemmas; + lemmas = + d_nlSlv.checkMonomialInferBounds(nt_lemmas, assertions, false_asserts); + // Trace("nl-ext") << "Bound lemmas : " << lemmas.size() << ", " << + // nt_lemmas.size() << std::endl; prioritize lemmas that do not + // introduce new monomials filterLemmas(lemmas, lems); + + if (options::nlExtTangentPlanes() + && options::nlExtTangentPlanesInterleave()) + { + lemmas = d_nlSlv.checkTangentPlanes(); + filterLemmas(lemmas, lems); + } + if (!lems.empty()) { Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas." << std::endl; return lems.size(); } + + // from inferred bound inferences : now do ones that introduce new terms + filterLemmas(nt_lemmas, lems); + if (!lems.empty()) + { + Trace("nl-ext") << " ...finished with " << lems.size() + << " new (monomial-introducing) lemmas." << std::endl; + return lems.size(); + } + + //------------------------------------factoring lemmas + // x*y + x*z >= t => exists k. k = y + z ^ x*k >= t + if (options::nlExtFactor()) + { + lemmas = d_nlSlv.checkFactoring(assertions, false_asserts); + filterLemmas(lemmas, lems); + if (!lems.empty()) + { + Trace("nl-ext") << " ...finished with " << lems.size() + << " new lemmas." << std::endl; + return lems.size(); + } + } + + //------------------------------------resolution bound inferences + // e.g. ( y>=0 ^ s <= x*z ^ x*y <= t ) => y*s <= z*t + if (options::nlExtResBound()) + { + lemmas = d_nlSlv.checkMonomialInferResBounds(); + filterLemmas(lemmas, lems); + if (!lems.empty()) + { + Trace("nl-ext") << " ...finished with " << lems.size() + << " new lemmas." << std::endl; + return lems.size(); + } + } + + //------------------------------------tangent planes + if (options::nlExtTangentPlanes() + && !options::nlExtTangentPlanesInterleave()) + { + lemmas = d_nlSlv.checkTangentPlanes(); + filterLemmas(lemmas, wlems); + } + if (options::nlExtTfTangentPlanes()) + { + lemmas = d_trSlv.checkTranscendentalTangentPlanes(); + filterLemmas(lemmas, wlems); + } } - - //------------------------------------tangent planes - if (options::nlExtTangentPlanes() && !options::nlExtTangentPlanesInterleave()) - { - lemmas = d_nlSlv.checkTangentPlanes(); - filterLemmas(lemmas, wlems); - } - if (options::nlExtTfTangentPlanes()) - { - lemmas = d_trSlv.checkTranscendentalTangentPlanes(lemSE); - filterLemmas(lemmas, wlems); - } + Trace("nl-ext") << " ...finished with " << wlems.size() << " waiting lemmas." << std::endl; 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 +575,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; } } @@ -559,10 +596,9 @@ void NonlinearExtension::check(Theory::Effort e) { else { // If we computed lemmas during collectModelInfo, send them now. - if (!d_cmiLemmas.empty() || !d_cmiLemmasPp.empty()) + if (!d_cmiLemmas.empty()) { - sendLemmas(d_cmiLemmas, false, d_cmiLemmasSE); - sendLemmas(d_cmiLemmasPp, true, d_cmiLemmasSE); + sendLemmas(d_cmiLemmas); return; } // Otherwise, we will answer SAT. The values that we approximated are @@ -582,10 +618,7 @@ void NonlinearExtension::check(Theory::Effort e) { } } -bool NonlinearExtension::modelBasedRefinement( - std::vector<Node>& mlems, - std::vector<Node>& mlemsPp, - std::map<Node, NlLemmaSideEffect>& lemSE) +bool NonlinearExtension::modelBasedRefinement(std::vector<NlLemma>& mlems) { // get the assertions std::vector<Node> assertions; @@ -665,15 +698,14 @@ bool NonlinearExtension::modelBasedRefinement( // 1 : we may answer SAT, -1 : we may not answer SAT, 0 : unknown int complete_status = 1; // lemmas that should be sent later - std::vector<Node> wlems; + std::vector<NlLemma> wlems; // We require a check either if an assertion is false or a shared term has // a wrong value if (!false_asserts.empty() || num_shared_wrong_value > 0) { complete_status = num_shared_wrong_value > 0 ? -1 : 0; - checkLastCall( - assertions, false_asserts, xts, mlems, mlemsPp, wlems, lemSE); - if (!mlems.empty() || !mlemsPp.empty()) + checkLastCall(assertions, false_asserts, xts, mlems, wlems); + if (!mlems.empty()) { return true; } @@ -689,7 +721,7 @@ bool NonlinearExtension::modelBasedRefinement( << std::endl; // check the model based on simple solving of equalities and using // error bounds on the Taylor approximation of transcendental functions. - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; std::vector<Node> gs; if (checkModel(assertions, false_asserts, lemmas, gs)) { @@ -727,7 +759,7 @@ bool NonlinearExtension::modelBasedRefinement( complete_status = -1; if (!shared_term_value_splits.empty()) { - std::vector<Node> stvLemmas; + std::vector<NlLemma> stvLemmas; for (const Node& eq : shared_term_value_splits) { Node req = Rewriter::rewrite(eq); @@ -754,7 +786,8 @@ bool NonlinearExtension::modelBasedRefinement( } // we are incomplete - if (options::nlExtIncPrecision() && d_model.usedApproximate()) + if (options::nlExt() && options::nlExtIncPrecision() + && d_model.usedApproximate()) { d_trSlv.incrementTaylorDegree(); needsRecheck = true; @@ -788,12 +821,10 @@ void NonlinearExtension::interceptModel(std::map<Node, Node>& arithModel) d_model.reset(d_containing.getValuation().getModel(), arithModel); // run a last call effort check d_cmiLemmas.clear(); - d_cmiLemmasPp.clear(); - d_cmiLemmasSE.clear(); if (!d_builtModel.get()) { Trace("nl-ext") << "interceptModel: do model-based refinement" << std::endl; - modelBasedRefinement(d_cmiLemmas, d_cmiLemmasPp, d_cmiLemmasSE); + modelBasedRefinement(d_cmiLemmas); } if (d_builtModel.get()) { @@ -809,7 +840,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..cb436bda7 100644 --- a/src/theory/arith/nonlinear_extension.h +++ b/src/theory/arith/nl/nonlinear_extension.h @@ -2,9 +2,9 @@ /*! \file nonlinear_extension.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King + ** Andrew Reynolds, Tim King, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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. * @@ -142,8 +147,8 @@ class NonlinearExtension { * involve e.g. solving for variables in nonlinear equations. * * Notice that in the former case, the lemmas it constructs are not sent out - * immediately. Instead, they are put in temporary vectors d_cmiLemmas - * and d_cmiLemmasPp, which are then sent out (if necessary) when a last call + * immediately. Instead, they are put in temporary vector d_cmiLemmas, which + * are then sent out (if necessary) when a last call * effort check is issued to this class. */ void interceptModel(std::map<Node, Node>& arithModel); @@ -157,6 +162,7 @@ class NonlinearExtension { * on the output channel of TheoryArith in this function. */ void presolve(); + private: /** Model-based refinement * @@ -167,18 +173,12 @@ class NonlinearExtension { * described in Reynolds et al. FroCoS 2017 that are based on ruling out * the current candidate model. * - * This function returns true if a lemma was added to the vector lems/lemsPp. + * This function returns true if a lemma was added to the vector lems. * Otherwise, it returns false. In the latter case, the model object d_model * may have information regarding how to construct a model, in the case that * we determined the problem is satisfiable. - * - * The argument lemSE is the "side effect" of the lemmas in mlems and mlemsPp - * (for details, see checkLastCall). */ - bool modelBasedRefinement(std::vector<Node>& mlems, - std::vector<Node>& mlemsPp, - std::map<Node, NlLemmaSideEffect>& lemSE); - + bool modelBasedRefinement(std::vector<NlLemma>& mlems); /** check last call * @@ -187,32 +187,24 @@ class NonlinearExtension { * * xts : the list of (non-reduced) extended terms in the current context. * - * This method adds lemmas to arguments lems, lemsPp, and wlems, each of + * This method adds lemmas to arguments lems and wlems, each of * which are intended to be sent out on the output channel of TheoryArith * under certain conditions. * - * If the set lems or lemsPp is non-empty, then no further processing is + * If the set lems is non-empty, then no further processing is * necessary. The last call effort check should terminate and these - * lemmas should be sent. The set lemsPp is distinguished from lems since - * the preprocess flag on the lemma(...) call should be set to true. + * lemmas should be sent. * * The "waiting" lemmas wlems contain lemmas that should be sent on the * output channel as a last resort. In other words, only if we are not * able to establish SAT via a call to checkModel(...) should wlems be * considered. This set typically contains tangent plane lemmas. - * - * The argument lemSE is the "side effect" of the lemmas from the previous - * three calls. If a lemma is mapping to a side effect, it should be - * processed via a call to processSideEffect(...) immediately after the - * lemma is sent (if it is indeed sent on this call to check). */ int checkLastCall(const std::vector<Node>& assertions, const std::vector<Node>& false_asserts, const std::vector<Node>& xts, - std::vector<Node>& lems, - std::vector<Node>& lemsPp, - std::vector<Node>& wlems, - std::map<Node, NlLemmaSideEffect>& lemSE); + std::vector<NlLemma>& lems, + std::vector<NlLemma>& wlems); /** get assertions * @@ -254,7 +246,7 @@ class NonlinearExtension { */ bool checkModel(const std::vector<Node>& assertions, const std::vector<Node>& false_asserts, - std::vector<Node>& lemmas, + std::vector<NlLemma>& lemmas, std::vector<Node>& gs); //---------------------------end check model @@ -266,21 +258,22 @@ class NonlinearExtension { * the number of lemmas added to out. We do not add lemmas that have already * been sent on the output channel of TheoryArith. */ - unsigned filterLemmas(std::vector<Node>& lemmas, std::vector<Node>& out); + unsigned filterLemmas(std::vector<NlLemma>& lemmas, + std::vector<NlLemma>& out); /** singleton version of above */ - unsigned filterLemma(Node lem, std::vector<Node>& out); + unsigned filterLemma(NlLemma lem, std::vector<NlLemma>& out); /** * Send lemmas in out on the output channel of theory of arithmetic. */ - void sendLemmas(const std::vector<Node>& out, - bool preprocess, - std::map<Node, NlLemmaSideEffect>& lemSE); + void sendLemmas(const std::vector<NlLemma>& out); /** Process side effect se */ - void processSideEffect(const NlLemmaSideEffect& se); + void processSideEffect(const NlLemma& se); /** cache of all lemmas sent on the output channel (user-context-dependent) */ NodeSet d_lemmas; + /** Same as above, for preprocessed lemmas */ + NodeSet d_lemmasPp; /** commonly used terms */ Node d_zero; Node d_one; @@ -307,18 +300,14 @@ class NonlinearExtension { /** The nonlinear extension object * * This is the subsolver responsible for running the procedure for - * constraints involving nonlinear mulitplication. + * constraints involving nonlinear mulitplication, Cimatti et al., TACAS 2017. */ NlSolver d_nlSlv; /** - * The lemmas we computed during collectModelInfo. We store two vectors of - * lemmas to be sent out on the output channel of TheoryArith. The first - * is not preprocessed, the second is. + * The lemmas we computed during collectModelInfo, to be sent out on the + * output channel of TheoryArith. */ - std::vector<Node> d_cmiLemmas; - std::vector<Node> d_cmiLemmasPp; - /** the side effects of the above lemmas */ - std::map<Node, NlLemmaSideEffect> d_cmiLemmasSE; + std::vector<NlLemma> d_cmiLemmas; /** * The approximations computed during collectModelInfo. For details, see * NlModel::getModelValueRepair. @@ -328,6 +317,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..1377aa54a 100644 --- a/src/theory/arith/transcendental_solver.cpp +++ b/src/theory/arith/nl/transcendental_solver.cpp @@ -2,9 +2,9 @@ /*! \file transcendental_solver.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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) { @@ -49,8 +50,7 @@ TranscendentalSolver::~TranscendentalSolver() {} void TranscendentalSolver::initLastCall(const std::vector<Node>& assertions, const std::vector<Node>& false_asserts, const std::vector<Node>& xts, - std::vector<Node>& lems, - std::vector<Node>& lemsPp) + std::vector<NlLemma>& lems) { d_funcCongClass.clear(); d_funcMap.clear(); @@ -212,7 +212,9 @@ void TranscendentalSolver::initLastCall(const std::vector<Node>& assertions, // note we must do preprocess on this lemma Trace("nl-ext-lemma") << "NonlinearExtension::Lemma : purify : " << lem << std::endl; - lemsPp.push_back(lem); + NlLemma nlem(lem); + nlem.d_preprocess = true; + lems.push_back(nlem); } if (Trace.isOn("nl-ext-mv")) @@ -332,7 +334,7 @@ unsigned TranscendentalSolver::getTaylorDegree() const return d_taylor_degree; } -void TranscendentalSolver::processSideEffect(const NlLemmaSideEffect& se) +void TranscendentalSolver::processSideEffect(const NlLemma& se) { for (const std::tuple<Node, unsigned, Node>& sp : se.d_secantPoint) { @@ -361,7 +363,7 @@ void TranscendentalSolver::mkPi() } } -void TranscendentalSolver::getCurrentPiBounds(std::vector<Node>& lemmas) +void TranscendentalSolver::getCurrentPiBounds(std::vector<NlLemma>& lemmas) { NodeManager* nm = NodeManager::currentNM(); Node pi_lem = nm->mkNode(AND, @@ -370,10 +372,10 @@ void TranscendentalSolver::getCurrentPiBounds(std::vector<Node>& lemmas) lemmas.push_back(pi_lem); } -std::vector<Node> TranscendentalSolver::checkTranscendentalInitialRefine() +std::vector<NlLemma> TranscendentalSolver::checkTranscendentalInitialRefine() { NodeManager* nm = NodeManager::currentNM(); - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; Trace("nl-ext") << "Get initial refinement lemmas for transcendental functions..." << std::endl; @@ -461,9 +463,9 @@ std::vector<Node> TranscendentalSolver::checkTranscendentalInitialRefine() return lemmas; } -std::vector<Node> TranscendentalSolver::checkTranscendentalMonotonic() +std::vector<NlLemma> TranscendentalSolver::checkTranscendentalMonotonic() { - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; Trace("nl-ext") << "Get monotonicity lemmas for transcendental functions..." << std::endl; @@ -643,10 +645,9 @@ std::vector<Node> TranscendentalSolver::checkTranscendentalMonotonic() return lemmas; } -std::vector<Node> TranscendentalSolver::checkTranscendentalTangentPlanes( - std::map<Node, NlLemmaSideEffect>& lemSE) +std::vector<NlLemma> TranscendentalSolver::checkTranscendentalTangentPlanes() { - std::vector<Node> lemmas; + std::vector<NlLemma> lemmas; Trace("nl-ext") << "Get tangent plane lemmas for transcendental functions..." << std::endl; // this implements Figure 3 of "Satisfiaility Modulo Transcendental Functions @@ -682,7 +683,7 @@ std::vector<Node> TranscendentalSolver::checkTranscendentalTangentPlanes( { Trace("nl-ext-tftp") << "- run at degree " << d << "..." << std::endl; unsigned prev = lemmas.size(); - if (checkTfTangentPlanesFun(tf, d, lemmas, lemSE)) + if (checkTfTangentPlanesFun(tf, d, lemmas)) { Trace("nl-ext-tftp") << "...fail, #lemmas = " << (lemmas.size() - prev) << std::endl; @@ -699,11 +700,9 @@ std::vector<Node> TranscendentalSolver::checkTranscendentalTangentPlanes( return lemmas; } -bool TranscendentalSolver::checkTfTangentPlanesFun( - Node tf, - unsigned d, - std::vector<Node>& lemmas, - std::map<Node, NlLemmaSideEffect>& lemSE) +bool TranscendentalSolver::checkTfTangentPlanesFun(Node tf, + unsigned d, + std::vector<NlLemma>& lemmas) { NodeManager* nm = NodeManager::currentNM(); Kind k = tf.getKind(); @@ -1019,10 +1018,11 @@ bool TranscendentalSolver::checkTfTangentPlanesFun( Assert(!lemmaConj.empty()); Node lem = lemmaConj.size() == 1 ? lemmaConj[0] : nm->mkNode(AND, lemmaConj); - lemmas.push_back(lem); + NlLemma nlem(lem); // The side effect says that if lem is added, then we should add the // secant point c for (tf,d). - lemSE[lem].d_secantPoint.push_back(std::make_tuple(tf, d, c)); + nlem.d_secantPoint.push_back(std::make_tuple(tf, d, c)); + lemmas.push_back(nlem); } return true; } @@ -1470,6 +1470,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..c80fa99e6 100644 --- a/src/theory/arith/transcendental_solver.h +++ b/src/theory/arith/nl/transcendental_solver.h @@ -2,9 +2,9 @@ /*! \file transcendental_solver.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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 * @@ -54,14 +55,13 @@ class TranscendentalSolver * model, and xts is the set of extended function terms that are active in * the current context. * - * This call may add lemmas to lems/lemsPp based on registering term + * This call may add lemmas to lems based on registering term * information (for example, purification of sine terms). */ void initLastCall(const std::vector<Node>& assertions, const std::vector<Node>& false_asserts, const std::vector<Node>& xts, - std::vector<Node>& lems, - std::vector<Node>& lemsPp); + std::vector<NlLemma>& lems); /** increment taylor degree */ void incrementTaylorDegree(); /** get taylor degree */ @@ -75,8 +75,8 @@ class TranscendentalSolver * was conflicting. */ bool preprocessAssertionsCheckModel(std::vector<Node>& assertions); - /** Process side effect se */ - void processSideEffect(const NlLemmaSideEffect& se); + /** Process side effects in lemma se */ + void processSideEffect(const NlLemma& se); //-------------------------------------------- lemma schemas /** check transcendental initial refine * @@ -94,7 +94,7 @@ class TranscendentalSolver * exp( x )>0 * x<0 => exp( x )<1 */ - std::vector<Node> checkTranscendentalInitialRefine(); + std::vector<NlLemma> checkTranscendentalInitialRefine(); /** check transcendental monotonic * @@ -108,7 +108,7 @@ class TranscendentalSolver * PI/2 > x > y > 0 => sin( x ) > sin( y ) * PI > x > y > PI/2 => sin( x ) < sin( y ) */ - std::vector<Node> checkTranscendentalMonotonic(); + std::vector<NlLemma> checkTranscendentalMonotonic(); /** check transcendental tangent planes * @@ -167,12 +167,8 @@ class TranscendentalSolver * ( 1 < y < PI/2 ) => (sin y) >= c1*(y+c2) * where c1, c2 are rationals (for brevity, omitted here) * such that c1 ~= .277 and c2 ~= 2.032. - * - * The argument lemSE is the "side effect" of the lemmas in the return - * value of this function (for details, see checkLastCall). */ - std::vector<Node> checkTranscendentalTangentPlanes( - std::map<Node, NlLemmaSideEffect>& lemSE); + std::vector<NlLemma> checkTranscendentalTangentPlanes(); /** check transcendental function refinement for tf * * This method is called by the above method for each "master" @@ -184,16 +180,13 @@ class TranscendentalSolver * * This runs Figure 3 of Cimatti et al., CADE 2017 for transcendental * function application tf for Taylor degree d. It may add a secant or - * tangent plane lemma to lems and its side effect (if one exists) - * to lemSE. + * tangent plane lemma to lems, which includes the side effect of the lemma + * (if one exists). * * It returns false if the bounds are not precise enough to add a * secant or tangent plane lemma. */ - bool checkTfTangentPlanesFun(Node tf, - unsigned d, - std::vector<Node>& lems, - std::map<Node, NlLemmaSideEffect>& lemSE); + bool checkTfTangentPlanesFun(Node tf, unsigned d, std::vector<NlLemma>& lems); //-------------------------------------------- end lemma schemas private: /** polynomial approximation bounds @@ -275,7 +268,7 @@ class TranscendentalSolver Node getDerivative(Node n, Node x); void mkPi(); - void getCurrentPiBounds(std::vector<Node>& lemmas); + void getCurrentPiBounds(std::vector<NlLemma>& lemmas); /** Make the node -pi <= a <= pi */ static Node mkValidPhase(Node a, Node pi); @@ -421,6 +414,7 @@ class TranscendentalSolver Node d_pi_bound[2]; }; /* class TranscendentalSolver */ +} // namespace nl } // namespace arith } // namespace theory } // namespace CVC4 diff --git a/src/theory/arith/normal_form.cpp b/src/theory/arith/normal_form.cpp index c0658b9af..f964f1628 100644 --- a/src/theory/arith/normal_form.cpp +++ b/src/theory/arith/normal_form.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -71,6 +71,12 @@ bool Variable::isLeafMember(Node n){ VarList::VarList(Node n) : NodeWrapper(n) { Assert(isSorted(begin(), end())); } +bool Variable::isIAndMember(Node n) +{ + return n.getKind() == kind::IAND && Polynomial::isMember(n[0]) + && Polynomial::isMember(n[1]); +} + bool Variable::isDivMember(Node n){ switch(n.getKind()){ case kind::DIVISION: diff --git a/src/theory/arith/normal_form.h b/src/theory/arith/normal_form.h index 8099339ae..484bdbf44 100644 --- a/src/theory/arith/normal_form.h +++ b/src/theory/arith/normal_form.h @@ -2,9 +2,9 @@ /*! \file normal_form.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andrew Reynolds + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -239,6 +239,7 @@ public: case kind::INTS_DIVISION_TOTAL: case kind::INTS_MODULUS_TOTAL: case kind::DIVISION_TOTAL: return isDivMember(n); + case kind::IAND: return isIAndMember(n); case kind::EXPONENTIAL: case kind::SINE: case kind::COSINE: @@ -264,6 +265,7 @@ public: } static bool isLeafMember(Node n); + static bool isIAndMember(Node n); static bool isDivMember(Node n); bool isDivLike() const{ return isDivMember(getNode()); diff --git a/src/theory/arith/operator_elim.cpp b/src/theory/arith/operator_elim.cpp new file mode 100644 index 000000000..593fbd584 --- /dev/null +++ b/src/theory/arith/operator_elim.cpp @@ -0,0 +1,508 @@ +/********************* */ +/*! \file operator_elim.cpp + ** \verbatim + ** Top contributors (to current version): + ** Tim King, Andrew Reynolds, Morgan Deters + ** 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 operator elimination for arithmetic + **/ + +#include "theory/arith/operator_elim.h" + +#include "expr/skolem_manager.h" +#include "options/arith_options.h" +#include "smt/logic_exception.h" +#include "theory/arith/arith_utilities.h" +#include "theory/rewriter.h" +#include "theory/theory.h" + +using namespace CVC4::kind; + +namespace CVC4 { +namespace theory { +namespace arith { + +OperatorElim::OperatorElim(const LogicInfo& info) : d_info(info) {} + +void OperatorElim::checkNonLinearLogic(Node term) +{ + if (d_info.isLinear()) + { + Trace("arith-logic") << "ERROR: Non-linear term in linear logic: " << term + << std::endl; + std::stringstream serr; + serr << "A non-linear fact was asserted to arithmetic in a linear logic." + << std::endl; + serr << "The fact in question: " << term << std::endl; + throw LogicException(serr.str()); + } +} + +Node OperatorElim::eliminateOperatorsRec(Node n) +{ + Trace("arith-elim") << "Begin elim: " << n << std::endl; + NodeManager* nm = NodeManager::currentNM(); + std::unordered_map<Node, Node, TNodeHashFunction> visited; + std::unordered_map<Node, Node, TNodeHashFunction>::iterator it; + std::vector<Node> visit; + Node cur; + visit.push_back(n); + do + { + cur = visit.back(); + visit.pop_back(); + it = visited.find(cur); + if (Theory::theoryOf(cur) != THEORY_ARITH) + { + visited[cur] = cur; + } + else if (it == visited.end()) + { + visited[cur] = Node::null(); + visit.push_back(cur); + for (const Node& cn : cur) + { + visit.push_back(cn); + } + } + else if (it->second.isNull()) + { + Node ret = cur; + bool childChanged = false; + std::vector<Node> children; + if (cur.getMetaKind() == metakind::PARAMETERIZED) + { + children.push_back(cur.getOperator()); + } + for (const Node& cn : cur) + { + it = visited.find(cn); + Assert(it != visited.end()); + Assert(!it->second.isNull()); + childChanged = childChanged || cn != it->second; + children.push_back(it->second); + } + if (childChanged) + { + ret = nm->mkNode(cur.getKind(), children); + } + Node retElim = eliminateOperators(ret); + if (retElim != ret) + { + // recursively eliminate operators in result, since some eliminations + // are defined in terms of other non-standard operators. + ret = eliminateOperatorsRec(retElim); + } + visited[cur] = ret; + } + } while (!visit.empty()); + Assert(visited.find(n) != visited.end()); + Assert(!visited.find(n)->second.isNull()); + return visited[n]; +} + +Node OperatorElim::eliminateOperators(Node node) +{ + NodeManager* nm = NodeManager::currentNM(); + SkolemManager* sm = nm->getSkolemManager(); + + Kind k = node.getKind(); + switch (k) + { + case TANGENT: + case COSECANT: + case SECANT: + case COTANGENT: + { + // these are eliminated by rewriting + return Rewriter::rewrite(node); + break; + } + case TO_INTEGER: + case IS_INTEGER: + { + Node toIntSkolem; + std::map<Node, Node>::const_iterator it = d_to_int_skolem.find(node[0]); + if (it == d_to_int_skolem.end()) + { + // node[0] - 1 < toIntSkolem <= node[0] + // -1 < toIntSkolem - node[0] <= 0 + // 0 <= node[0] - toIntSkolem < 1 + Node v = nm->mkBoundVar(nm->integerType()); + Node one = mkRationalNode(1); + Node zero = mkRationalNode(0); + Node diff = nm->mkNode(MINUS, node[0], v); + Node lem = mkInRange(diff, zero, one); + toIntSkolem = sm->mkSkolem( + v, lem, "toInt", "a conversion of a Real term to its Integer part"); + toIntSkolem = SkolemManager::getWitnessForm(toIntSkolem); + d_to_int_skolem[node[0]] = toIntSkolem; + } + else + { + toIntSkolem = (*it).second; + } + if (k == IS_INTEGER) + { + return nm->mkNode(EQUAL, node[0], toIntSkolem); + } + Assert(k == TO_INTEGER); + return toIntSkolem; + } + + case INTS_DIVISION_TOTAL: + case INTS_MODULUS_TOTAL: + { + Node den = Rewriter::rewrite(node[1]); + Node num = Rewriter::rewrite(node[0]); + Node intVar; + Node rw = nm->mkNode(k, num, den); + std::map<Node, Node>::const_iterator it = d_int_div_skolem.find(rw); + if (it == d_int_div_skolem.end()) + { + Node v = nm->mkBoundVar(nm->integerType()); + Node lem; + Node leqNum = nm->mkNode(LEQ, nm->mkNode(MULT, den, v), num); + if (den.isConst()) + { + const Rational& rat = den.getConst<Rational>(); + if (num.isConst() || rat == 0) + { + // just rewrite + return Rewriter::rewrite(node); + } + if (rat > 0) + { + lem = nm->mkNode( + AND, + leqNum, + nm->mkNode( + LT, + num, + nm->mkNode(MULT, + den, + nm->mkNode(PLUS, v, nm->mkConst(Rational(1)))))); + } + else + { + lem = nm->mkNode( + AND, + leqNum, + nm->mkNode( + LT, + num, + nm->mkNode( + MULT, + den, + nm->mkNode(PLUS, v, nm->mkConst(Rational(-1)))))); + } + } + else + { + checkNonLinearLogic(node); + lem = nm->mkNode( + AND, + nm->mkNode( + IMPLIES, + nm->mkNode(GT, den, nm->mkConst(Rational(0))), + nm->mkNode( + AND, + leqNum, + nm->mkNode( + LT, + num, + nm->mkNode( + MULT, + den, + nm->mkNode(PLUS, v, nm->mkConst(Rational(1))))))), + nm->mkNode( + IMPLIES, + nm->mkNode(LT, den, nm->mkConst(Rational(0))), + nm->mkNode( + AND, + leqNum, + nm->mkNode( + LT, + num, + nm->mkNode( + MULT, + den, + nm->mkNode( + PLUS, v, nm->mkConst(Rational(-1)))))))); + } + intVar = sm->mkSkolem( + v, lem, "linearIntDiv", "the result of an intdiv-by-k term"); + intVar = SkolemManager::getWitnessForm(intVar); + d_int_div_skolem[rw] = intVar; + } + else + { + intVar = (*it).second; + } + if (k == INTS_MODULUS_TOTAL) + { + Node nn = nm->mkNode(MINUS, num, nm->mkNode(MULT, den, intVar)); + return nn; + } + else + { + return intVar; + } + break; + } + case DIVISION_TOTAL: + { + Node num = Rewriter::rewrite(node[0]); + Node den = Rewriter::rewrite(node[1]); + if (den.isConst()) + { + // No need to eliminate here, can eliminate via rewriting later. + // Moreover, rewriting may change the type of this node from real to + // int, which impacts certain issues with subtyping. + return node; + } + checkNonLinearLogic(node); + Node var; + Node rw = nm->mkNode(k, num, den); + std::map<Node, Node>::const_iterator it = d_div_skolem.find(rw); + if (it == d_div_skolem.end()) + { + Node v = nm->mkBoundVar(nm->realType()); + Node lem = nm->mkNode(IMPLIES, + den.eqNode(nm->mkConst(Rational(0))).negate(), + nm->mkNode(MULT, den, v).eqNode(num)); + var = sm->mkSkolem( + v, lem, "nonlinearDiv", "the result of a non-linear div term"); + var = SkolemManager::getWitnessForm(var); + d_div_skolem[rw] = var; + } + else + { + var = (*it).second; + } + return var; + break; + } + case DIVISION: + { + Node num = Rewriter::rewrite(node[0]); + Node den = Rewriter::rewrite(node[1]); + Node ret = nm->mkNode(DIVISION_TOTAL, num, den); + if (!den.isConst() || den.getConst<Rational>().sgn() == 0) + { + checkNonLinearLogic(node); + Node divByZeroNum = getArithSkolemApp(num, ArithSkolemId::DIV_BY_ZERO); + Node denEq0 = nm->mkNode(EQUAL, den, nm->mkConst(Rational(0))); + ret = nm->mkNode(ITE, denEq0, divByZeroNum, ret); + } + return ret; + break; + } + + case INTS_DIVISION: + { + // partial function: integer div + Node num = Rewriter::rewrite(node[0]); + Node den = Rewriter::rewrite(node[1]); + Node ret = nm->mkNode(INTS_DIVISION_TOTAL, num, den); + if (!den.isConst() || den.getConst<Rational>().sgn() == 0) + { + checkNonLinearLogic(node); + Node intDivByZeroNum = + getArithSkolemApp(num, ArithSkolemId::INT_DIV_BY_ZERO); + Node denEq0 = nm->mkNode(EQUAL, den, nm->mkConst(Rational(0))); + ret = nm->mkNode(ITE, denEq0, intDivByZeroNum, ret); + } + return ret; + break; + } + + case INTS_MODULUS: + { + // partial function: mod + Node num = Rewriter::rewrite(node[0]); + Node den = Rewriter::rewrite(node[1]); + Node ret = nm->mkNode(INTS_MODULUS_TOTAL, num, den); + if (!den.isConst() || den.getConst<Rational>().sgn() == 0) + { + checkNonLinearLogic(node); + Node modZeroNum = getArithSkolemApp(num, ArithSkolemId::MOD_BY_ZERO); + Node denEq0 = nm->mkNode(EQUAL, den, nm->mkConst(Rational(0))); + ret = nm->mkNode(ITE, denEq0, modZeroNum, ret); + } + return ret; + break; + } + + case ABS: + { + return nm->mkNode(ITE, + nm->mkNode(LT, node[0], nm->mkConst(Rational(0))), + nm->mkNode(UMINUS, node[0]), + node[0]); + break; + } + case SQRT: + case ARCSINE: + case ARCCOSINE: + case ARCTANGENT: + case ARCCOSECANT: + case ARCSECANT: + case ARCCOTANGENT: + { + checkNonLinearLogic(node); + // eliminate inverse functions here + std::map<Node, Node>::const_iterator it = + d_nlin_inverse_skolem.find(node); + if (it == d_nlin_inverse_skolem.end()) + { + Node var = nm->mkBoundVar(nm->realType()); + Node lem; + if (k == SQRT) + { + Node skolemApp = getArithSkolemApp(node[0], ArithSkolemId::SQRT); + Node uf = skolemApp.eqNode(var); + Node nonNeg = + nm->mkNode(AND, nm->mkNode(MULT, var, var).eqNode(node[0]), uf); + + // sqrt(x) reduces to: + // witness y. ite(x >= 0.0, y * y = x ^ y = Uf(x), y = Uf(x)) + // + // Uf(x) makes sure that the reduction still behaves like a function, + // otherwise the reduction of (x = 1) ^ (sqrt(x) != sqrt(1)) would be + // satisfiable. On the original formula, this would require that we + // simultaneously interpret sqrt(1) as 1 and -1, which is not a valid + // model. + lem = nm->mkNode(ITE, + nm->mkNode(GEQ, node[0], nm->mkConst(Rational(0))), + nonNeg, + uf); + } + else + { + Node pi = mkPi(); + + // range of the skolem + Node rlem; + if (k == ARCSINE || k == ARCTANGENT || k == ARCCOSECANT) + { + Node half = nm->mkConst(Rational(1) / Rational(2)); + Node pi2 = nm->mkNode(MULT, half, pi); + Node npi2 = nm->mkNode(MULT, nm->mkConst(Rational(-1)), pi2); + // -pi/2 < var <= pi/2 + rlem = nm->mkNode( + AND, nm->mkNode(LT, npi2, var), nm->mkNode(LEQ, var, pi2)); + } + else + { + // 0 <= var < pi + rlem = nm->mkNode(AND, + nm->mkNode(LEQ, nm->mkConst(Rational(0)), var), + nm->mkNode(LT, var, pi)); + } + + Kind rk = k == ARCSINE + ? SINE + : (k == ARCCOSINE + ? COSINE + : (k == ARCTANGENT + ? TANGENT + : (k == ARCCOSECANT + ? COSECANT + : (k == ARCSECANT ? SECANT + : COTANGENT)))); + Node invTerm = nm->mkNode(rk, var); + lem = nm->mkNode(AND, rlem, invTerm.eqNode(node[0])); + } + Assert(!lem.isNull()); + Node ret = sm->mkSkolem( + var, + lem, + "tfk", + "Skolem to eliminate a non-standard transcendental function"); + ret = SkolemManager::getWitnessForm(ret); + d_nlin_inverse_skolem[node] = ret; + return ret; + } + return (*it).second; + break; + } + + default: break; + } + return node; +} + +Node OperatorElim::getArithSkolem(ArithSkolemId asi) +{ + std::map<ArithSkolemId, Node>::iterator it = d_arith_skolem.find(asi); + if (it == d_arith_skolem.end()) + { + NodeManager* nm = NodeManager::currentNM(); + + TypeNode tn; + std::string name; + std::string desc; + switch (asi) + { + case ArithSkolemId::DIV_BY_ZERO: + tn = nm->realType(); + name = std::string("divByZero"); + desc = std::string("partial real division"); + break; + case ArithSkolemId::INT_DIV_BY_ZERO: + tn = nm->integerType(); + name = std::string("intDivByZero"); + desc = std::string("partial int division"); + break; + case ArithSkolemId::MOD_BY_ZERO: + tn = nm->integerType(); + name = std::string("modZero"); + desc = std::string("partial modulus"); + break; + case ArithSkolemId::SQRT: + tn = nm->realType(); + name = std::string("sqrtUf"); + desc = std::string("partial sqrt"); + break; + default: Unhandled(); + } + + Node skolem; + if (options::arithNoPartialFun()) + { + // partial function: division + skolem = nm->mkSkolem(name, tn, desc, NodeManager::SKOLEM_EXACT_NAME); + } + else + { + // partial function: division + skolem = nm->mkSkolem(name, + nm->mkFunctionType(tn, tn), + desc, + NodeManager::SKOLEM_EXACT_NAME); + } + d_arith_skolem[asi] = skolem; + return skolem; + } + return it->second; +} + +Node OperatorElim::getArithSkolemApp(Node n, ArithSkolemId asi) +{ + Node skolem = getArithSkolem(asi); + if (!options::arithNoPartialFun()) + { + skolem = NodeManager::currentNM()->mkNode(APPLY_UF, skolem, n); + } + return skolem; +} + +} // namespace arith +} // namespace theory +} // namespace CVC4 diff --git a/src/theory/arith/operator_elim.h b/src/theory/arith/operator_elim.h new file mode 100644 index 000000000..2cdf9bc49 --- /dev/null +++ b/src/theory/arith/operator_elim.h @@ -0,0 +1,123 @@ +/********************* */ +/*! \file operator_elim.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 Operator elimination for arithmetic + **/ + +#pragma once + +#include <map> + +#include "expr/node.h" +#include "theory/logic_info.h" + +namespace CVC4 { +namespace theory { +namespace arith { + +class OperatorElim +{ + public: + OperatorElim(const LogicInfo& info); + ~OperatorElim() {} + /** + * Eliminate operators in term n. If n has top symbol that is not a core + * one (including division, int division, mod, to_int, is_int, syntactic sugar + * transcendental functions), then we replace it by a form that eliminates + * that operator. This may involve the introduction of witness terms. + * + * One exception to the above rule is that we may leave certain applications + * like (/ 4 1) unchanged, since replacing this by 4 changes its type from + * real to int. This is important for some subtyping issues during + * expandDefinition. Moreover, applications like this can be eliminated + * trivially later by rewriting. + * + * This method is called both during expandDefinition and during ppRewrite. + * + * @param n The node to eliminate operators from. + * @return The (single step) eliminated form of n. + */ + Node eliminateOperators(Node n); + /** + * Recursively ensure that n has no non-standard operators. This applies + * the above method on all subterms of n. + * + * @param n The node to eliminate operators from. + * @return The eliminated form of n. + */ + Node eliminateOperatorsRec(Node n); + + private: + /** Logic info of the owner of this class */ + const LogicInfo& d_info; + + /** + * Maps for Skolems for to-integer, real/integer div-by-k, and inverse + * non-linear operators that are introduced during ppRewriteTerms. + */ + std::map<Node, Node> d_to_int_skolem; + std::map<Node, Node> d_div_skolem; + std::map<Node, Node> d_int_div_skolem; + std::map<Node, Node> d_nlin_inverse_skolem; + + /** Arithmetic skolem identifier */ + enum class ArithSkolemId + { + /* an uninterpreted function f s.t. f(x) = x / 0.0 (real division) */ + DIV_BY_ZERO, + /* an uninterpreted function f s.t. f(x) = x / 0 (integer division) */ + INT_DIV_BY_ZERO, + /* an uninterpreted function f s.t. f(x) = x mod 0 */ + MOD_BY_ZERO, + /* an uninterpreted function f s.t. f(x) = sqrt(x) */ + SQRT, + }; + + /** + * Function symbols used to implement: + * (1) Uninterpreted division-by-zero semantics. Needed to deal with partial + * division function ("/"), + * (2) Uninterpreted int-division-by-zero semantics. Needed to deal with + * partial function "div", + * (3) Uninterpreted mod-zero semantics. Needed to deal with partial + * function "mod". + * + * If the option arithNoPartialFun() is enabled, then the range of this map + * stores Skolem constants instead of Skolem functions, meaning that the + * function-ness of e.g. division by zero is ignored. + */ + std::map<ArithSkolemId, Node> d_arith_skolem; + /** get arithmetic skolem + * + * Returns the Skolem in the above map for the given id, creating it if it + * does not already exist. + */ + Node getArithSkolem(ArithSkolemId asi); + /** get arithmetic skolem application + * + * By default, this returns the term f( n ), where f is the Skolem function + * for the identifier asi. + * + * If the option arithNoPartialFun is enabled, this returns f, where f is + * the Skolem constant for the identifier asi. + */ + Node getArithSkolemApp(Node n, ArithSkolemId asi); + + /** + * Called when a non-linear term n is given to this class. Throw an exception + * if the logic is linear. + */ + void checkNonLinearLogic(Node term); +}; + +} // namespace arith +} // namespace theory +} // namespace CVC4 diff --git a/src/theory/arith/partial_model.cpp b/src/theory/arith/partial_model.cpp index 855b673c5..9b2c38d81 100644 --- a/src/theory/arith/partial_model.cpp +++ b/src/theory/arith/partial_model.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/partial_model.h b/src/theory/arith/partial_model.h index 5006c6a9c..43c265278 100644 --- a/src/theory/arith/partial_model.h +++ b/src/theory/arith/partial_model.h @@ -2,9 +2,9 @@ /*! \file partial_model.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/proof_checker.cpp b/src/theory/arith/proof_checker.cpp new file mode 100644 index 000000000..5b7a3d63a --- /dev/null +++ b/src/theory/arith/proof_checker.cpp @@ -0,0 +1,269 @@ +/********************* */ +/*! \file proof_checker.cpp + ** \verbatim + ** Top contributors (to current version): + ** Alex Ozdemir + ** 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 arithmetic proof checker + **/ + +#include "theory/arith/proof_checker.h" + +#include <iostream> +#include <set> + +#include "expr/skolem_manager.h" +#include "theory/arith/arith_utilities.h" +#include "theory/arith/constraint.h" +#include "theory/arith/normal_form.h" +#include "theory/arith/operator_elim.h" + +namespace CVC4 { +namespace theory { +namespace arith { + +void ArithProofRuleChecker::registerTo(ProofChecker* pc) +{ + pc->registerChecker(PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS, this); + pc->registerChecker(PfRule::ARITH_TRICHOTOMY, this); + pc->registerChecker(PfRule::INT_TIGHT_UB, this); + pc->registerChecker(PfRule::INT_TIGHT_LB, this); + pc->registerChecker(PfRule::INT_TRUST, this); + pc->registerChecker(PfRule::ARITH_OP_ELIM_AXIOM, this); +} + +Node ArithProofRuleChecker::checkInternal(PfRule id, + const std::vector<Node>& children, + const std::vector<Node>& args) +{ + if (Debug.isOn("arith::pf::check")) + { + Debug("arith::pf::check") << "Arith PfRule:" << id << std::endl; + Debug("arith::pf::check") << " children: " << std::endl; + for (const auto& c : children) + { + Debug("arith::pf::check") << " * " << c << std::endl; + } + Debug("arith::pf::check") << " args:" << std::endl; + for (const auto& c : args) + { + Debug("arith::pf::check") << " * " << c << std::endl; + } + } + switch (id) + { + case PfRule::ARITH_SCALE_SUM_UPPER_BOUNDS: + { + // Children: (P1:l1, ..., Pn:ln) + // where each li is an ArithLiteral + // not(= ...) is dis-allowed! + // + // Arguments: (k1, ..., kn), non-zero reals + // --------------------- + // Conclusion: (>< (* k t1) (* k t2)) + // where >< is the fusion of the combination of the ><i, (flipping each + // it its ki is negative). >< is always one of <, <= NB: this implies + // that lower bounds must have negative ki, + // and upper bounds must have positive ki. + // t1 is the sum of the polynomials. + // t2 is the sum of the constants. + Assert(children.size() == args.size()); + if (children.size() < 2) + { + return Node::null(); + } + + // Whether a strict inequality is in the sum. + auto nm = NodeManager::currentNM(); + bool strict = false; + NodeBuilder<> leftSum(Kind::PLUS); + NodeBuilder<> rightSum(Kind::PLUS); + for (size_t i = 0; i < children.size(); ++i) + { + Rational scalar = args[i].getConst<Rational>(); + if (scalar == 0) + { + Debug("arith::pf::check") << "Error: zero scalar" << std::endl; + return Node::null(); + } + + // Adjust strictness + switch (children[i].getKind()) + { + case Kind::GT: + case Kind::LT: + { + strict = true; + break; + } + case Kind::GEQ: + case Kind::LEQ: + case Kind::EQUAL: + { + break; + } + default: + { + Debug("arith::pf::check") + << "Bad kind: " << children[i].getKind() << std::endl; + } + } + // Check sign + switch (children[i].getKind()) + { + case Kind::GT: + case Kind::GEQ: + { + if (scalar > 0) + { + Debug("arith::pf::check") + << "Positive scalar for lower bound: " << scalar << " for " + << children[i] << std::endl; + return Node::null(); + } + break; + } + case Kind::LEQ: + case Kind::LT: + { + if (scalar < 0) + { + Debug("arith::pf::check") + << "Negative scalar for upper bound: " << scalar << " for " + << children[i] << std::endl; + return Node::null(); + } + break; + } + case Kind::EQUAL: + { + break; + } + default: + { + Debug("arith::pf::check") + << "Bad kind: " << children[i].getKind() << std::endl; + } + } + leftSum << nm->mkNode( + Kind::MULT, children[i][0], nm->mkConst<Rational>(scalar)); + rightSum << nm->mkNode( + Kind::MULT, children[i][1], nm->mkConst<Rational>(scalar)); + } + Node r = nm->mkNode(strict ? Kind::LT : Kind::LEQ, + leftSum.constructNode(), + rightSum.constructNode()); + return r; + } + case PfRule::INT_TIGHT_LB: + { + // Children: (P:(> i c)) + // where i has integer type. + // Arguments: none + // --------------------- + // Conclusion: (>= i leastIntGreaterThan(c)}) + if (children.size() != 1 + || (children[0].getKind() != Kind::GT + && children[0].getKind() != Kind::GEQ) + || !children[0][0].getType().isInteger() + || children[0][1].getKind() != Kind::CONST_RATIONAL) + { + Debug("arith::pf::check") << "Illformed input: " << children; + return Node::null(); + } + else + { + Rational originalBound = children[0][1].getConst<Rational>(); + Rational newBound = leastIntGreaterThan(originalBound); + auto nm = NodeManager::currentNM(); + Node rational = nm->mkConst<Rational>(newBound); + return nm->mkNode(kind::GEQ, children[0][0], rational); + } + } + case PfRule::INT_TIGHT_UB: + { + // ======== Tightening Strict Integer Upper Bounds + // Children: (P:(< i c)) + // where i has integer type. + // Arguments: none + // --------------------- + // Conclusion: (<= i greatestIntLessThan(c)}) + if (children.size() != 1 + || (children[0].getKind() != Kind::LT + && children[0].getKind() != Kind::LEQ) + || !children[0][0].getType().isInteger() + || children[0][1].getKind() != Kind::CONST_RATIONAL) + { + Debug("arith::pf::check") << "Illformed input: " << children; + return Node::null(); + } + else + { + Rational originalBound = children[0][1].getConst<Rational>(); + Rational newBound = greatestIntLessThan(originalBound); + auto nm = NodeManager::currentNM(); + Node rational = nm->mkConst<Rational>(newBound); + return nm->mkNode(kind::LEQ, children[0][0], rational); + } + } + case PfRule::ARITH_TRICHOTOMY: + { + Node a = negateProofLiteral(children[0]); + Node b = negateProofLiteral(children[1]); + Node c = args[0]; + if (a[0] == b[0] && b[0] == c[0] && a[1] == b[1] && b[1] == c[1]) + { + std::set<Kind> cmps; + cmps.insert(a.getKind()); + cmps.insert(b.getKind()); + cmps.insert(c.getKind()); + if (cmps.count(Kind::EQUAL) == 0) + { + Debug("arith::pf::check") << "Error: No = " << std::endl; + return Node::null(); + } + if (cmps.count(Kind::GT) == 0) + { + Debug("arith::pf::check") << "Error: No > " << std::endl; + return Node::null(); + } + if (cmps.count(Kind::LT) == 0) + { + Debug("arith::pf::check") << "Error: No < " << std::endl; + return Node::null(); + } + return args[0]; + } + else + { + Debug("arith::pf::check") + << "Error: Different polynomials / values" << std::endl; + Debug("arith::pf::check") << " a: " << a << std::endl; + Debug("arith::pf::check") << " b: " << b << std::endl; + Debug("arith::pf::check") << " c: " << c << std::endl; + return Node::null(); + } + // Check that all have the same constant: + } + case PfRule::INT_TRUST: + { + Assert(args.size() == 1); + return args[0]; + } + case PfRule::ARITH_OP_ELIM_AXIOM: + { + Assert(children.empty()); + Assert(args.size() == 1); + return OperatorElim::getAxiomFor(args[0]); + } + default: return Node::null(); + } +} +} // namespace arith +} // namespace theory +} // namespace CVC4 diff --git a/src/theory/arith/proof_checker.h b/src/theory/arith/proof_checker.h new file mode 100644 index 000000000..b8a5d0df7 --- /dev/null +++ b/src/theory/arith/proof_checker.h @@ -0,0 +1,49 @@ +/********************* */ +/*! \file proof_checker.h + ** \verbatim + ** Top contributors (to current version): + ** Alex Ozdemir + ** 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 Arithmetic proof checker utility + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__THEORY__ARITH__PROOF_CHECKER_H +#define CVC4__THEORY__ARITH__PROOF_CHECKER_H + +#include "expr/node.h" +#include "expr/proof_checker.h" +#include "expr/proof_node.h" + +namespace CVC4 { +namespace theory { +namespace arith { + +/** A checker for arithmetic reasoning in proofs */ +class ArithProofRuleChecker : public ProofRuleChecker +{ + public: + ArithProofRuleChecker() {} + ~ArithProofRuleChecker() {} + + /** 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 arith +} // namespace theory +} // namespace CVC4 + +#endif /* CVC4__THEORY__ARITH__PROOF_CHECKER_H */ diff --git a/src/theory/arith/simplex.cpp b/src/theory/arith/simplex.cpp index bf27af36a..50248167e 100644 --- a/src/theory/arith/simplex.cpp +++ b/src/theory/arith/simplex.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/simplex.h b/src/theory/arith/simplex.h index 5bd6034d2..6a297113e 100644 --- a/src/theory/arith/simplex.h +++ b/src/theory/arith/simplex.h @@ -2,9 +2,9 @@ /*! \file simplex.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Clark Barrett + ** Tim King, Mathias Preiner, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/simplex_update.cpp b/src/theory/arith/simplex_update.cpp index 011e07143..613a30a07 100644 --- a/src/theory/arith/simplex_update.cpp +++ b/src/theory/arith/simplex_update.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/simplex_update.h b/src/theory/arith/simplex_update.h index b1153d36f..7668bb2f0 100644 --- a/src/theory/arith/simplex_update.h +++ b/src/theory/arith/simplex_update.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/soi_simplex.cpp b/src/theory/arith/soi_simplex.cpp index 1876f4b88..71d5fda8b 100644 --- a/src/theory/arith/soi_simplex.cpp +++ b/src/theory/arith/soi_simplex.cpp @@ -2,9 +2,9 @@ /*! \file soi_simplex.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andres Noetzli + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/soi_simplex.h b/src/theory/arith/soi_simplex.h index 6fd8cf7c1..95c19a50a 100644 --- a/src/theory/arith/soi_simplex.h +++ b/src/theory/arith/soi_simplex.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/tableau.cpp b/src/theory/arith/tableau.cpp index 82b46bf30..4c119ba36 100644 --- a/src/theory/arith/tableau.cpp +++ b/src/theory/arith/tableau.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/tableau.h b/src/theory/arith/tableau.h index 3f3bf883a..1affc61d4 100644 --- a/src/theory/arith/tableau.h +++ b/src/theory/arith/tableau.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/tableau_sizes.cpp b/src/theory/arith/tableau_sizes.cpp index aec7b0384..f54c3dfef 100644 --- a/src/theory/arith/tableau_sizes.cpp +++ b/src/theory/arith/tableau_sizes.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/tableau_sizes.h b/src/theory/arith/tableau_sizes.h index 95820dc93..085ff9640 100644 --- a/src/theory/arith/tableau_sizes.h +++ b/src/theory/arith/tableau_sizes.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/theory_arith.cpp b/src/theory/arith/theory_arith.cpp index e65369f96..8b4747927 100644 --- a/src/theory/arith/theory_arith.cpp +++ b/src/theory/arith/theory_arith.cpp @@ -2,9 +2,9 @@ /*! \file theory_arith.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Dejan Jovanovic, Andrew Reynolds + ** Tim King, Andrew Reynolds, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -40,12 +40,15 @@ TheoryArith::TheoryArith(context::Context* c, context::UserContext* u, , d_proofRecorder(nullptr) { smtStatisticsRegistry()->registerStat(&d_ppRewriteTimer); - if (options::nlExt()) { + // if logic is non-linear + if (logicInfo.isTheoryEnabled(THEORY_ARITH) && !logicInfo.isLinear()) + { setupExtTheory(); getExtTheory()->addFunctionKind(kind::NONLINEAR_MULT); getExtTheory()->addFunctionKind(kind::EXPONENTIAL); getExtTheory()->addFunctionKind(kind::SINE); getExtTheory()->addFunctionKind(kind::PI); + getExtTheory()->addFunctionKind(kind::IAND); } } @@ -72,6 +75,10 @@ void TheoryArith::finishInit() { // witness is used to eliminate square root tm->setUnevaluatedKind(kind::WITNESS); + // we only need to add the operators that are not syntax sugar + tm->setUnevaluatedKind(kind::EXPONENTIAL); + tm->setUnevaluatedKind(kind::SINE); + tm->setUnevaluatedKind(kind::PI); } } diff --git a/src/theory/arith/theory_arith.h b/src/theory/arith/theory_arith.h index 8672f7145..5b68e3e7a 100644 --- a/src/theory/arith/theory_arith.h +++ b/src/theory/arith/theory_arith.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Alex Ozdemir, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp index 09b6d742a..d0da29e7a 100644 --- a/src/theory/arith/theory_arith_private.cpp +++ b/src/theory/arith/theory_arith_private.cpp @@ -2,9 +2,9 @@ /*! \file theory_arith_private.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Andrew Reynolds, Morgan Deters + ** Tim King, Andrew Reynolds, Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -34,7 +34,7 @@ #include "expr/node.h" #include "expr/node_algorithm.h" #include "expr/node_builder.h" -#include "expr/proof_skolem_cache.h" +#include "expr/skolem_manager.h" #include "options/arith_options.h" #include "options/smt_options.h" // for incrementalSolving() #include "preprocessing/util/ite_utilities.h" @@ -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" @@ -156,13 +156,12 @@ TheoryArithPrivate::TheoryArithPrivate(TheoryArith& containing, d_solveIntMaybeHelp(0u), d_solveIntAttempts(0u), d_statistics(), - d_to_int_skolem(u), - d_div_skolem(u), - d_int_div_skolem(u), - d_nlin_inverse_skolem(u) + d_opElim(logicInfo) { - if( options::nlExt() ){ - d_nonlinearExtension = new NonlinearExtension( + // only need to create if non-linear logic + if (logicInfo.isTheoryEnabled(THEORY_ARITH) && !logicInfo.isLinear()) + { + d_nonlinearExtension = new nl::NonlinearExtension( containing, d_congruenceManager.getEqualityEngine()); } } @@ -1088,440 +1087,16 @@ Node TheoryArithPrivate::ppRewriteTerms(TNode n) { // example, quantifier instantiation may use TO_INTEGER terms; SyGuS may // introduce non-standard arithmetic terms appearing in grammars. // call eliminate operators - Node nn = eliminateOperators(n); + Node nn = d_opElim.eliminateOperators(n); if (nn != n) { // since elimination may introduce new operators to eliminate, we must // recursively eliminate result - return eliminateOperatorsRec(nn); + return d_opElim.eliminateOperatorsRec(nn); } return n; } -void TheoryArithPrivate::checkNonLinearLogic(Node term) -{ - if (getLogicInfo().isLinear()) - { - Trace("arith-logic") << "ERROR: Non-linear term in linear logic: " << term - << std::endl; - std::stringstream serr; - serr << "A non-linear fact was asserted to arithmetic in a linear logic." - << std::endl; - serr << "The fact in question: " << term << endl; - throw LogicException(serr.str()); - } -} - -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; - std::unordered_map<Node, Node, TNodeHashFunction>::iterator it; - std::vector<Node> visit; - Node cur; - visit.push_back(n); - do - { - cur = visit.back(); - visit.pop_back(); - it = visited.find(cur); - if (Theory::theoryOf(cur) != THEORY_ARITH) - { - visited[cur] = cur; - } - 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) - { - visit.push_back(cn); - } - } - } - else if (it->second.isNull()) - { - Node ret = cur; - bool childChanged = false; - std::vector<Node> children; - if (cur.getMetaKind() == metakind::PARAMETERIZED) - { - children.push_back(cur.getOperator()); - } - for (const Node& cn : cur) - { - it = visited.find(cn); - Assert(it != visited.end()); - Assert(!it->second.isNull()); - childChanged = childChanged || cn != it->second; - children.push_back(it->second); - } - if (childChanged) - { - ret = nm->mkNode(cur.getKind(), children); - } - Node retElim = eliminateOperators(ret); - if (retElim != ret) - { - // recursively eliminate operators in result, since some eliminations - // are defined in terms of other non-standard operators. - ret = eliminateOperatorsRec(retElim); - } - cur.setAttribute(aeoa, ret); - visited[cur] = ret; - } - } while (!visit.empty()); - Assert(visited.find(n) != visited.end()); - Assert(!visited.find(n)->second.isNull()); - return visited[n]; -} - -Node TheoryArithPrivate::eliminateOperators(Node node) -{ - NodeManager* nm = NodeManager::currentNM(); - - Kind k = node.getKind(); - switch (k) - { - case kind::TANGENT: - case kind::COSECANT: - case kind::SECANT: - case kind::COTANGENT: - { - // these are eliminated by rewriting - return Rewriter::rewrite(node); - break; - } - case kind::TO_INTEGER: - case kind::IS_INTEGER: - { - Node toIntSkolem; - NodeMap::const_iterator it = d_to_int_skolem.find(node[0]); - if (it == d_to_int_skolem.end()) - { - // node[0] - 1 < toIntSkolem <= node[0] - // -1 < toIntSkolem - node[0] <= 0 - // 0 <= node[0] - toIntSkolem < 1 - Node v = nm->mkBoundVar(nm->integerType()); - Node one = mkRationalNode(1); - Node zero = mkRationalNode(0); - Node diff = nm->mkNode(kind::MINUS, node[0], v); - Node lem = mkInRange(diff, zero, one); - toIntSkolem = ProofSkolemCache::mkSkolem( - v, lem, "toInt", "a conversion of a Real term to its Integer part"); - toIntSkolem = ProofSkolemCache::getWitnessForm(toIntSkolem); - d_to_int_skolem[node[0]] = toIntSkolem; - } - else - { - toIntSkolem = (*it).second; - } - if (k == kind::IS_INTEGER) - { - return nm->mkNode(kind::EQUAL, node[0], toIntSkolem); - } - Assert(k == kind::TO_INTEGER); - return toIntSkolem; - } - - case kind::INTS_DIVISION_TOTAL: - case kind::INTS_MODULUS_TOTAL: - { - Node den = Rewriter::rewrite(node[1]); - Node num = Rewriter::rewrite(node[0]); - Node intVar; - Node rw = nm->mkNode(k, num, den); - NodeMap::const_iterator it = d_int_div_skolem.find(rw); - if (it == d_int_div_skolem.end()) - { - Node v = nm->mkBoundVar(nm->integerType()); - Node lem; - Node leqNum = nm->mkNode(LEQ, nm->mkNode(MULT, den, v), num); - if (den.isConst()) - { - const Rational& rat = den.getConst<Rational>(); - if (num.isConst() || rat == 0) - { - // just rewrite - return Rewriter::rewrite(node); - } - if (rat > 0) - { - lem = nm->mkNode( - AND, - leqNum, - nm->mkNode( - LT, - num, - nm->mkNode(MULT, - den, - nm->mkNode(PLUS, v, nm->mkConst(Rational(1)))))); - } - else - { - lem = nm->mkNode( - AND, - leqNum, - nm->mkNode( - LT, - num, - nm->mkNode( - MULT, - den, - nm->mkNode(PLUS, v, nm->mkConst(Rational(-1)))))); - } - } - else - { - checkNonLinearLogic(node); - lem = nm->mkNode( - AND, - nm->mkNode( - IMPLIES, - nm->mkNode(GT, den, nm->mkConst(Rational(0))), - nm->mkNode( - AND, - leqNum, - nm->mkNode( - LT, - num, - nm->mkNode( - MULT, - den, - nm->mkNode(PLUS, v, nm->mkConst(Rational(1))))))), - nm->mkNode( - IMPLIES, - nm->mkNode(LT, den, nm->mkConst(Rational(0))), - nm->mkNode( - AND, - leqNum, - nm->mkNode( - LT, - num, - nm->mkNode( - MULT, - den, - nm->mkNode( - PLUS, v, nm->mkConst(Rational(-1)))))))); - } - intVar = ProofSkolemCache::mkSkolem( - v, lem, "linearIntDiv", "the result of an intdiv-by-k term"); - intVar = ProofSkolemCache::getWitnessForm(intVar); - d_int_div_skolem[rw] = intVar; - } - else - { - intVar = (*it).second; - } - if (k == kind::INTS_MODULUS_TOTAL) - { - Node nn = - nm->mkNode(kind::MINUS, num, nm->mkNode(kind::MULT, den, intVar)); - return nn; - } - else - { - return intVar; - } - break; - } - case kind::DIVISION_TOTAL: - { - Node num = Rewriter::rewrite(node[0]); - Node den = Rewriter::rewrite(node[1]); - if (den.isConst()) - { - // No need to eliminate here, can eliminate via rewriting later. - // Moreover, rewriting may change the type of this node from real to - // int, which impacts certain issues with subtyping. - return node; - } - checkNonLinearLogic(node); - Node var; - Node rw = nm->mkNode(k, num, den); - NodeMap::const_iterator it = d_div_skolem.find(rw); - if (it == d_div_skolem.end()) - { - Node v = nm->mkBoundVar(nm->realType()); - Node lem = nm->mkNode(IMPLIES, - den.eqNode(nm->mkConst(Rational(0))).negate(), - nm->mkNode(MULT, den, v).eqNode(num)); - var = ProofSkolemCache::mkSkolem( - v, lem, "nonlinearDiv", "the result of a non-linear div term"); - var = ProofSkolemCache::getWitnessForm(var); - d_div_skolem[rw] = var; - } - else - { - var = (*it).second; - } - return var; - break; - } - case kind::DIVISION: - { - Node num = Rewriter::rewrite(node[0]); - Node den = Rewriter::rewrite(node[1]); - Node ret = nm->mkNode(kind::DIVISION_TOTAL, num, den); - if (!den.isConst() || den.getConst<Rational>().sgn() == 0) - { - checkNonLinearLogic(node); - Node divByZeroNum = getArithSkolemApp(num, ArithSkolemId::DIV_BY_ZERO); - Node denEq0 = nm->mkNode(kind::EQUAL, den, nm->mkConst(Rational(0))); - ret = nm->mkNode(kind::ITE, denEq0, divByZeroNum, ret); - } - return ret; - break; - } - - case kind::INTS_DIVISION: - { - // partial function: integer div - Node num = Rewriter::rewrite(node[0]); - Node den = Rewriter::rewrite(node[1]); - Node ret = nm->mkNode(kind::INTS_DIVISION_TOTAL, num, den); - if (!den.isConst() || den.getConst<Rational>().sgn() == 0) - { - checkNonLinearLogic(node); - Node intDivByZeroNum = - getArithSkolemApp(num, ArithSkolemId::INT_DIV_BY_ZERO); - Node denEq0 = nm->mkNode(kind::EQUAL, den, nm->mkConst(Rational(0))); - ret = nm->mkNode(kind::ITE, denEq0, intDivByZeroNum, ret); - } - return ret; - break; - } - - case kind::INTS_MODULUS: - { - // partial function: mod - Node num = Rewriter::rewrite(node[0]); - Node den = Rewriter::rewrite(node[1]); - Node ret = nm->mkNode(kind::INTS_MODULUS_TOTAL, num, den); - if (!den.isConst() || den.getConst<Rational>().sgn() == 0) - { - checkNonLinearLogic(node); - Node modZeroNum = getArithSkolemApp(num, ArithSkolemId::MOD_BY_ZERO); - Node denEq0 = nm->mkNode(kind::EQUAL, den, nm->mkConst(Rational(0))); - ret = nm->mkNode(kind::ITE, denEq0, modZeroNum, ret); - } - return ret; - break; - } - - case kind::ABS: - { - return nm->mkNode(kind::ITE, - nm->mkNode(kind::LT, node[0], nm->mkConst(Rational(0))), - nm->mkNode(kind::UMINUS, node[0]), - node[0]); - break; - } - case kind::SQRT: - case kind::ARCSINE: - case kind::ARCCOSINE: - case kind::ARCTANGENT: - case kind::ARCCOSECANT: - case kind::ARCSECANT: - case kind::ARCCOTANGENT: - { - checkNonLinearLogic(node); - // eliminate inverse functions here - NodeMap::const_iterator it = d_nlin_inverse_skolem.find(node); - if (it == d_nlin_inverse_skolem.end()) - { - Node var = nm->mkBoundVar(nm->realType()); - Node lem; - if (k == kind::SQRT) - { - Node skolemApp = getArithSkolemApp(node[0], ArithSkolemId::SQRT); - Node uf = skolemApp.eqNode(var); - Node nonNeg = nm->mkNode( - kind::AND, nm->mkNode(kind::MULT, var, var).eqNode(node[0]), uf); - - // sqrt(x) reduces to: - // witness y. ite(x >= 0.0, y * y = x ^ y = Uf(x), y = Uf(x)) - // - // Uf(x) makes sure that the reduction still behaves like a function, - // otherwise the reduction of (x = 1) ^ (sqrt(x) != sqrt(1)) would be - // satisfiable. On the original formula, this would require that we - // simultaneously interpret sqrt(1) as 1 and -1, which is not a valid - // model. - lem = nm->mkNode( - kind::ITE, - nm->mkNode(kind::GEQ, node[0], nm->mkConst(Rational(0))), - nonNeg, - uf); - } - else - { - Node pi = mkPi(); - - // range of the skolem - Node rlem; - if (k == kind::ARCSINE || k == ARCTANGENT || k == ARCCOSECANT) - { - Node half = nm->mkConst(Rational(1) / Rational(2)); - Node pi2 = nm->mkNode(kind::MULT, half, pi); - Node npi2 = nm->mkNode(kind::MULT, nm->mkConst(Rational(-1)), pi2); - // -pi/2 < var <= pi/2 - rlem = nm->mkNode( - AND, nm->mkNode(LT, npi2, var), nm->mkNode(LEQ, var, pi2)); - } - else - { - // 0 <= var < pi - rlem = nm->mkNode(AND, - nm->mkNode(LEQ, nm->mkConst(Rational(0)), var), - nm->mkNode(LT, var, pi)); - } - - Kind rk = k == kind::ARCSINE - ? kind::SINE - : (k == kind::ARCCOSINE - ? kind::COSINE - : (k == kind::ARCTANGENT - ? kind::TANGENT - : (k == kind::ARCCOSECANT - ? kind::COSECANT - : (k == kind::ARCSECANT - ? kind::SECANT - : kind::COTANGENT)))); - Node invTerm = nm->mkNode(rk, var); - lem = nm->mkNode(AND, rlem, invTerm.eqNode(node[0])); - } - Assert(!lem.isNull()); - Node ret = ProofSkolemCache::mkSkolem( - var, - lem, - "tfk", - "Skolem to eliminate a non-standard transcendental function"); - ret = ProofSkolemCache::getWitnessForm(ret); - d_nlin_inverse_skolem[node] = ret; - return ret; - } - return (*it).second; - break; - } - - default: break; - } - return node; -} - Node TheoryArithPrivate::ppRewrite(TNode atom) { Debug("arith::preprocess") << "arith::preprocess() : " << atom << endl; @@ -1690,7 +1265,8 @@ void TheoryArithPrivate::setupVariableList(const VarList& vl){ throw LogicException("A non-linear fact was asserted to arithmetic in a linear logic."); } - if( !options::nlExt() ){ + if (d_nonlinearExtension == nullptr) + { d_nlIncomplete = true; } @@ -1701,7 +1277,8 @@ void TheoryArithPrivate::setupVariableList(const VarList& vl){ markSetup(vlNode); }else{ - if( !options::nlExt() ){ + if (d_nonlinearExtension == nullptr) + { if( vlNode.getKind()==kind::EXPONENTIAL || vlNode.getKind()==kind::SINE || vlNode.getKind()==kind::COSINE || vlNode.getKind()==kind::TANGENT ){ d_nlIncomplete = true; @@ -1867,8 +1444,9 @@ void TheoryArithPrivate::setupAtom(TNode atom) { void TheoryArithPrivate::preRegisterTerm(TNode n) { Debug("arith::preregister") <<"begin arith::preRegisterTerm("<< n <<")"<< endl; - - if( options::nlExt() ){ + + if (d_nonlinearExtension != nullptr) + { d_containing.getExtTheory()->registerTermRec( n ); } @@ -3749,7 +3327,8 @@ void TheoryArithPrivate::check(Theory::Effort effortLevel){ } if(effortLevel == Theory::EFFORT_LAST_CALL){ - if( options::nlExt() ){ + if (d_nonlinearExtension != nullptr) + { d_nonlinearExtension->check(effortLevel); } return; @@ -4073,7 +3652,8 @@ void TheoryArithPrivate::check(Theory::Effort effortLevel){ }//if !emmittedConflictOrSplit && fullEffort(effortLevel) && !hasIntegerModel() if(!emmittedConflictOrSplit && effortLevel>=Theory::EFFORT_FULL){ - if( options::nlExt() ){ + if (d_nonlinearExtension != nullptr) + { d_nonlinearExtension->check( effortLevel ); } } @@ -4276,15 +3856,16 @@ void TheoryArithPrivate::debugPrintModel(std::ostream& out) const{ } bool TheoryArithPrivate::needsCheckLastEffort() { - if( options::nlExt() ){ + if (d_nonlinearExtension != nullptr) + { return d_nonlinearExtension->needsCheckLastEffort(); }else{ return false; } } -Node TheoryArithPrivate::explain(TNode n) { - +Node TheoryArithPrivate::explain(TNode n) +{ Debug("arith::explain") << "explain @" << getSatContext()->getLevel() << ": " << n << endl; ConstraintP c = d_constraintDatabase.lookup(n); @@ -4313,7 +3894,8 @@ Node TheoryArithPrivate::explain(TNode n) { } bool TheoryArithPrivate::getCurrentSubstitution( int effort, std::vector< Node >& vars, std::vector< Node >& subs, std::map< Node, std::vector< Node > >& exp ) { - if( options::nlExt() ){ + if (d_nonlinearExtension != nullptr) + { return d_nonlinearExtension->getCurrentSubstitution( effort, vars, subs, exp ); }else{ return false; @@ -4322,7 +3904,8 @@ bool TheoryArithPrivate::getCurrentSubstitution( int effort, std::vector< Node > bool TheoryArithPrivate::isExtfReduced(int effort, Node n, Node on, std::vector<Node>& exp) { - if (options::nlExt()) { + if (d_nonlinearExtension != nullptr) + { std::pair<bool, Node> reduced = d_nonlinearExtension->isExtfReduced(effort, n, on, exp); if (!reduced.second.isNull()) { @@ -4570,7 +4153,7 @@ bool TheoryArithPrivate::collectModelInfo(TheoryModel* m) Node qNode = mkRationalNode(qmodel); Debug("arith::collectModelInfo") << "m->assertEquality(" << term << ", " << qmodel << ", true)" << endl; - if (options::nlExt()) + if (d_nonlinearExtension != nullptr) { // Let non-linear extension inspect the values before they are sent // to the theory model. @@ -4589,7 +4172,7 @@ bool TheoryArithPrivate::collectModelInfo(TheoryModel* m) } } } - if (options::nlExt()) + if (d_nonlinearExtension != nullptr) { // Non-linear may repair values to satisfy non-linear constraints (see // documentation for NonlinearExtension::interceptModel). @@ -4739,7 +4322,7 @@ void TheoryArithPrivate::presolve(){ outputLemma(lem); } - if (options::nlExt()) + if (d_nonlinearExtension != nullptr) { d_nonlinearExtension->presolve(); } @@ -5231,155 +4814,16 @@ const BoundsInfo& TheoryArithPrivate::boundsInfo(ArithVar basic) const{ Node TheoryArithPrivate::expandDefinition(Node node) { // call eliminate operators - Node nn = eliminateOperators(node); + Node nn = d_opElim.eliminateOperators(node); if (nn != node) { // since elimination may introduce new operators to eliminate, we must // recursively eliminate result - return eliminateOperatorsRec(nn); + return d_opElim.eliminateOperatorsRec(nn); } return node; } -Node TheoryArithPrivate::getArithSkolem(ArithSkolemId asi) -{ - std::map<ArithSkolemId, Node>::iterator it = d_arith_skolem.find(asi); - if (it == d_arith_skolem.end()) - { - NodeManager* nm = NodeManager::currentNM(); - - TypeNode tn; - std::string name; - std::string desc; - switch (asi) - { - case ArithSkolemId::DIV_BY_ZERO: - tn = nm->realType(); - name = std::string("divByZero"); - desc = std::string("partial real division"); - break; - case ArithSkolemId::INT_DIV_BY_ZERO: - tn = nm->integerType(); - name = std::string("intDivByZero"); - desc = std::string("partial int division"); - break; - case ArithSkolemId::MOD_BY_ZERO: - tn = nm->integerType(); - name = std::string("modZero"); - desc = std::string("partial modulus"); - break; - case ArithSkolemId::SQRT: - tn = nm->realType(); - name = std::string("sqrtUf"); - desc = std::string("partial sqrt"); - break; - default: Unhandled(); - } - - Node skolem; - if (options::arithNoPartialFun()) - { - // partial function: division - skolem = nm->mkSkolem(name, tn, desc, NodeManager::SKOLEM_EXACT_NAME); - } - else - { - // partial function: division - skolem = nm->mkSkolem(name, - nm->mkFunctionType(tn, tn), - desc, - NodeManager::SKOLEM_EXACT_NAME); - } - d_arith_skolem[asi] = skolem; - return skolem; - } - return it->second; -} - -Node TheoryArithPrivate::getArithSkolemApp(Node n, ArithSkolemId asi) -{ - Node skolem = getArithSkolem(asi); - if (!options::arithNoPartialFun()) - { - skolem = NodeManager::currentNM()->mkNode(APPLY_UF, skolem, n); - } - return skolem; -} - -// InferBoundsResult TheoryArithPrivate::inferBound(TNode term, const -// InferBoundsParameters& param){ -// Node t = Rewriter::rewrite(term); -// Assert(Polynomial::isMember(t)); -// Polynomial p = Polynomial::parsePolynomial(t); -// if(p.containsConstant()){ -// Constant c = p.getHead().getConstant(); -// if(p.isConstant()){ -// InferBoundsResult res(t, param.findLowerBound()); -// res.setBound((DeltaRational)c.getValue(), mkBoolNode(true)); -// return res; -// }else{ -// Polynomial tail = p.getTail(); -// InferBoundsResult res = inferBound(tail.getNode(), param); -// if(res.foundBound()){ -// DeltaRational newBound = res.getValue() + c.getValue(); -// if(tail.isIntegral()){ -// Integer asInt = (param.findLowerBound()) ? newBound.ceiling() : -// newBound.floor(); newBound = DeltaRational(asInt); -// } -// res.setBound(newBound, res.getExplanation()); -// } -// return res; -// } -// }else if(param.findLowerBound()){ -// InferBoundsParameters find_ub = param; -// find_ub.setFindUpperBound(); -// if(param.useThreshold()){ -// find_ub.setThreshold(- param.getThreshold() ); -// } -// Polynomial negP = -p; -// InferBoundsResult res = inferBound(negP.getNode(), find_ub); -// res.setFindLowerBound(); -// if(res.foundBound()){ -// res.setTerm(p.getNode()); -// res.setBound(-res.getValue(), res.getExplanation()); -// } -// return res; -// }else{ -// Assert(param.findUpperBound()); -// // does not contain a constant -// switch(param.getEffort()){ -// case InferBoundsParameters::Lookup: -// return inferUpperBoundLookup(t, param); -// case InferBoundsParameters::Simplex: -// return inferUpperBoundSimplex(t, param); -// case InferBoundsParameters::LookupAndSimplexOnFailure: -// case InferBoundsParameters::TryBoth: -// { -// InferBoundsResult lookup = inferUpperBoundLookup(t, param); -// if(lookup.foundBound()){ -// if(param.getEffort() == -// InferBoundsParameters::LookupAndSimplexOnFailure || -// lookup.boundIsOptimal()){ -// return lookup; -// } -// } -// InferBoundsResult simplex = inferUpperBoundSimplex(t, param); -// if(lookup.foundBound() && simplex.foundBound()){ -// return (lookup.getValue() <= simplex.getValue()) ? lookup : -// simplex; -// }else if(lookup.foundBound()){ -// return lookup; -// }else{ -// return simplex; -// } -// } -// default: -// Unreachable(); -// return InferBoundsResult(); -// } -// } -// } - std::pair<bool, Node> TheoryArithPrivate::entailmentCheck(TNode lit, const ArithEntailmentCheckParameters& params, ArithEntailmentCheckSideEffects& out){ using namespace inferbounds; diff --git a/src/theory/arith/theory_arith_private.h b/src/theory/arith/theory_arith_private.h index 8198dbcf1..867029e3c 100644 --- a/src/theory/arith/theory_arith_private.h +++ b/src/theory/arith/theory_arith_private.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -35,15 +35,12 @@ #include "smt/logic_exception.h" #include "smt_util/boolean_simplification.h" #include "theory/arith/arith_rewriter.h" -#include "theory/arith/arith_rewriter.h" #include "theory/arith/arith_static_learner.h" #include "theory/arith/arith_utilities.h" #include "theory/arith/arithvar.h" #include "theory/arith/attempt_solution_simplex.h" #include "theory/arith/congruence_manager.h" #include "theory/arith/constraint.h" -#include "theory/arith/constraint.h" -#include "theory/arith/delta_rational.h" #include "theory/arith/delta_rational.h" #include "theory/arith/dio_solver.h" #include "theory/arith/dual_simplex.h" @@ -51,9 +48,8 @@ #include "theory/arith/infer_bounds.h" #include "theory/arith/linear_equality.h" #include "theory/arith/matrix.h" -#include "theory/arith/matrix.h" #include "theory/arith/normal_form.h" -#include "theory/arith/partial_model.h" +#include "theory/arith/operator_elim.h" #include "theory/arith/partial_model.h" #include "theory/arith/simplex.h" #include "theory/arith/soi_simplex.h" @@ -83,7 +79,9 @@ namespace inferbounds { } class InferBoundsResult; +namespace nl { class NonlinearExtension; +} /** * Implementation of QF_LRA. @@ -372,7 +370,7 @@ private: AttemptSolutionSDP d_attemptSolSimplex; /** non-linear algebraic approach */ - NonlinearExtension * d_nonlinearExtension; + nl::NonlinearExtension* d_nonlinearExtension; bool solveRealRelaxation(Theory::Effort effortLevel); @@ -419,40 +417,13 @@ private: // handle linear /, div, mod, and also is_int, to_int Node ppRewriteTerms(TNode atom); - /** - * Called when a non-linear term n is given to this class. Throw an exception - * if the logic is linear. - */ - void checkNonLinearLogic(Node term); - /** - * Eliminate operators in term n. If n has top symbol that is not a core - * one (including division, int division, mod, to_int, is_int, syntactic sugar - * transcendental functions), then we replace it by a form that eliminates - * that operator. This may involve the introduction of witness terms. - * - * One exception to the above rule is that we may leave certain applications - * like (/ 4 1) unchanged, since replacing this by 4 changes its type from - * real to int. This is important for some subtyping issues during - * expandDefinition. Moreover, applications like this can be eliminated - * trivially later by rewriting. - * - * This method is called both during expandDefinition and during ppRewrite. - * - * @param n The node to eliminate operators from. - * @return The (single step) eliminated form of n. - */ - Node eliminateOperators(Node n); - /** - * Recursively ensure that n has no non-standard operators. This applies - * the above method on all subterms of n. - * - * @param n The node to eliminate operators from. - * @return The eliminated form of n. - */ - Node eliminateOperatorsRec(Node n); - public: - TheoryArithPrivate(TheoryArith& containing, context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo); + TheoryArithPrivate(TheoryArith& containing, + context::Context* c, + context::UserContext* u, + OutputChannel& out, + Valuation valuation, + const LogicInfo& logicInfo); ~TheoryArithPrivate(); TheoryRewriter* getTheoryRewriter() { return &d_rewriter; } @@ -860,60 +831,10 @@ private: Statistics d_statistics; - enum class ArithSkolemId - { - /* an uninterpreted function f s.t. f(x) = x / 0.0 (real division) */ - DIV_BY_ZERO, - /* an uninterpreted function f s.t. f(x) = x / 0 (integer division) */ - INT_DIV_BY_ZERO, - /* an uninterpreted function f s.t. f(x) = x mod 0 */ - MOD_BY_ZERO, - /* an uninterpreted function f s.t. f(x) = sqrt(x) */ - SQRT, - }; - - /** - * Function symbols used to implement: - * (1) Uninterpreted division-by-zero semantics. Needed to deal with partial - * division function ("/"), - * (2) Uninterpreted int-division-by-zero semantics. Needed to deal with - * partial function "div", - * (3) Uninterpreted mod-zero semantics. Needed to deal with partial - * function "mod". - * - * If the option arithNoPartialFun() is enabled, then the range of this map - * stores Skolem constants instead of Skolem functions, meaning that the - * function-ness of e.g. division by zero is ignored. - */ - std::map<ArithSkolemId, Node> d_arith_skolem; - /** get arithmetic skolem - * - * Returns the Skolem in the above map for the given id, creating it if it - * does not already exist. - */ - Node getArithSkolem(ArithSkolemId asi); - /** get arithmetic skolem application - * - * By default, this returns the term f( n ), where f is the Skolem function - * for the identifier asi. - * - * If the option arithNoPartialFun is enabled, this returns f, where f is - * the Skolem constant for the identifier asi. - */ - Node getArithSkolemApp(Node n, ArithSkolemId asi); - - /** - * Maps for Skolems for to-integer, real/integer div-by-k, and inverse - * non-linear operators that are introduced during ppRewriteTerms. - */ - typedef context::CDHashMap< Node, Node, NodeHashFunction > NodeMap; - NodeMap d_to_int_skolem; - NodeMap d_div_skolem; - NodeMap d_int_div_skolem; - NodeMap d_nlin_inverse_skolem; - /** The theory rewriter for this theory. */ ArithRewriter d_rewriter; + /** The operator elimination utility */ + OperatorElim d_opElim; };/* class TheoryArithPrivate */ }/* CVC4::theory::arith namespace */ diff --git a/src/theory/arith/theory_arith_private_forward.h b/src/theory/arith/theory_arith_private_forward.h index 84dea1b4e..363debf30 100644 --- a/src/theory/arith/theory_arith_private_forward.h +++ b/src/theory/arith/theory_arith_private_forward.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arith/theory_arith_type_rules.h b/src/theory/arith/theory_arith_type_rules.h index 8b587c0fb..77efcfff7 100644 --- a/src/theory/arith/theory_arith_type_rules.h +++ b/src/theory/arith/theory_arith_type_rules.h @@ -2,9 +2,9 @@ /*! \file theory_arith_type_rules.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Morgan Deters, Christopher L. Conway + ** Dejan Jovanovic, Christopher L. Conway, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -87,6 +87,49 @@ public: } };/* class RealNullaryOperatorTypeRule */ +class IAndOpTypeRule +{ + public: + inline static TypeNode computeType(NodeManager* nodeManager, + TNode n, + bool check) + { + if (n.getKind() != kind::IAND_OP) + { + InternalError() << "IAND_OP typerule invoked for IAND_OP kind"; + } + TypeNode iType = nodeManager->integerType(); + std::vector<TypeNode> argTypes; + argTypes.push_back(iType); + argTypes.push_back(iType); + return nodeManager->mkFunctionType(argTypes, iType); + } +}; /* class IAndOpTypeRule */ + +class IAndTypeRule +{ + public: + inline static TypeNode computeType(NodeManager* nodeManager, + TNode n, + bool check) + { + if (n.getKind() != kind::IAND) + { + InternalError() << "IAND typerule invoked for IAND kind"; + } + if (check) + { + TypeNode arg1 = n[0].getType(check); + TypeNode arg2 = n[1].getType(check); + if (!arg1.isInteger() || !arg2.isInteger()) + { + throw TypeCheckingExceptionPrivate(n, "expecting integer terms"); + } + } + return nodeManager->integerType(); + } +}; /* class BitVectorConversionTypeRule */ + }/* CVC4::theory::arith namespace */ }/* CVC4::theory namespace */ }/* CVC4 namespace */ diff --git a/src/theory/arith/type_enumerator.h b/src/theory/arith/type_enumerator.h index bb1612928..ff6308122 100644 --- a/src/theory/arith/type_enumerator.h +++ b/src/theory/arith/type_enumerator.h @@ -2,9 +2,9 @@ /*! \file type_enumerator.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/array_info.cpp b/src/theory/arrays/array_info.cpp index 3103f4ecc..c2928e534 100644 --- a/src/theory/arrays/array_info.cpp +++ b/src/theory/arrays/array_info.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Clark Barrett, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/array_info.h b/src/theory/arrays/array_info.h index 982317350..d472277c7 100644 --- a/src/theory/arrays/array_info.h +++ b/src/theory/arrays/array_info.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Clark Barrett, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/array_proof_reconstruction.cpp b/src/theory/arrays/array_proof_reconstruction.cpp index c25ce1aba..abc4857e8 100644 --- a/src/theory/arrays/array_proof_reconstruction.cpp +++ b/src/theory/arrays/array_proof_reconstruction.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Guy Katz, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/array_proof_reconstruction.h b/src/theory/arrays/array_proof_reconstruction.h index 37b014d35..a73b5dd08 100644 --- a/src/theory/arrays/array_proof_reconstruction.h +++ b/src/theory/arrays/array_proof_reconstruction.h @@ -2,9 +2,9 @@ /*! \file array_proof_reconstruction.h ** \verbatim ** Top contributors (to current version): - ** Paul Meng, Tim King + ** Paul Meng, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/kinds b/src/theory/arrays/kinds index 1adbdb0b2..659f05ae8 100644 --- a/src/theory/arrays/kinds +++ b/src/theory/arrays/kinds @@ -31,6 +31,9 @@ operator SELECT 2 "array select; first parameter is an array term, second is the # store a i e is a[i] <= e operator STORE 3 "array store; first parameter is an array term, second is the store index, third is the term to store at the index" +# eqrange a b i j \forall k. i <= k <= j -> a[k] = b[k] +operator EQ_RANGE 4 "equality of two arrays over an index range lower/upper" + # storeall t e is \all i in indexType(t) <= e constant STORE_ALL \ ::CVC4::ArrayStoreAll \ @@ -53,6 +56,7 @@ typerule STORE ::CVC4::theory::arrays::ArrayStoreTypeRule typerule STORE_ALL ::CVC4::theory::arrays::ArrayStoreTypeRule typerule ARR_TABLE_FUN ::CVC4::theory::arrays::ArrayTableFunTypeRule typerule ARRAY_LAMBDA ::CVC4::theory::arrays::ArrayLambdaTypeRule +typerule EQ_RANGE ::CVC4::theory::arrays::ArrayEqRangeTypeRule operator PARTIAL_SELECT_0 0:2 "partial array select, for internal use only" operator PARTIAL_SELECT_1 0:2 "partial array select, for internal use only" diff --git a/src/theory/arrays/static_fact_manager.cpp b/src/theory/arrays/static_fact_manager.cpp index 546db649c..d2f4b75c9 100644 --- a/src/theory/arrays/static_fact_manager.cpp +++ b/src/theory/arrays/static_fact_manager.cpp @@ -2,9 +2,9 @@ /*! \file static_fact_manager.cpp ** \verbatim ** Top contributors (to current version): - ** Clark Barrett + ** Clark Barrett, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/static_fact_manager.h b/src/theory/arrays/static_fact_manager.h index 6b68edf26..2df4b0fda 100644 --- a/src/theory/arrays/static_fact_manager.h +++ b/src/theory/arrays/static_fact_manager.h @@ -2,9 +2,9 @@ /*! \file static_fact_manager.h ** \verbatim ** Top contributors (to current version): - ** Clark Barrett, Morgan Deters, Tim King + ** Clark Barrett, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp index 5085c00ec..71e040ccc 100644 --- a/src/theory/arrays/theory_arrays.cpp +++ b/src/theory/arrays/theory_arrays.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Clark Barrett, Morgan Deters, Guy Katz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -2312,6 +2312,61 @@ std::string TheoryArrays::TheoryArraysDecisionStrategy::identify() const return std::string("th_arrays_dec"); } +Node TheoryArrays::expandDefinition(Node node) +{ + NodeManager* nm = NodeManager::currentNM(); + Kind kind = node.getKind(); + + /* Expand + * + * (eqrange a b i j) + * + * to + * + * forall k . i <= k <= j => a[k] = b[k] + * + */ + if (kind == kind::EQ_RANGE) + { + TNode a = node[0]; + TNode b = node[1]; + TNode i = node[2]; + TNode j = node[3]; + Node k = nm->mkBoundVar(i.getType()); + Node bvl = nm->mkNode(kind::BOUND_VAR_LIST, k); + TypeNode type = k.getType(); + + Kind kle; + Node range; + if (type.isBitVector()) + { + kle = kind::BITVECTOR_ULE; + } + else if (type.isFloatingPoint()) + { + kle = kind::FLOATINGPOINT_LEQ; + } + else if (type.isInteger() || type.isReal()) + { + kle = kind::LEQ; + } + else + { + Unimplemented() << "Type " << type << " is not supported for predicate " + << kind; + } + + range = nm->mkNode(kind::AND, nm->mkNode(kle, i, k), nm->mkNode(kle, k, j)); + + Node eq = nm->mkNode(kind::EQUAL, + nm->mkNode(kind::SELECT, a, k), + nm->mkNode(kind::SELECT, b, k)); + Node implies = nm->mkNode(kind::IMPLIES, range, eq); + return nm->mkNode(kind::FORALL, bvl, implies); + } + return node; +} + }/* CVC4::theory::arrays namespace */ }/* CVC4::theory namespace */ }/* CVC4 namespace */ diff --git a/src/theory/arrays/theory_arrays.h b/src/theory/arrays/theory_arrays.h index 34cf6c424..c5cd24fd3 100644 --- a/src/theory/arrays/theory_arrays.h +++ b/src/theory/arrays/theory_arrays.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Clark Barrett, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -151,6 +151,8 @@ class TheoryArrays : public Theory { std::string identify() const override { return std::string("TheoryArrays"); } + Node expandDefinition(Node node) override; + ///////////////////////////////////////////////////////////////////////////// // PREPROCESSING ///////////////////////////////////////////////////////////////////////////// diff --git a/src/theory/arrays/theory_arrays_rewriter.cpp b/src/theory/arrays/theory_arrays_rewriter.cpp index 43c6153c7..86e5d8c08 100644 --- a/src/theory/arrays/theory_arrays_rewriter.cpp +++ b/src/theory/arrays/theory_arrays_rewriter.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/theory_arrays_rewriter.h b/src/theory/arrays/theory_arrays_rewriter.h index e8c3d78d0..e81b7d7c0 100644 --- a/src/theory/arrays/theory_arrays_rewriter.h +++ b/src/theory/arrays/theory_arrays_rewriter.h @@ -2,9 +2,9 @@ /*! \file theory_arrays_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Clark Barrett, Morgan Deters, Dejan Jovanovic + ** Clark Barrett, Morgan Deters, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/theory_arrays_type_rules.h b/src/theory/arrays/theory_arrays_type_rules.h index 223d742eb..e5681d50f 100644 --- a/src/theory/arrays/theory_arrays_type_rules.h +++ b/src/theory/arrays/theory_arrays_type_rules.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Clark Barrett, Christopher L. Conway ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -224,6 +224,57 @@ struct ArrayPartialSelectTypeRule { } };/* struct ArrayPartialSelectTypeRule */ +struct ArrayEqRangeTypeRule +{ + inline static TypeNode computeType(NodeManager* nodeManager, + TNode n, + bool check) + { + Assert(n.getKind() == kind::EQ_RANGE); + if (check) + { + TypeNode n0_type = n[0].getType(check); + TypeNode n1_type = n[1].getType(check); + if (!n0_type.isArray()) + { + throw TypeCheckingExceptionPrivate( + n, "first operand of eqrange is not an array"); + } + if (!n1_type.isArray()) + { + throw TypeCheckingExceptionPrivate( + n, "second operand of eqrange is not an array"); + } + if (n0_type != n1_type) + { + throw TypeCheckingExceptionPrivate(n, "array types do not match"); + } + TypeNode indexType = n0_type.getArrayIndexType(); + TypeNode indexRangeType1 = n[2].getType(check); + TypeNode indexRangeType2 = n[3].getType(check); + if (!indexRangeType1.isSubtypeOf(indexType)) + { + throw TypeCheckingExceptionPrivate( + n, "eqrange lower index type does not match array index type"); + } + if (!indexRangeType2.isSubtypeOf(indexType)) + { + throw TypeCheckingExceptionPrivate( + n, "eqrange upper index type does not match array index type"); + } + if (!indexType.isBitVector() && !indexType.isFloatingPoint() + && !indexType.isInteger() && !indexType.isReal()) + { + throw TypeCheckingExceptionPrivate( + n, + "eqrange only supports bit-vectors, floating-points, integers, and " + "reals as index type"); + } + } + return nodeManager->booleanType(); + } +}; /* struct ArrayEqRangeTypeRule */ + }/* CVC4::theory::arrays namespace */ }/* CVC4::theory namespace */ }/* CVC4 namespace */ diff --git a/src/theory/arrays/type_enumerator.h b/src/theory/arrays/type_enumerator.h index 5ca156b2e..3da793617 100644 --- a/src/theory/arrays/type_enumerator.h +++ b/src/theory/arrays/type_enumerator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Clark Barrett, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/union_find.cpp b/src/theory/arrays/union_find.cpp index 0afa94a8e..fe249c50b 100644 --- a/src/theory/arrays/union_find.cpp +++ b/src/theory/arrays/union_find.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/arrays/union_find.h b/src/theory/arrays/union_find.h index 1f38f1280..f8a7677aa 100644 --- a/src/theory/arrays/union_find.h +++ b/src/theory/arrays/union_find.h @@ -2,9 +2,9 @@ /*! \file union_find.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/assertion.cpp b/src/theory/assertion.cpp index 97b3dcbbb..e561052c6 100644 --- a/src/theory/assertion.cpp +++ b/src/theory/assertion.cpp @@ -2,9 +2,9 @@ /*! \file assertion.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/assertion.h b/src/theory/assertion.h index 797ff3372..14dc7d920 100644 --- a/src/theory/assertion.h +++ b/src/theory/assertion.h @@ -2,9 +2,9 @@ /*! \file assertion.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Dejan Jovanovic + ** Tim King, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/atom_requests.cpp b/src/theory/atom_requests.cpp index 821c2384c..fb1c8d83f 100644 --- a/src/theory/atom_requests.cpp +++ b/src/theory/atom_requests.cpp @@ -2,9 +2,9 @@ /*! \file atom_requests.cpp ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic + ** Dejan Jovanovic, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/atom_requests.h b/src/theory/atom_requests.h index b96b042af..29dd4f1a3 100644 --- a/src/theory/atom_requests.h +++ b/src/theory/atom_requests.h @@ -2,9 +2,9 @@ /*! \file atom_requests.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic + ** Dejan Jovanovic, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/booleans/circuit_propagator.cpp b/src/theory/booleans/circuit_propagator.cpp index f9631c94d..32901e7ed 100644 --- a/src/theory/booleans/circuit_propagator.cpp +++ b/src/theory/booleans/circuit_propagator.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Morgan Deters, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/booleans/circuit_propagator.h b/src/theory/booleans/circuit_propagator.h index 9c4798898..f0a0b3c3f 100644 --- a/src/theory/booleans/circuit_propagator.h +++ b/src/theory/booleans/circuit_propagator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Aina Niemetz, Morgan Deters, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/booleans/proof_checker.cpp b/src/theory/booleans/proof_checker.cpp new file mode 100644 index 000000000..6e7cabccd --- /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 + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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..8258130fb --- /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 + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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/booleans/theory_bool.cpp b/src/theory/booleans/theory_bool.cpp index 29f5bb82d..04a1675a4 100644 --- a/src/theory/booleans/theory_bool.cpp +++ b/src/theory/booleans/theory_bool.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Dejan Jovanovic, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/booleans/theory_bool.h b/src/theory/booleans/theory_bool.h index ae498165f..99c80dd4a 100644 --- a/src/theory/booleans/theory_bool.h +++ b/src/theory/booleans/theory_bool.h @@ -2,9 +2,9 @@ /*! \file theory_bool.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Mathias Preiner + ** Andres Noetzli, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/booleans/theory_bool_rewriter.cpp b/src/theory/booleans/theory_bool_rewriter.cpp index ca22467d4..ca2ac13ea 100644 --- a/src/theory/booleans/theory_bool_rewriter.cpp +++ b/src/theory/booleans/theory_bool_rewriter.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Dejan Jovanovic, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -157,6 +157,19 @@ RewriteResponse TheoryBoolRewriter::preRewrite(TNode n) { if (!done) { return flattenNode(n, /* trivialNode = */ tt, /* skipNode = */ ff); } + // x v ... v x --> x + unsigned ind, size; + for (ind = 0, size = n.getNumChildren(); ind < size - 1; ++ind) + { + if (n[ind] != n[ind+1]) + { + break; + } + } + if (ind == size - 1) + { + return RewriteResponse(REWRITE_AGAIN, n[0]); + } break; } case kind::AND: { @@ -172,6 +185,19 @@ RewriteResponse TheoryBoolRewriter::preRewrite(TNode n) { Debug("bool-flatten") << n << ": " << ret.d_node << std::endl; return ret; } + // x ^ ... ^ x --> x + unsigned ind, size; + for (ind = 0, size = n.getNumChildren(); ind < size - 1; ++ind) + { + if (n[ind] != n[ind+1]) + { + break; + } + } + if (ind == size - 1) + { + return RewriteResponse(REWRITE_AGAIN, n[0]); + } break; } case kind::IMPLIES: { @@ -293,28 +319,39 @@ RewriteResponse TheoryBoolRewriter::preRewrite(TNode n) { if (n[0].isConst()) { if (n[0] == tt) { // ITE true x y - - Debug("bool-ite") << "n[0] ==tt " << n << ": " << n[1] << std::endl; + Debug("bool-ite") << "TheoryBoolRewriter::preRewrite_ITE: n[0] ==tt " + << n << ": " << n[1] << std::endl; return RewriteResponse(REWRITE_AGAIN, n[1]); } else { Assert(n[0] == ff); // ITE false x y - Debug("bool-ite") << "n[0] ==ff " << n << ": " << n[1] << std::endl; + Debug("bool-ite") << "TheoryBoolRewriter::preRewrite_ITE: n[0] ==ff " + << n << ": " << n[1] << std::endl; return RewriteResponse(REWRITE_AGAIN, n[2]); } } else if (n[1].isConst()) { if (n[1] == tt && n[2] == ff) { - Debug("bool-ite") << "n[1] ==tt && n[2] == ff " << n << ": " << n[0] << std::endl; + Debug("bool-ite") + << "TheoryBoolRewriter::preRewrite_ITE: n[1] ==tt && n[2] == ff " + << n << ": " << n[0] << std::endl; return RewriteResponse(REWRITE_AGAIN, n[0]); } else if (n[1] == ff && n[2] == tt) { - Debug("bool-ite") << "n[1] ==ff && n[2] == tt " << n << ": " << n[0].notNode() << std::endl; + Debug("bool-ite") + << "TheoryBoolRewriter::preRewrite_ITE: n[1] ==ff && n[2] == tt " + << n << ": " << n[0].notNode() << std::endl; return RewriteResponse(REWRITE_AGAIN, makeNegation(n[0])); } - // else if(n[1] == ff){ - // Node resp = (n[0].notNode()).andNode(n[2]); - // return RewriteResponse(REWRITE_AGAIN, resp); - // } + if (n[1] == tt || n[1] == ff) + { + // ITE C true y --> C v y + // ITE C false y --> ~C ^ y + Node resp = + n[1] == tt ? n[0].orNode(n[2]) : (n[0].negate()).andNode(n[2]); + Debug("bool-ite") << "TheoryBoolRewriter::preRewrite_ITE: n[1] const " + << n << ": " << resp << std::endl; + return RewriteResponse(REWRITE_AGAIN, resp); + } } if (n[0].getKind() == kind::NOT) @@ -324,18 +361,23 @@ RewriteResponse TheoryBoolRewriter::preRewrite(TNode n) { REWRITE_AGAIN, nodeManager->mkNode(kind::ITE, n[0][0], n[2], n[1])); } - // else if (n[2].isConst()) { - // if(n[2] == ff){ - // Node resp = (n[0]).andNode(n[1]); - // return RewriteResponse(REWRITE_AGAIN, resp); - // } - // } + if (n[2].isConst() && (n[2] == tt || n[2] == ff)) + { + // ITE C x true --> ~C v x + // ITE C x false --> C ^ x + Node resp = + n[2] == tt ? (n[0].negate()).orNode(n[1]) : n[0].andNode(n[1]); + Debug("bool-ite") << "TheoryBoolRewriter::preRewrite_ITE: n[2] const " + << n << ": " << resp << std::endl; + return RewriteResponse(REWRITE_AGAIN, resp); + } int parityTmp; if ((parityTmp = equalityParity(n[1], n[2])) != 0) { Node resp = (parityTmp == 1) ? (Node)n[1] : n[0].eqNode(n[1]); - Debug("bool-ite") << "equalityParity n[1], n[2] " << parityTmp - << " " << n << ": " << resp << std::endl; + Debug("bool-ite") + << "TheoryBoolRewriter::preRewrite_ITE: equalityParity n[1], n[2] " + << parityTmp << " " << n << ": " << resp << std::endl; return RewriteResponse(REWRITE_AGAIN, resp); // Curiously, this rewrite affects several benchmarks dramatically, including copy_array and some simple_startup - disable for now // } else if (n[0].getKind() == kind::NOT) { @@ -346,15 +388,17 @@ RewriteResponse TheoryBoolRewriter::preRewrite(TNode n) { // if n[1] is constant this can loop, this is possible in prewrite Node resp = n[0].iteNode( (parityTmp == 1) ? tt : ff, n[2]); - Debug("bool-ite") << "equalityParity n[0], n[1] " << parityTmp - << " " << n << ": " << resp << std::endl; + Debug("bool-ite") + << "TheoryBoolRewriter::preRewrite_ITE: equalityParity n[0], n[1] " + << parityTmp << " " << n << ": " << resp << std::endl; return RewriteResponse(REWRITE_AGAIN, resp); } else if(!n[2].isConst() && (parityTmp = equalityParity(n[0], n[2])) != 0){ // (parityTmp == 1) if n[0] == n[2] // otherwise, n[0] == not(n[2]) or not(n[0]) == n[2] Node resp = n[0].iteNode(n[1], (parityTmp == 1) ? ff : tt); - Debug("bool-ite") << "equalityParity n[0], n[2] " << parityTmp - << " " << n << ": " << resp << std::endl; + Debug("bool-ite") + << "TheoryBoolRewriter::preRewrite_ITE: equalityParity n[0], n[2] " + << parityTmp << " " << n << ": " << resp << std::endl; return RewriteResponse(REWRITE_AGAIN, resp); } else if(n[1].getKind() == kind::ITE && (parityTmp = equalityParity(n[0], n[1][0])) != 0){ @@ -362,8 +406,9 @@ RewriteResponse TheoryBoolRewriter::preRewrite(TNode n) { // (parityTmp > 1) then n : (ite c (ite (not c) x y) z) or // n: (ite (not c) (ite c x y) z) Node resp = n[0].iteNode((parityTmp == 1) ? n[1][1] : n[1][2], n[2]); - Debug("bool-ite") << "equalityParity n[0], n[1][0] " << parityTmp - << " " << n << ": " << resp << std::endl; + Debug("bool-ite") + << "TheoryBoolRewriter::preRewrite: equalityParity n[0], n[1][0] " + << parityTmp << " " << n << ": " << resp << std::endl; return RewriteResponse(REWRITE_AGAIN, resp); } else if(n[2].getKind() == kind::ITE && (parityTmp = equalityParity(n[0], n[2][0])) != 0){ @@ -371,8 +416,9 @@ RewriteResponse TheoryBoolRewriter::preRewrite(TNode n) { // (parityTmp > 1) then n : (ite c x (ite (not c) y z)) or // n: (ite (not c) x (ite c y z)) Node resp = n[0].iteNode(n[1], (parityTmp == 1) ? n[2][2] : n[2][1]); - Debug("bool-ite") << "equalityParity n[0], n[2][0] " << parityTmp - << " " << n << ": " << resp << std::endl; + Debug("bool-ite") + << "TheoryBoolRewriter::preRewrite: equalityParity n[0], n[2][0] " + << parityTmp << " " << n << ": " << resp << std::endl; return RewriteResponse(REWRITE_AGAIN, resp); } break; diff --git a/src/theory/booleans/theory_bool_rewriter.h b/src/theory/booleans/theory_bool_rewriter.h index 8fc65932e..04de76ac3 100644 --- a/src/theory/booleans/theory_bool_rewriter.h +++ b/src/theory/booleans/theory_bool_rewriter.h @@ -2,9 +2,9 @@ /*! \file theory_bool_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Morgan Deters, Tim King + ** Andres Noetzli, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/booleans/theory_bool_type_rules.h b/src/theory/booleans/theory_bool_type_rules.h index 18329b8b9..25701d394 100644 --- a/src/theory/booleans/theory_bool_type_rules.h +++ b/src/theory/booleans/theory_bool_type_rules.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Morgan Deters, Christopher L. Conway ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/booleans/type_enumerator.h b/src/theory/booleans/type_enumerator.h index b0bae3e47..4966afa7d 100644 --- a/src/theory/booleans/type_enumerator.h +++ b/src/theory/booleans/type_enumerator.h @@ -2,9 +2,9 @@ /*! \file type_enumerator.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/builtin/proof_checker.cpp b/src/theory/builtin/proof_checker.cpp new file mode 100644 index 000000000..df6109b1d --- /dev/null +++ b/src/theory/builtin/proof_checker.cpp @@ -0,0 +1,374 @@ +/********************* */ +/*! \file proof_checker.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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/skolem_manager.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 = SkolemManager::getSkolemForm(n); + Node nkr = applyRewriteExternal(nk, idr); + return SkolemManager::getWitnessForm(nkr); +} + +Node BuiltinProofRuleChecker::applySubstitution(Node n, Node exp, MethodId ids) +{ + if (exp.isNull() || exp.getKind() != EQUAL) + { + return Node::null(); + } + Node nk = SkolemManager::getSkolemForm(n); + Node nks = applySubstitutionExternal(nk, exp, ids); + return SkolemManager::getWitnessForm(nks); +} + +Node BuiltinProofRuleChecker::applySubstitution(Node n, + const std::vector<Node>& exp, + MethodId ids) +{ + Node nk = SkolemManager::getSkolemForm(n); + Node nks = applySubstitutionExternal(nk, exp, ids); + return SkolemManager::getWitnessForm(nks); +} + +Node BuiltinProofRuleChecker::applySubstitutionRewrite( + Node n, const std::vector<Node>& exp, MethodId ids, MethodId idr) +{ + Node nk = SkolemManager::getSkolemForm(n); + Node nks = applySubstitutionExternal(nk, exp, ids); + Node nksr = applyRewriteExternal(nks, idr); + return SkolemManager::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 = SkolemManager::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; +} + +void BuiltinProofRuleChecker::addMethodIds(std::vector<Node>& args, + MethodId ids, + MethodId idr) +{ + bool ndefRewriter = (idr != MethodId::RW_REWRITE); + if (ids != MethodId::SB_DEFAULT || ndefRewriter) + { + args.push_back(mkMethodId(ids)); + } + if (ndefRewriter) + { + args.push_back(mkMethodId(idr)); + } +} + +} // 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..a2ec8b715 --- /dev/null +++ b/src/theory/builtin/proof_checker.h @@ -0,0 +1,159 @@ +/********************* */ +/*! \file proof_checker.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 method identifier from a node, return false if we fail */ + static bool getMethodId(TNode n, MethodId& i); + /** + * Get method identifiers from args starting at the given index. Store their + * values into ids, idr. This method returns false if args does not contain + * valid method identifiers at position index in args. + */ + bool getMethodIds(const std::vector<Node>& args, + MethodId& ids, + MethodId& idr, + size_t index); + /** + * Add method identifiers ids and idr as nodes to args. This does not add ids + * or idr if their values are the default ones. + */ + static void addMethodIds(std::vector<Node>& args, MethodId ids, MethodId idr); + + /** 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; + /** + * 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/builtin/theory_builtin.cpp b/src/theory/builtin/theory_builtin.cpp index a49903f13..695d5b91b 100644 --- a/src/theory/builtin/theory_builtin.cpp +++ b/src/theory/builtin/theory_builtin.cpp @@ -2,9 +2,9 @@ /*! \file theory_builtin.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Mudathir Mohamed, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/builtin/theory_builtin.h b/src/theory/builtin/theory_builtin.h index bf99003ec..e4767645e 100644 --- a/src/theory/builtin/theory_builtin.h +++ b/src/theory/builtin/theory_builtin.h @@ -2,9 +2,9 @@ /*! \file theory_builtin.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Mathias Preiner + ** Mudathir Mohamed, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/builtin/theory_builtin_rewriter.cpp b/src/theory/builtin/theory_builtin_rewriter.cpp index d8175dd60..47986c966 100644 --- a/src/theory/builtin/theory_builtin_rewriter.cpp +++ b/src/theory/builtin/theory_builtin_rewriter.cpp @@ -2,9 +2,9 @@ /*! \file theory_builtin_rewriter.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Dejan Jovanovic + ** Andrew Reynolds, Haniel Barbosa, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -98,12 +98,31 @@ RewriteResponse TheoryBuiltinRewriter::postRewrite(TNode node) { { for (unsigned i = 0; i < 2; i++) { + // (witness ((x T)) (= x t)) ---> t if (node[1][i] == node[0][0]) { + Trace("builtin-rewrite") << "Witness rewrite: " << node << " --> " + << node[1][1 - i] << std::endl; + // based on the witness terms we construct, this should be a legal + // elimination, since t should not contain x and be a subtype of x. + Assert(!expr::hasSubterm(node[1][1 - i], node[0][0])); + Assert(node[1][i].getType().isSubtypeOf(node[0][0].getType())); return RewriteResponse(REWRITE_DONE, node[1][1 - i]); } } } + else if (node[1] == node[0][0]) + { + // (witness ((x Bool)) x) ---> true + return RewriteResponse(REWRITE_DONE, + NodeManager::currentNM()->mkConst(true)); + } + else if (node[1].getKind() == kind::NOT && node[1][0] == node[0][0]) + { + // (witness ((x Bool)) (not x)) ---> false + return RewriteResponse(REWRITE_DONE, + NodeManager::currentNM()->mkConst(false)); + } return RewriteResponse(REWRITE_DONE, node); }else{ return doRewrite(node); @@ -201,9 +220,12 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambdaRec(TNode n, Node first_arg = n[0][0]; Node rec_bvl; - if( n[0].getNumChildren()>1 ){ + unsigned size = n[0].getNumChildren(); + if (size > 1) + { std::vector< Node > args; - for( unsigned i=1; i<n[0].getNumChildren(); i++ ){ + for (unsigned i = 1; i < size; i++) + { args.push_back( n[0][i] ); } rec_bvl = nm->mkNode(kind::BOUND_VAR_LIST, args); @@ -214,8 +236,8 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambdaRec(TNode n, std::vector< Node > vals; Node curr = n[1]; Kind ck = curr.getKind(); - while (ck == kind::ITE || ck == kind::EQUAL || ck == kind::NOT - || ck == kind::BOUND_VARIABLE) + while (ck == kind::ITE || ck == kind::OR || ck == kind::AND + || ck == kind::EQUAL || ck == kind::NOT || ck == kind::BOUND_VARIABLE) { Node index_eq; Node curr_val; @@ -234,13 +256,79 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambdaRec(TNode n, curr_val = curr[1]; next = curr[2]; } + else if (ck == kind::OR || ck == kind::AND) + { + Trace("builtin-rewrite-debug2") + << " process base : " << curr << std::endl; + // curr = Rewriter::rewrite(curr); + // Trace("builtin-rewrite-debug2") + // << " rewriten base : " << curr << std::endl; + // Complex Boolean return cases, in which + // (1) lambda x. (= x v1) v ... becomes + // lambda x. (ite (= x v1) true [...]) + // + // (2) lambda x. (not (= x v1)) ^ ... becomes + // lambda x. (ite (= x v1) false [...]) + // + // Note the negated cases of the lhs of the OR/AND operators above are + // handled by pushing the recursion to the then-branch, with the + // else-branch being the constant value. For example, the negated (1) + // would be + // (1') lambda x. (not (= x v1)) v ... becomes + // lambda x. (ite (= x v1) [...] true) + // thus requiring the rest of the disjunction to be further processed in + // the then-branch as the current value. + bool pol = curr[0].getKind() != kind::NOT; + bool inverted = (pol && ck == kind::AND) || (!pol && ck == kind::OR); + index_eq = pol ? curr[0] : curr[0][0]; + // processed : the value that is determined by the first child of curr + // remainder : the remaining children of curr + Node processed, remainder; + // the value is the polarity of the first child or its inverse if we are + // in the inverted case + processed = nm->mkConst(!inverted? pol : !pol); + // build an OR/AND with the remaining components + if (curr.getNumChildren() == 2) + { + remainder = curr[1]; + } + else + { + std::vector<Node> remainderNodes{curr.begin() + 1, curr.end()}; + remainder = nm->mkNode(ck, remainderNodes); + } + if (inverted) + { + curr_val = remainder; + next = processed; + // If the lambda contains more variables than the one being currently + // processed, the current value can be non-constant, since it'll be + // processed recursively below. Otherwise we fail. + if (rec_bvl.isNull() && !curr_val.isConst()) + { + Trace("builtin-rewrite-debug2") + << "...non-const curr_val " << curr_val << "\n"; + return Node::null(); + } + } + else + { + curr_val = processed; + next = remainder; + } + Trace("builtin-rewrite-debug2") << " index_eq : " << index_eq << "\n"; + Trace("builtin-rewrite-debug2") << " curr_val : " << curr_val << "\n"; + Trace("builtin-rewrite-debug2") << " next : " << next << std::endl; + } else { Trace("builtin-rewrite-debug2") << " process base : " << curr << std::endl; - // Boolean return case, e.g. lambda x. (= x v) becomes - // lambda x. (ite (= x v) true false) - bool pol = curr.getKind() != kind::NOT; + // Simple Boolean return cases, in which + // (1) lambda x. (= x v) becomes lambda x. (ite (= x v) true false) + // (2) lambda x. v becomes lambda x. (ite (= x v) true false) + // Note the negateg cases of the bodies above are also handled. + bool pol = ck != kind::NOT; index_eq = pol ? curr : curr[0]; curr_val = nm->mkConst(pol); next = nm->mkConst(!pol); @@ -291,11 +379,13 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambdaRec(TNode n, if (!val.isConst()) { // non-constant value - Trace("builtin-rewrite-debug2") << " ...non-constant value." << std::endl; + Trace("builtin-rewrite-debug2") + << " ...non-constant value for argument\n."; return Node::null(); }else{ curr_index = val; - Trace("builtin-rewrite-debug2") << " " << arg << " -> " << val << std::endl; + Trace("builtin-rewrite-debug2") + << " arg " << arg << " -> " << val << std::endl; break; } } @@ -312,7 +402,11 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambdaRec(TNode n, if (!rec_bvl.isNull()) { curr_val = nm->mkNode(kind::LAMBDA, rec_bvl, curr_val); + Trace("builtin-rewrite-debug") << push; + Trace("builtin-rewrite-debug2") << push; curr_val = getArrayRepresentationForLambdaRec(curr_val, retType); + Trace("builtin-rewrite-debug") << pop; + Trace("builtin-rewrite-debug2") << pop; if (curr_val.isNull()) { Trace("builtin-rewrite-debug2") @@ -330,28 +424,39 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambdaRec(TNode n, // we will now process the remainder curr = next; ck = curr.getKind(); + Trace("builtin-rewrite-debug2") + << " process remainder : " << curr << std::endl; } if( !rec_bvl.isNull() ){ - curr = NodeManager::currentNM()->mkNode( kind::LAMBDA, rec_bvl, curr ); + curr = nm->mkNode(kind::LAMBDA, rec_bvl, curr); + Trace("builtin-rewrite-debug") << push; + Trace("builtin-rewrite-debug2") << push; curr = getArrayRepresentationForLambdaRec(curr, retType); + Trace("builtin-rewrite-debug") << pop; + Trace("builtin-rewrite-debug2") << pop; } if( !curr.isNull() && curr.isConst() ){ // compute the return type TypeNode array_type = retType; - for( unsigned i=0; i<n[0].getNumChildren(); i++ ){ - unsigned index = (n[0].getNumChildren()-1)-i; - array_type = NodeManager::currentNM()->mkArrayType( n[0][index].getType(), array_type ); + for (unsigned i = 0; i < size; i++) + { + unsigned index = (size - 1) - i; + array_type = nm->mkArrayType(n[0][index].getType(), array_type); } Trace("builtin-rewrite-debug2") << " make array store all " << curr.getType() << " annotated : " << array_type << std::endl; Assert(curr.getType().isSubtypeOf(array_type.getArrayConstituentType())); - curr = NodeManager::currentNM()->mkConst(ArrayStoreAll(((ArrayType)array_type.toType()), curr.toExpr())); + curr = nm->mkConst( + ArrayStoreAll((ArrayType(array_type.toType())), curr.toExpr())); Trace("builtin-rewrite-debug2") << " build array..." << std::endl; // can only build if default value is constant (since array store all must be constant) Trace("builtin-rewrite-debug2") << " got constant base " << curr << std::endl; + Trace("builtin-rewrite-debug2") << " conditions " << conds << std::endl; + Trace("builtin-rewrite-debug2") << " values " << vals << std::endl; // construct store chain - for( int i=((int)conds.size()-1); i>=0; i-- ){ + for (int i = static_cast<int>(conds.size()) - 1; i >= 0; i--) + { Assert(conds[i].getType().isSubtypeOf(first_arg.getType())); - curr = NodeManager::currentNM()->mkNode( kind::STORE, curr, conds[i], vals[i] ); + curr = nm->mkNode(kind::STORE, curr, conds[i], vals[i]); } Trace("builtin-rewrite-debug") << "...got array " << curr << " for " << n << std::endl; return curr; @@ -364,8 +469,9 @@ Node TheoryBuiltinRewriter::getArrayRepresentationForLambdaRec(TNode n, Node TheoryBuiltinRewriter::getArrayRepresentationForLambda(TNode n) { Assert(n.getKind() == kind::LAMBDA); - // must carry the overall return type to deal with cases like (lambda ((x Int)(y Int)) (ite (= x _) 0.5 0.0)), - // where the inner construction for the else case about should be (arraystoreall (Array Int Real) 0.0) + // must carry the overall return type to deal with cases like (lambda ((x Int) + // (y Int)) (ite (= x _) 0.5 0.0)), where the inner construction for the else + // case above should be (arraystoreall (Array Int Real) 0.0) Node anode = getArrayRepresentationForLambdaRec(n, n[1].getType()); if (anode.isNull()) { diff --git a/src/theory/builtin/theory_builtin_rewriter.h b/src/theory/builtin/theory_builtin_rewriter.h index 4b75d7e3a..930a316a2 100644 --- a/src/theory/builtin/theory_builtin_rewriter.h +++ b/src/theory/builtin/theory_builtin_rewriter.h @@ -2,9 +2,9 @@ /*! \file theory_builtin_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Dejan Jovanovic, Morgan Deters + ** Andrew Reynolds, Andres Noetzli, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/builtin/theory_builtin_type_rules.h b/src/theory/builtin/theory_builtin_type_rules.h index 28d6c9037..3a6b9bfff 100644 --- a/src/theory/builtin/theory_builtin_type_rules.h +++ b/src/theory/builtin/theory_builtin_type_rules.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andrew Reynolds, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/builtin/type_enumerator.cpp b/src/theory/builtin/type_enumerator.cpp index 10c6d16dc..f971a6242 100644 --- a/src/theory/builtin/type_enumerator.cpp +++ b/src/theory/builtin/type_enumerator.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/builtin/type_enumerator.h b/src/theory/builtin/type_enumerator.h index 8ce17306f..edac15d86 100644 --- a/src/theory/builtin/type_enumerator.h +++ b/src/theory/builtin/type_enumerator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/abstraction.cpp b/src/theory/bv/abstraction.cpp index f2f12a548..a9ec7aa53 100644 --- a/src/theory/bv/abstraction.cpp +++ b/src/theory/bv/abstraction.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/abstraction.h b/src/theory/bv/abstraction.h index 4895d1818..77fe1e363 100644 --- a/src/theory/bv/abstraction.h +++ b/src/theory/bv/abstraction.h @@ -2,9 +2,9 @@ /*! \file abstraction.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Tim King, Guy Katz + ** Liana Hadarean, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bitblast/aig_bitblaster.cpp b/src/theory/bv/bitblast/aig_bitblaster.cpp index 295090699..331db9378 100644 --- a/src/theory/bv/bitblast/aig_bitblaster.cpp +++ b/src/theory/bv/bitblast/aig_bitblaster.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bitblast/aig_bitblaster.h b/src/theory/bv/bitblast/aig_bitblaster.h index 4e11c0f36..1e1b5bab4 100644 --- a/src/theory/bv/bitblast/aig_bitblaster.h +++ b/src/theory/bv/bitblast/aig_bitblaster.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bitblast/bitblast_strategies_template.h b/src/theory/bv/bitblast/bitblast_strategies_template.h index 463203118..7f1fe4eeb 100644 --- a/src/theory/bv/bitblast/bitblast_strategies_template.h +++ b/src/theory/bv/bitblast/bitblast_strategies_template.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Aina Niemetz, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bitblast/bitblast_utils.h b/src/theory/bv/bitblast/bitblast_utils.h index 03e0aa349..13ae129be 100644 --- a/src/theory/bv/bitblast/bitblast_utils.h +++ b/src/theory/bv/bitblast/bitblast_utils.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Dejan Jovanovic, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bitblast/bitblaster.h b/src/theory/bv/bitblast/bitblaster.h index a16a8bbbf..82921b3a0 100644 --- a/src/theory/bv/bitblast/bitblaster.h +++ b/src/theory/bv/bitblast/bitblaster.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Mathias Preiner, Alex Ozdemir ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bitblast/eager_bitblaster.cpp b/src/theory/bv/bitblast/eager_bitblaster.cpp index 0ba69c8b8..ef583cc13 100644 --- a/src/theory/bv/bitblast/eager_bitblaster.cpp +++ b/src/theory/bv/bitblast/eager_bitblaster.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bitblast/eager_bitblaster.h b/src/theory/bv/bitblast/eager_bitblaster.h index d407b8131..a8b7ccbe5 100644 --- a/src/theory/bv/bitblast/eager_bitblaster.h +++ b/src/theory/bv/bitblast/eager_bitblaster.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner, Liana Hadarean, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bitblast/lazy_bitblaster.cpp b/src/theory/bv/bitblast/lazy_bitblaster.cpp index 463ffae79..9abeee65e 100644 --- a/src/theory/bv/bitblast/lazy_bitblaster.cpp +++ b/src/theory/bv/bitblast/lazy_bitblaster.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -440,11 +440,13 @@ void TLazyBitblaster::MinisatNotify::safePoint(ResourceManager::Resource r) EqualityStatus TLazyBitblaster::getEqualityStatus(TNode a, TNode b) { int numAssertions = d_bv->numAssertions(); + bool has_full_model = + numAssertions != 0 && d_fullModelAssertionLevel.get() == numAssertions; + Debug("bv-equality-status") << "TLazyBitblaster::getEqualityStatus " << a << " = " << b << "\n"; Debug("bv-equality-status") - << "BVSatSolver has full model? " - << (d_fullModelAssertionLevel.get() == numAssertions) << "\n"; + << "BVSatSolver has full model? " << has_full_model << "\n"; // First check if it trivially rewrites to false/true Node a_eq_b = @@ -453,7 +455,7 @@ EqualityStatus TLazyBitblaster::getEqualityStatus(TNode a, TNode b) if (a_eq_b == utils::mkFalse()) return theory::EQUALITY_FALSE; if (a_eq_b == utils::mkTrue()) return theory::EQUALITY_TRUE; - if (d_fullModelAssertionLevel.get() != numAssertions) + if (!has_full_model) { return theory::EQUALITY_UNKNOWN; } diff --git a/src/theory/bv/bitblast/lazy_bitblaster.h b/src/theory/bv/bitblast/lazy_bitblaster.h index 3fe2398f1..a355d42c4 100644 --- a/src/theory/bv/bitblast/lazy_bitblaster.h +++ b/src/theory/bv/bitblast/lazy_bitblaster.h @@ -2,9 +2,9 @@ /*! \file lazy_bitblaster.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Mathias Preiner, Tim King + ** Liana Hadarean, Mathias Preiner, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_eager_solver.cpp b/src/theory/bv/bv_eager_solver.cpp index d743a6023..36aa72da3 100644 --- a/src/theory/bv/bv_eager_solver.cpp +++ b/src/theory/bv/bv_eager_solver.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner, Liana Hadarean, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_eager_solver.h b/src/theory/bv/bv_eager_solver.h index 8e42d5cab..6182832e9 100644 --- a/src/theory/bv/bv_eager_solver.h +++ b/src/theory/bv/bv_eager_solver.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_inequality_graph.cpp b/src/theory/bv/bv_inequality_graph.cpp index ed8756456..05d6806f8 100644 --- a/src/theory/bv/bv_inequality_graph.cpp +++ b/src/theory/bv/bv_inequality_graph.cpp @@ -2,9 +2,9 @@ /*! \file bv_inequality_graph.cpp ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Aina Niemetz, Morgan Deters + ** Liana Hadarean, Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_inequality_graph.h b/src/theory/bv/bv_inequality_graph.h index 9e8078a72..77984d217 100644 --- a/src/theory/bv/bv_inequality_graph.h +++ b/src/theory/bv/bv_inequality_graph.h @@ -2,9 +2,9 @@ /*! \file bv_inequality_graph.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Tim King, Clark Barrett + ** Liana Hadarean, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_quick_check.cpp b/src/theory/bv/bv_quick_check.cpp index dbdeccfe5..ed445eb33 100644 --- a/src/theory/bv/bv_quick_check.cpp +++ b/src/theory/bv/bv_quick_check.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_quick_check.h b/src/theory/bv/bv_quick_check.h index 75f39b6e0..03a62e41b 100644 --- a/src/theory/bv/bv_quick_check.h +++ b/src/theory/bv/bv_quick_check.h @@ -2,9 +2,9 @@ /*! \file bv_quick_check.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Morgan Deters, Mathias Preiner + ** Liana Hadarean, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_subtheory.h b/src/theory/bv/bv_subtheory.h index 60660eda9..725b61f95 100644 --- a/src/theory/bv/bv_subtheory.h +++ b/src/theory/bv/bv_subtheory.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Tim King, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_subtheory_algebraic.cpp b/src/theory/bv/bv_subtheory_algebraic.cpp index de8a0e11e..e5a416a1b 100644 --- a/src/theory/bv/bv_subtheory_algebraic.cpp +++ b/src/theory/bv/bv_subtheory_algebraic.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Aina Niemetz, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_subtheory_algebraic.h b/src/theory/bv/bv_subtheory_algebraic.h index de75ad859..d9a9bce6f 100644 --- a/src/theory/bv/bv_subtheory_algebraic.h +++ b/src/theory/bv/bv_subtheory_algebraic.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_subtheory_bitblast.cpp b/src/theory/bv/bv_subtheory_bitblast.cpp index b5e4b7c85..8f87bc4b8 100644 --- a/src/theory/bv/bv_subtheory_bitblast.cpp +++ b/src/theory/bv/bv_subtheory_bitblast.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Aina Niemetz, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_subtheory_bitblast.h b/src/theory/bv/bv_subtheory_bitblast.h index 0b0a9521b..a2b099609 100644 --- a/src/theory/bv/bv_subtheory_bitblast.h +++ b/src/theory/bv/bv_subtheory_bitblast.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Mathias Preiner, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_subtheory_core.cpp b/src/theory/bv/bv_subtheory_core.cpp index 5d9c297f1..668d7b87e 100644 --- a/src/theory/bv/bv_subtheory_core.cpp +++ b/src/theory/bv/bv_subtheory_core.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Aina Niemetz, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_subtheory_core.h b/src/theory/bv/bv_subtheory_core.h index e2026d4a5..a9ca57fb4 100644 --- a/src/theory/bv/bv_subtheory_core.h +++ b/src/theory/bv/bv_subtheory_core.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_subtheory_inequality.cpp b/src/theory/bv/bv_subtheory_inequality.cpp index 8a895e9eb..1ff23c460 100644 --- a/src/theory/bv/bv_subtheory_inequality.cpp +++ b/src/theory/bv/bv_subtheory_inequality.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Aina Niemetz, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/bv_subtheory_inequality.h b/src/theory/bv/bv_subtheory_inequality.h index e18c886df..abfb0d3cf 100644 --- a/src/theory/bv/bv_subtheory_inequality.h +++ b/src/theory/bv/bv_subtheory_inequality.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/slicer.cpp b/src/theory/bv/slicer.cpp index e1732625e..4524ddb8c 100644 --- a/src/theory/bv/slicer.cpp +++ b/src/theory/bv/slicer.cpp @@ -2,9 +2,9 @@ /*! \file slicer.cpp ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Aina Niemetz, Tim King + ** Liana Hadarean, Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/slicer.h b/src/theory/bv/slicer.h index 88ac0debb..794df633f 100644 --- a/src/theory/bv/slicer.h +++ b/src/theory/bv/slicer.h @@ -2,9 +2,9 @@ /*! \file slicer.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Tim King + ** Liana Hadarean, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp index fd8459641..1bbcc05ce 100644 --- a/src/theory/bv/theory_bv.cpp +++ b/src/theory/bv/theory_bv.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Andrew Reynolds, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h index 7f88d8388..513ed6bc0 100644 --- a/src/theory/bv/theory_bv.h +++ b/src/theory/bv/theory_bv.h @@ -2,9 +2,9 @@ /*! \file theory_bv.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Tim King, Andrew Reynolds + ** Liana Hadarean, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv_rewrite_rules.h b/src/theory/bv/theory_bv_rewrite_rules.h index 44ac14464..6e7fb37d0 100644 --- a/src/theory/bv/theory_bv_rewrite_rules.h +++ b/src/theory/bv/theory_bv_rewrite_rules.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Dejan Jovanovic, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h b/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h index 27fad165f..f007bbc16 100644 --- a/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h +++ b/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Clark Barrett, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv_rewrite_rules_core.h b/src/theory/bv/theory_bv_rewrite_rules_core.h index 4a66aa847..53c8546a3 100644 --- a/src/theory/bv/theory_bv_rewrite_rules_core.h +++ b/src/theory/bv/theory_bv_rewrite_rules_core.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Liana Hadarean, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv_rewrite_rules_normalization.h b/src/theory/bv/theory_bv_rewrite_rules_normalization.h index cd705e27e..6055ce86e 100644 --- a/src/theory/bv/theory_bv_rewrite_rules_normalization.h +++ b/src/theory/bv/theory_bv_rewrite_rules_normalization.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Aina Niemetz, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h b/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h index 6be1e7203..3ff3a88b3 100644 --- a/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h +++ b/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h @@ -2,9 +2,9 @@ /*! \file theory_bv_rewrite_rules_operator_elimination.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Aina Niemetz, Clark Barrett + ** Liana Hadarean, Aina Niemetz, Yoni Zohar ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv_rewrite_rules_simplification.h b/src/theory/bv/theory_bv_rewrite_rules_simplification.h index 9e6c31061..c35f33f53 100644 --- a/src/theory/bv/theory_bv_rewrite_rules_simplification.h +++ b/src/theory/bv/theory_bv_rewrite_rules_simplification.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv_rewriter.cpp b/src/theory/bv/theory_bv_rewriter.cpp index 6a04d6e4e..0b1b58f9a 100644 --- a/src/theory/bv/theory_bv_rewriter.cpp +++ b/src/theory/bv/theory_bv_rewriter.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Liana Hadarean, Aina Niemetz, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv_rewriter.h b/src/theory/bv/theory_bv_rewriter.h index 8c8b7846c..74e8b4f79 100644 --- a/src/theory/bv/theory_bv_rewriter.h +++ b/src/theory/bv/theory_bv_rewriter.h @@ -2,9 +2,9 @@ /*! \file theory_bv_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Morgan Deters, Dejan Jovanovic + ** Liana Hadarean, Andres Noetzli, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv_type_rules.h b/src/theory/bv/theory_bv_type_rules.h index 97b7a8a8f..ea3e30d9e 100644 --- a/src/theory/bv/theory_bv_type_rules.h +++ b/src/theory/bv/theory_bv_type_rules.h @@ -2,9 +2,9 @@ /*! \file theory_bv_type_rules.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Andrew Reynolds, Morgan Deters + ** Aina Niemetz, Andrew Reynolds, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -302,6 +302,10 @@ class BitVectorRepeatTypeRule throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term"); } unsigned repeatAmount = n.getOperator().getConst<BitVectorRepeat>(); + if (repeatAmount == 0) + { + throw TypeCheckingExceptionPrivate(n, "expecting number of repeats > 0"); + } return nodeManager->mkBitVectorType(repeatAmount * t.getBitVectorSize()); } }; /* class BitVectorRepeatTypeRule */ @@ -339,6 +343,10 @@ class IntToBitVectorOpTypeRule if (n.getKind() == kind::INT_TO_BITVECTOR_OP) { size_t bvSize = n.getConst<IntToBitVector>(); + if (bvSize == 0) + { + throw TypeCheckingExceptionPrivate(n, "expecting bit-width > 0"); + } return nodeManager->mkFunctionType(nodeManager->integerType(), nodeManager->mkBitVectorType(bvSize)); } diff --git a/src/theory/bv/theory_bv_utils.cpp b/src/theory/bv/theory_bv_utils.cpp index b98aacb2f..b7b3ebf57 100644 --- a/src/theory/bv/theory_bv_utils.cpp +++ b/src/theory/bv/theory_bv_utils.cpp @@ -2,9 +2,9 @@ /*! \file theory_bv_utils.cpp ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Liana Hadarean, Andrew Reynolds + ** Aina Niemetz, Andrew Reynolds, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/theory_bv_utils.h b/src/theory/bv/theory_bv_utils.h index 4303926f1..92c7f3d00 100644 --- a/src/theory/bv/theory_bv_utils.h +++ b/src/theory/bv/theory_bv_utils.h @@ -2,9 +2,9 @@ /*! \file theory_bv_utils.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Dejan Jovanovic, Tim King + ** Aina Niemetz, Andrew Reynolds, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/bv/type_enumerator.h b/src/theory/bv/type_enumerator.h index 90aae339b..6a388cc0e 100644 --- a/src/theory/bv/type_enumerator.h +++ b/src/theory/bv/type_enumerator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/care_graph.h b/src/theory/care_graph.h index f17f67ee0..121d605dc 100644 --- a/src/theory/care_graph.h +++ b/src/theory/care_graph.h @@ -2,9 +2,9 @@ /*! \file care_graph.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Tim King, Morgan Deters + ** Andrew Reynolds, Dejan Jovanovic, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/datatypes/datatypes_rewriter.cpp b/src/theory/datatypes/datatypes_rewriter.cpp index 77cb45f36..699e26d21 100644 --- a/src/theory/datatypes/datatypes_rewriter.cpp +++ b/src/theory/datatypes/datatypes_rewriter.cpp @@ -2,9 +2,9 @@ /*! \file datatypes_rewriter.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Paul Meng + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -20,6 +20,7 @@ #include "expr/node_algorithm.h" #include "expr/sygus_datatype.h" #include "options/datatypes_options.h" +#include "theory/datatypes/sygus_datatype_utils.h" #include "theory/datatypes/theory_datatypes_utils.h" using namespace CVC4; diff --git a/src/theory/datatypes/datatypes_rewriter.h b/src/theory/datatypes/datatypes_rewriter.h index 8f24a5aef..7f39a68ab 100644 --- a/src/theory/datatypes/datatypes_rewriter.h +++ b/src/theory/datatypes/datatypes_rewriter.h @@ -2,9 +2,9 @@ /*! \file datatypes_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Dejan Jovanovic + ** Andrew Reynolds, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/datatypes/sygus_datatype_utils.cpp b/src/theory/datatypes/sygus_datatype_utils.cpp new file mode 100644 index 000000000..3caee52f9 --- /dev/null +++ b/src/theory/datatypes/sygus_datatype_utils.cpp @@ -0,0 +1,741 @@ +/********************* */ +/*! \file sygus_datatype_utils.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds, Morgan Deters, Mathias Preiner + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 rewriter for the theory of (co)inductive datatypes. + ** + ** Implementation of rewriter for the theory of (co)inductive datatypes. + **/ + +#include "theory/datatypes/sygus_datatype_utils.h" + +#include "expr/dtype.h" +#include "expr/node_algorithm.h" +#include "expr/sygus_datatype.h" +#include "printer/sygus_print_callback.h" +#include "smt/smt_engine.h" +#include "smt/smt_engine_scope.h" +#include "theory/evaluator.h" +#include "theory/rewriter.h" + +using namespace CVC4; +using namespace CVC4::kind; + +namespace CVC4 { +namespace theory { +namespace datatypes { +namespace utils { + +Node applySygusArgs(const DType& dt, + Node op, + Node n, + const std::vector<Node>& args) +{ + if (n.getKind() == BOUND_VARIABLE) + { + Assert(n.hasAttribute(SygusVarNumAttribute())); + int vn = n.getAttribute(SygusVarNumAttribute()); + Assert(dt.getSygusVarList()[vn] == n); + return args[vn]; + } + // n is an application of operator op. + // We must compute the free variables in op to determine if there are + // any substitutions we need to make to n. + TNode val; + if (!op.hasAttribute(SygusVarFreeAttribute())) + { + std::unordered_set<Node, NodeHashFunction> fvs; + if (expr::getFreeVariables(op, fvs)) + { + if (fvs.size() == 1) + { + for (const Node& v : fvs) + { + val = v; + } + } + else + { + val = op; + } + } + Trace("dt-sygus-fv") << "Free var in " << op << " : " << val << std::endl; + op.setAttribute(SygusVarFreeAttribute(), val); + } + else + { + val = op.getAttribute(SygusVarFreeAttribute()); + } + if (val.isNull()) + { + return n; + } + if (val.getKind() == BOUND_VARIABLE) + { + // single substitution case + int vn = val.getAttribute(SygusVarNumAttribute()); + TNode sub = args[vn]; + return n.substitute(val, sub); + } + // do the full substitution + std::vector<Node> vars; + Node bvl = dt.getSygusVarList(); + for (unsigned i = 0, nvars = bvl.getNumChildren(); i < nvars; i++) + { + vars.push_back(bvl[i]); + } + return n.substitute(vars.begin(), vars.end(), args.begin(), args.end()); +} + +Kind getOperatorKindForSygusBuiltin(Node op) +{ + Assert(op.getKind() != BUILTIN); + if (op.getKind() == LAMBDA) + { + return APPLY_UF; + } + return NodeManager::getKindForFunction(op); +} + +struct SygusOpRewrittenAttributeId +{ +}; +typedef expr::Attribute<SygusOpRewrittenAttributeId, Node> + SygusOpRewrittenAttribute; + +Kind getEliminateKind(Kind ok) +{ + Kind nk = ok; + // We also must ensure that builtin operators which are eliminated + // during expand definitions are replaced by the proper operator. + if (ok == BITVECTOR_UDIV) + { + nk = BITVECTOR_UDIV_TOTAL; + } + else if (ok == BITVECTOR_UREM) + { + nk = BITVECTOR_UREM_TOTAL; + } + else if (ok == DIVISION) + { + nk = DIVISION_TOTAL; + } + else if (ok == INTS_DIVISION) + { + nk = INTS_DIVISION_TOTAL; + } + else if (ok == INTS_MODULUS) + { + nk = INTS_MODULUS_TOTAL; + } + return nk; +} + +Node eliminatePartialOperators(Node n) +{ + NodeManager* nm = NodeManager::currentNM(); + std::unordered_map<TNode, Node, TNodeHashFunction> visited; + std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it; + std::vector<TNode> visit; + TNode cur; + visit.push_back(n); + do + { + cur = visit.back(); + visit.pop_back(); + it = visited.find(cur); + + if (it == visited.end()) + { + visited[cur] = Node::null(); + visit.push_back(cur); + for (const Node& cn : cur) + { + visit.push_back(cn); + } + } + else if (it->second.isNull()) + { + Node ret = cur; + bool childChanged = false; + std::vector<Node> children; + if (cur.getMetaKind() == metakind::PARAMETERIZED) + { + children.push_back(cur.getOperator()); + } + for (const Node& cn : cur) + { + it = visited.find(cn); + Assert(it != visited.end()); + Assert(!it->second.isNull()); + childChanged = childChanged || cn != it->second; + children.push_back(it->second); + } + Kind ok = cur.getKind(); + Kind nk = getEliminateKind(ok); + if (nk != ok || childChanged) + { + ret = nm->mkNode(nk, children); + } + visited[cur] = ret; + } + } while (!visit.empty()); + Assert(visited.find(n) != visited.end()); + Assert(!visited.find(n)->second.isNull()); + return visited[n]; +} + +Node mkSygusTerm(const DType& dt, + unsigned i, + const std::vector<Node>& children, + bool doBetaReduction, + bool isExternal) +{ + Trace("dt-sygus-util") << "Make sygus term " << dt.getName() << "[" << i + << "] with children: " << children << std::endl; + Assert(i < dt.getNumConstructors()); + Assert(dt.isSygus()); + Assert(!dt[i].getSygusOp().isNull()); + Node op = dt[i].getSygusOp(); + Node opn = op; + if (!isExternal) + { + // Get the normalized version of the sygus operator. We do this by + // expanding definitions, rewriting it, and eliminating partial operators. + if (!op.hasAttribute(SygusOpRewrittenAttribute())) + { + if (op.isConst()) + { + // If it is a builtin operator, convert to total version if necessary. + // First, get the kind for the operator. + Kind ok = NodeManager::operatorToKind(op); + Trace("sygus-grammar-normalize-debug") + << "...builtin kind is " << ok << std::endl; + Kind nk = getEliminateKind(ok); + if (nk != ok) + { + Trace("sygus-grammar-normalize-debug") + << "...replace by builtin operator " << nk << std::endl; + opn = NodeManager::currentNM()->operatorOf(nk); + } + } + else + { + // Only expand definitions if the operator is not constant, since + // calling expandDefinitions on them should be a no-op. This check + // ensures we don't try to expand e.g. bitvector extract operators, + // whose type is undefined, and thus should not be passed to + // expandDefinitions. + opn = Node::fromExpr( + smt::currentSmtEngine()->expandDefinitions(op.toExpr())); + opn = Rewriter::rewrite(opn); + opn = eliminatePartialOperators(opn); + SygusOpRewrittenAttribute sora; + op.setAttribute(sora, opn); + } + } + else + { + opn = op.getAttribute(SygusOpRewrittenAttribute()); + } + } + return mkSygusTerm(opn, children, doBetaReduction); +} + +Node mkSygusTerm(Node op, + const std::vector<Node>& children, + bool doBetaReduction) +{ + Trace("dt-sygus-util") << "Operator is " << op << std::endl; + if (children.empty()) + { + // no children, return immediately + Trace("dt-sygus-util") << "...return direct op" << std::endl; + return op; + } + // if it is the any constant, we simply return the child + if (op.getAttribute(SygusAnyConstAttribute())) + { + Assert(children.size() == 1); + return children[0]; + } + std::vector<Node> schildren; + // get the kind of the operator + Kind ok = op.getKind(); + if (ok != BUILTIN) + { + if (ok == LAMBDA && doBetaReduction) + { + // Do immediate beta reduction. It suffices to use a normal substitution + // since neither op nor children have quantifiers, since they are + // generated by sygus grammars. + std::vector<Node> vars{op[0].begin(), op[0].end()}; + Assert(vars.size() == children.size()); + Node ret = op[1].substitute( + vars.begin(), vars.end(), children.begin(), children.end()); + Trace("dt-sygus-util") << "...return (beta-reduce) " << ret << std::endl; + return ret; + } + else + { + schildren.push_back(op); + } + } + schildren.insert(schildren.end(), children.begin(), children.end()); + Node ret; + if (ok == BUILTIN) + { + ret = NodeManager::currentNM()->mkNode(op, schildren); + Trace("dt-sygus-util") << "...return (builtin) " << ret << std::endl; + return ret; + } + // get the kind used for applying op + Kind otk = NodeManager::operatorToKind(op); + Trace("dt-sygus-util") << "operator kind is " << otk << std::endl; + if (otk != UNDEFINED_KIND) + { + // If it is an APPLY_UF operator, we should have at least an operator and + // a child. + Assert(otk != APPLY_UF || schildren.size() != 1); + ret = NodeManager::currentNM()->mkNode(otk, schildren); + Trace("dt-sygus-util") << "...return (op) " << ret << std::endl; + return ret; + } + Kind tok = getOperatorKindForSygusBuiltin(op); + if (schildren.size() == 1 && tok == UNDEFINED_KIND) + { + ret = schildren[0]; + } + else + { + ret = NodeManager::currentNM()->mkNode(tok, schildren); + } + Trace("dt-sygus-util") << "...return " << ret << std::endl; + return ret; +} + +struct SygusToBuiltinTermAttributeId +{ +}; +typedef expr::Attribute<SygusToBuiltinTermAttributeId, Node> + SygusToBuiltinTermAttribute; + +Node sygusToBuiltin(Node n, bool isExternal) +{ + Assert(n.isConst()); + std::unordered_map<TNode, Node, TNodeHashFunction> visited; + std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it; + std::vector<TNode> visit; + TNode cur; + unsigned index; + visit.push_back(n); + do + { + cur = visit.back(); + visit.pop_back(); + it = visited.find(cur); + if (it == visited.end()) + { + if (cur.getKind() == APPLY_CONSTRUCTOR) + { + if (!isExternal && cur.hasAttribute(SygusToBuiltinTermAttribute())) + { + visited[cur] = cur.getAttribute(SygusToBuiltinTermAttribute()); + } + else + { + visited[cur] = Node::null(); + visit.push_back(cur); + for (const Node& cn : cur) + { + visit.push_back(cn); + } + } + } + else + { + // non-datatypes are themselves + visited[cur] = cur; + } + } + else if (it->second.isNull()) + { + Node ret = cur; + Assert(cur.getKind() == APPLY_CONSTRUCTOR); + const DType& dt = cur.getType().getDType(); + // Non sygus-datatype terms are also themselves. Notice we treat the + // case of non-sygus datatypes this way since it avoids computing + // the type / datatype of the node in the pre-traversal above. The + // case of non-sygus datatypes is very rare, so the extra addition to + // visited is justified performance-wise. + if (dt.isSygus()) + { + std::vector<Node> children; + for (const Node& cn : cur) + { + it = visited.find(cn); + Assert(it != visited.end()); + Assert(!it->second.isNull()); + children.push_back(it->second); + } + index = indexOf(cur.getOperator()); + ret = mkSygusTerm(dt, index, children, true, isExternal); + } + visited[cur] = ret; + // cache + if (!isExternal) + { + SygusToBuiltinTermAttribute stbt; + cur.setAttribute(stbt, ret); + } + } + } while (!visit.empty()); + Assert(visited.find(n) != visited.end()); + Assert(!visited.find(n)->second.isNull()); + return visited[n]; +} + +Node sygusToBuiltinEval(Node n, const std::vector<Node>& args) +{ + NodeManager* nm = NodeManager::currentNM(); + Evaluator eval; + // constant arguments? + bool constArgs = true; + for (const Node& a : args) + { + if (!a.isConst()) + { + constArgs = false; + break; + } + } + std::vector<Node> eargs; + bool svarsInit = false; + std::vector<Node> svars; + std::unordered_map<TNode, Node, TNodeHashFunction> visited; + std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it; + std::vector<TNode> visit; + TNode cur; + unsigned index; + visit.push_back(n); + do + { + cur = visit.back(); + visit.pop_back(); + it = visited.find(cur); + if (it == visited.end()) + { + TypeNode tn = cur.getType(); + if (!tn.isDatatype() || !tn.getDType().isSygus()) + { + visited[cur] = cur; + } + else if (cur.isConst()) + { + // convert to builtin term + Node bt = sygusToBuiltin(cur); + // run the evaluator if possible + if (!svarsInit) + { + svarsInit = true; + TypeNode type = cur.getType(); + Node varList = type.getDType().getSygusVarList(); + for (const Node& v : varList) + { + svars.push_back(v); + } + } + Assert(args.size() == svars.size()); + // try evaluation if we have constant arguments + Node ret = constArgs ? eval.eval(bt, svars, args) : Node::null(); + if (ret.isNull()) + { + // if evaluation was not available, use a substitution + ret = bt.substitute( + svars.begin(), svars.end(), args.begin(), args.end()); + } + visited[cur] = ret; + } + else + { + if (cur.getKind() == APPLY_CONSTRUCTOR) + { + visited[cur] = Node::null(); + visit.push_back(cur); + for (const Node& cn : cur) + { + visit.push_back(cn); + } + } + else + { + // it is the evaluation of this term on the arguments + if (eargs.empty()) + { + eargs.push_back(cur); + eargs.insert(eargs.end(), args.begin(), args.end()); + } + else + { + eargs[0] = cur; + } + visited[cur] = nm->mkNode(DT_SYGUS_EVAL, eargs); + } + } + } + else if (it->second.isNull()) + { + Node ret = cur; + Assert(cur.getKind() == APPLY_CONSTRUCTOR); + const DType& dt = cur.getType().getDType(); + // non sygus-datatype terms are also themselves + if (dt.isSygus()) + { + std::vector<Node> children; + for (const Node& cn : cur) + { + it = visited.find(cn); + Assert(it != visited.end()); + Assert(!it->second.isNull()); + children.push_back(it->second); + } + index = indexOf(cur.getOperator()); + // apply to arguments + ret = mkSygusTerm(dt, index, children); + } + visited[cur] = ret; + } + } while (!visit.empty()); + Assert(visited.find(n) != visited.end()); + Assert(!visited.find(n)->second.isNull()); + 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 +} // namespace CVC4 diff --git a/src/theory/datatypes/sygus_datatype_utils.h b/src/theory/datatypes/sygus_datatype_utils.h new file mode 100644 index 000000000..593577b8e --- /dev/null +++ b/src/theory/datatypes/sygus_datatype_utils.h @@ -0,0 +1,229 @@ +/********************* */ +/*! \file sygus_datatype_utils.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 Util functions for sygus datatypes + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__THEORY__STRINGS__SYGUS_DATATYPE_UTILS_H +#define CVC4__THEORY__STRINGS__SYGUS_DATATYPE_UTILS_H + +#include <vector> + +#include "expr/dtype.h" +#include "expr/node.h" +#include "expr/node_manager_attributes.h" +#include "theory/datatypes/theory_datatypes_utils.h" + +namespace CVC4 { +namespace theory { + +// ----------------------- sygus datatype attributes +/** sygus var num */ +struct SygusVarNumAttributeId +{ +}; +typedef expr::Attribute<SygusVarNumAttributeId, uint64_t> SygusVarNumAttribute; + +/** + * Attribute true for enumerators whose current model values were registered by + * the datatypes sygus solver, and were not excluded by sygus symmetry breaking. + * This is set by the datatypes sygus solver during LAST_CALL effort checks for + * each active sygus enumerator. + */ +struct SygusSymBreakOkAttributeId +{ +}; +typedef expr::Attribute<SygusSymBreakOkAttributeId, bool> + SygusSymBreakOkAttribute; + +/** sygus var free + * + * This attribute is used to mark whether sygus operators have free occurrences + * of variables from the formal argument list of the function-to-synthesize. + * + * We store three possible cases for sygus operators op: + * (1) op.getAttribute(SygusVarFreeAttribute())==Node::null() + * In this case, op has no free variables from the formal argument list of the + * function-to-synthesize. + * (2) op.getAttribute(SygusVarFreeAttribute())==v, where v is a bound variable. + * In this case, op has exactly one free variable, v. + * (3) op.getAttribute(SygusVarFreeAttribute())==op + * In this case, op has an arbitrary set (cardinality >1) of free variables from + * the formal argument list of the function to synthesize. + * + * This attribute is used to compute applySygusArgs below. + */ +struct SygusVarFreeAttributeId +{ +}; +typedef expr::Attribute<SygusVarFreeAttributeId, Node> SygusVarFreeAttribute; +// ----------------------- end sygus datatype attributes + +namespace datatypes { +namespace utils { + + +/** get operator kind for sygus builtin + * + * This returns the Kind corresponding to applications of the operator op + * when building the builtin version of sygus terms. This is used by the + * function mkSygusTerm. + */ +Kind getOperatorKindForSygusBuiltin(Node op); +/** + * Returns the total version of Kind k if it is a partial operator, or + * otherwise k itself. + */ +Kind getEliminateKind(Kind k); +/** + * Returns a version of n where all partial functions such as bvudiv + * have been replaced by their total versions like bvudiv_total. + */ +Node eliminatePartialOperators(Node n); +/** make sygus term + * + * This function returns a builtin term f( children[0], ..., children[n] ) + * where f is the builtin op that the i^th constructor of sygus datatype dt + * encodes. If doBetaReduction is true, then lambdas are eagerly eliminated + * via beta reduction. + * + * If isExternal is true, then the returned term respects the original grammar + * that was provided. This includes the use of defined functions. + */ +Node mkSygusTerm(const DType& dt, + unsigned i, + const std::vector<Node>& children, + bool doBetaReduction = true, + bool isExternal = false); +/** + * Same as above, but we already have the sygus operator op. The above method + * is syntax sugar for calling this method on dt[i].getSygusOp(). + */ +Node mkSygusTerm(Node op, + const std::vector<Node>& children, + bool doBetaReduction = true); +/** + * n is a builtin term that is an application of operator op. + * + * This returns an n' such that (eval n args) is n', where n' is a instance of + * n for the appropriate substitution. + * + * For example, given a function-to-synthesize with formal argument list (x,y), + * say we have grammar: + * A -> A+A | A+x | A+(x+y) | y + * These lead to constructors with sygus ops: + * C1 / (lambda w1 w2. w1+w2) + * C2 / (lambda w1. w1+x) + * C3 / (lambda w1. w1+(x+y)) + * C4 / y + * Examples of calling this function: + * applySygusArgs( dt, C1, (APPLY_UF (lambda w1 w2. w1+w2) t1 t2), { 3, 5 } ) + * ... returns (APPLY_UF (lambda w1 w2. w1+w2) t1 t2). + * applySygusArgs( dt, C2, (APPLY_UF (lambda w1. w1+x) t1), { 3, 5 } ) + * ... returns (APPLY_UF (lambda w1. w1+3) t1). + * applySygusArgs( dt, C3, (APPLY_UF (lambda w1. w1+(x+y)) t1), { 3, 5 } ) + * ... returns (APPLY_UF (lambda w1. w1+(3+5)) t1). + * applySygusArgs( dt, C4, y, { 3, 5 } ) + * ... returns 5. + * Notice the attribute SygusVarFreeAttribute is applied to C1, C2, C3, C4, + * to cache the results of whether the evaluation of this constructor needs + * a substitution over the formal argument list of the function-to-synthesize. + */ +Node applySygusArgs(const DType& dt, + Node op, + Node n, + const std::vector<Node>& args); +/** Sygus to builtin + * + * This method converts a constant term of SyGuS datatype type to its builtin + * equivalent. For example, given input C_*( C_x(), C_y() ), this method returns + * x*y, assuming C_+, C_x, and C_y have sygus operators *, x, and y + * respectively. + * + * If isExternal is true, then the returned term respects the original grammar + * that was provided. This includes the use of defined functions. This argument + * should typically be false, unless we are e.g. exporting the value of the + * term as a final solution. + */ +Node sygusToBuiltin(Node c, bool isExternal = false); +/** Sygus to builtin eval + * + * This method returns the rewritten form of (DT_SYGUS_EVAL n args). Notice that + * n does not necessarily need to be a constant. + * + * It does so by (1) converting constant subterms of n to builtin terms and + * evaluating them on the arguments args, (2) unfolding non-constant + * applications of sygus constructors in n with respect to args and (3) + * converting all other non-constant subterms of n to applications of + * DT_SYGUS_EVAL. + * + * For example, if + * n = C_+( C_*( C_x(), C_y() ), n' ), and args = { 3, 4 } + * where n' is a variable, then this method returns: + * 12 + (DT_SYGUS_EVAL n' 3 4) + * Notice that the subterm C_*( C_x(), C_y() ) is converted to its builtin + * equivalent x*y and evaluated under the substition { x -> 3, x -> 4 } giving + * 12. The subterm n' is non-constant and thus we return its evaluation under + * 3,4, giving the term (DT_SYGUS_EVAL n' 3 4). Since the top-level constructor + * is C_+, these terms are added together to give the result. + */ +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 +} // namespace datatypes +} // namespace theory +} // namespace CVC4 + +#endif diff --git a/src/theory/datatypes/sygus_extension.cpp b/src/theory/datatypes/sygus_extension.cpp index f22e0e6d5..fda08bb0e 100644 --- a/src/theory/datatypes/sygus_extension.cpp +++ b/src/theory/datatypes/sygus_extension.cpp @@ -2,9 +2,9 @@ /*! \file sygus_extension.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -21,6 +21,7 @@ #include "options/datatypes_options.h" #include "options/quantifiers_options.h" #include "printer/printer.h" +#include "theory/datatypes/sygus_datatype_utils.h" #include "theory/datatypes/theory_datatypes.h" #include "theory/datatypes/theory_datatypes_utils.h" #include "theory/quantifiers/sygus/sygus_explain.h" @@ -1672,7 +1673,6 @@ bool SygusExtension::checkValue(Node n, } TypeNode tn = n.getType(); const DType& dt = tn.getDType(); - Assert(dt.isSygus()); // ensure that the expected size bound is met int cindex = utils::indexOf(vn.getOperator()); diff --git a/src/theory/datatypes/sygus_extension.h b/src/theory/datatypes/sygus_extension.h index 5f6cfa00c..0c475a8e0 100644 --- a/src/theory/datatypes/sygus_extension.h +++ b/src/theory/datatypes/sygus_extension.h @@ -2,9 +2,9 @@ /*! \file sygus_extension.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/datatypes/sygus_simple_sym.cpp b/src/theory/datatypes/sygus_simple_sym.cpp index 06f1ea79c..d2fed715b 100644 --- a/src/theory/datatypes/sygus_simple_sym.cpp +++ b/src/theory/datatypes/sygus_simple_sym.cpp @@ -2,9 +2,9 @@ /*! \file sygus_simple_sym.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/datatypes/sygus_simple_sym.h b/src/theory/datatypes/sygus_simple_sym.h index 59eadce93..56fa39359 100644 --- a/src/theory/datatypes/sygus_simple_sym.h +++ b/src/theory/datatypes/sygus_simple_sym.h @@ -2,9 +2,9 @@ /*! \file sygus_simple_sym.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp index 9c8e9e2fa..30ee07d27 100644 --- a/src/theory/datatypes/theory_datatypes.cpp +++ b/src/theory/datatypes/theory_datatypes.cpp @@ -2,9 +2,9 @@ /*! \file theory_datatypes.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -561,11 +561,32 @@ void TheoryDatatypes::finishInit() { Node TheoryDatatypes::expandDefinition(Node n) { NodeManager* nm = NodeManager::currentNM(); + // must ensure the type is well founded and has no nested recursion if + // the option dtNestedRec is not set to true. + TypeNode tn = n.getType(); + if (tn.isDatatype()) + { + const DType& dt = tn.getDType(); + if (!dt.isWellFounded()) + { + std::stringstream ss; + ss << "Cannot handle non-well-founded datatype " << dt.getName(); + throw LogicException(ss.str()); + } + if (!options::dtNestedRec()) + { + if (dt.hasNestedRecursion()) + { + std::stringstream ss; + ss << "Cannot handle nested-recursive datatype " << dt.getName(); + throw LogicException(ss.str()); + } + } + } switch (n.getKind()) { case kind::APPLY_SELECTOR: { - Trace("dt-expand") << "Dt Expand definition : " << n << std::endl; Node selector = n.getOperator(); // APPLY_SELECTOR always applies to an external selector, cindexOf is // legal here @@ -621,30 +642,28 @@ Node TheoryDatatypes::expandDefinition(Node n) case TUPLE_UPDATE: case RECORD_UPDATE: { - TypeNode t = n.getType(); - Assert(t.isDatatype()); - const DType& dt = t.getDType(); + Assert(tn.isDatatype()); + const DType& dt = tn.getDType(); NodeBuilder<> b(APPLY_CONSTRUCTOR); b << dt[0].getConstructor(); size_t size, updateIndex; if (n.getKind() == TUPLE_UPDATE) { - Assert(t.isTuple()); - size = t.getTupleLength(); + Assert(tn.isTuple()); + size = tn.getTupleLength(); updateIndex = n.getOperator().getConst<TupleUpdate>().getIndex(); } else { - Assert(t.toType().isRecord()); - const Record& record = - DatatypeType(t.toType()).getRecord(); + Assert(tn.toType().isRecord()); + const Record& record = DatatypeType(tn.toType()).getRecord(); size = record.getNumFields(); updateIndex = record.getIndex( n.getOperator().getConst<RecordUpdate>().getField()); } Debug("tuprec") << "expr is " << n << std::endl; Debug("tuprec") << "updateIndex is " << updateIndex << std::endl; - Debug("tuprec") << "t is " << t << std::endl; + Debug("tuprec") << "t is " << tn << std::endl; Debug("tuprec") << "t has arity " << size << std::endl; for (size_t i = 0; i < size; ++i) { @@ -657,7 +676,7 @@ Node TheoryDatatypes::expandDefinition(Node n) else { b << nm->mkNode( - APPLY_SELECTOR_TOTAL, dt[0].getSelectorInternal(t, i), n[0]); + APPLY_SELECTOR_TOTAL, dt[0].getSelectorInternal(tn, i), n[0]); Debug("tuprec") << "arg " << i << " copies " << b[b.getNumChildren() - 1] << std::endl; } diff --git a/src/theory/datatypes/theory_datatypes.h b/src/theory/datatypes/theory_datatypes.h index c6ffb8907..11c6b5f36 100644 --- a/src/theory/datatypes/theory_datatypes.h +++ b/src/theory/datatypes/theory_datatypes.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/datatypes/theory_datatypes_type_rules.h b/src/theory/datatypes/theory_datatypes_type_rules.h index 0779fdc58..e9df20c2e 100644 --- a/src/theory/datatypes/theory_datatypes_type_rules.h +++ b/src/theory/datatypes/theory_datatypes_type_rules.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/datatypes/theory_datatypes_utils.cpp b/src/theory/datatypes/theory_datatypes_utils.cpp index ee0fd814e..7020a0e04 100644 --- a/src/theory/datatypes/theory_datatypes_utils.cpp +++ b/src/theory/datatypes/theory_datatypes_utils.cpp @@ -2,9 +2,9 @@ /*! \file theory_datatypes_utils.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Paul Meng + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -17,12 +17,6 @@ #include "theory/datatypes/theory_datatypes_utils.h" #include "expr/dtype.h" -#include "expr/node_algorithm.h" -#include "expr/sygus_datatype.h" -#include "smt/smt_engine.h" -#include "smt/smt_engine_scope.h" -#include "theory/evaluator.h" -#include "theory/rewriter.h" using namespace CVC4; using namespace CVC4::kind; @@ -32,311 +26,6 @@ namespace theory { namespace datatypes { namespace utils { -Node applySygusArgs(const DType& dt, - Node op, - Node n, - const std::vector<Node>& args) -{ - if (n.getKind() == BOUND_VARIABLE) - { - Assert(n.hasAttribute(SygusVarNumAttribute())); - int vn = n.getAttribute(SygusVarNumAttribute()); - Assert(dt.getSygusVarList()[vn] == n); - return args[vn]; - } - // n is an application of operator op. - // We must compute the free variables in op to determine if there are - // any substitutions we need to make to n. - TNode val; - if (!op.hasAttribute(SygusVarFreeAttribute())) - { - std::unordered_set<Node, NodeHashFunction> fvs; - if (expr::getFreeVariables(op, fvs)) - { - if (fvs.size() == 1) - { - for (const Node& v : fvs) - { - val = v; - } - } - else - { - val = op; - } - } - Trace("dt-sygus-fv") << "Free var in " << op << " : " << val << std::endl; - op.setAttribute(SygusVarFreeAttribute(), val); - } - else - { - val = op.getAttribute(SygusVarFreeAttribute()); - } - if (val.isNull()) - { - return n; - } - if (val.getKind() == BOUND_VARIABLE) - { - // single substitution case - int vn = val.getAttribute(SygusVarNumAttribute()); - TNode sub = args[vn]; - return n.substitute(val, sub); - } - // do the full substitution - std::vector<Node> vars; - Node bvl = dt.getSygusVarList(); - for (unsigned i = 0, nvars = bvl.getNumChildren(); i < nvars; i++) - { - vars.push_back(bvl[i]); - } - return n.substitute(vars.begin(), vars.end(), args.begin(), args.end()); -} - -Kind getOperatorKindForSygusBuiltin(Node op) -{ - Assert(op.getKind() != BUILTIN); - if (op.getKind() == LAMBDA) - { - return APPLY_UF; - } - TypeNode tn = op.getType(); - if (tn.isConstructor()) - { - return APPLY_CONSTRUCTOR; - } - else if (tn.isSelector()) - { - return APPLY_SELECTOR; - } - else if (tn.isTester()) - { - return APPLY_TESTER; - } - else if (tn.isFunction()) - { - return APPLY_UF; - } - return UNDEFINED_KIND; -} - -struct SygusOpRewrittenAttributeId -{ -}; -typedef expr::Attribute<SygusOpRewrittenAttributeId, Node> - SygusOpRewrittenAttribute; - -Kind getEliminateKind(Kind ok) -{ - Kind nk = ok; - // We also must ensure that builtin operators which are eliminated - // during expand definitions are replaced by the proper operator. - if (ok == BITVECTOR_UDIV) - { - nk = BITVECTOR_UDIV_TOTAL; - } - else if (ok == BITVECTOR_UREM) - { - nk = BITVECTOR_UREM_TOTAL; - } - else if (ok == DIVISION) - { - nk = DIVISION_TOTAL; - } - else if (ok == INTS_DIVISION) - { - nk = INTS_DIVISION_TOTAL; - } - else if (ok == INTS_MODULUS) - { - nk = INTS_MODULUS_TOTAL; - } - return nk; -} - -Node eliminatePartialOperators(Node n) -{ - NodeManager* nm = NodeManager::currentNM(); - std::unordered_map<TNode, Node, TNodeHashFunction> visited; - std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it; - std::vector<TNode> visit; - TNode cur; - visit.push_back(n); - do - { - cur = visit.back(); - visit.pop_back(); - it = visited.find(cur); - - if (it == visited.end()) - { - visited[cur] = Node::null(); - visit.push_back(cur); - for (const Node& cn : cur) - { - visit.push_back(cn); - } - } - else if (it->second.isNull()) - { - Node ret = cur; - bool childChanged = false; - std::vector<Node> children; - if (cur.getMetaKind() == metakind::PARAMETERIZED) - { - children.push_back(cur.getOperator()); - } - for (const Node& cn : cur) - { - it = visited.find(cn); - Assert(it != visited.end()); - Assert(!it->second.isNull()); - childChanged = childChanged || cn != it->second; - children.push_back(it->second); - } - Kind ok = cur.getKind(); - Kind nk = getEliminateKind(ok); - if (nk != ok || childChanged) - { - ret = nm->mkNode(nk, children); - } - visited[cur] = ret; - } - } while (!visit.empty()); - Assert(visited.find(n) != visited.end()); - Assert(!visited.find(n)->second.isNull()); - return visited[n]; -} - -Node mkSygusTerm(const DType& dt, - unsigned i, - const std::vector<Node>& children, - bool doBetaReduction, - bool isExternal) -{ - Trace("dt-sygus-util") << "Make sygus term " << dt.getName() << "[" << i - << "] with children: " << children << std::endl; - Assert(i < dt.getNumConstructors()); - Assert(dt.isSygus()); - Assert(!dt[i].getSygusOp().isNull()); - Node op = dt[i].getSygusOp(); - Node opn = op; - if (!isExternal) - { - // Get the normalized version of the sygus operator. We do this by - // expanding definitions, rewriting it, and eliminating partial operators. - if (!op.hasAttribute(SygusOpRewrittenAttribute())) - { - if (op.isConst()) - { - // If it is a builtin operator, convert to total version if necessary. - // First, get the kind for the operator. - Kind ok = NodeManager::operatorToKind(op); - Trace("sygus-grammar-normalize-debug") - << "...builtin kind is " << ok << std::endl; - Kind nk = getEliminateKind(ok); - if (nk != ok) - { - Trace("sygus-grammar-normalize-debug") - << "...replace by builtin operator " << nk << std::endl; - opn = NodeManager::currentNM()->operatorOf(nk); - } - } - else - { - // Only expand definitions if the operator is not constant, since - // calling expandDefinitions on them should be a no-op. This check - // ensures we don't try to expand e.g. bitvector extract operators, - // whose type is undefined, and thus should not be passed to - // expandDefinitions. - opn = Node::fromExpr( - smt::currentSmtEngine()->expandDefinitions(op.toExpr())); - opn = Rewriter::rewrite(opn); - opn = eliminatePartialOperators(opn); - SygusOpRewrittenAttribute sora; - op.setAttribute(sora, opn); - } - } - else - { - opn = op.getAttribute(SygusOpRewrittenAttribute()); - } - } - return mkSygusTerm(opn, children, doBetaReduction); -} - -Node mkSygusTerm(Node op, - const std::vector<Node>& children, - bool doBetaReduction) -{ - Trace("dt-sygus-util") << "Operator is " << op << std::endl; - if (children.empty()) - { - // no children, return immediately - Trace("dt-sygus-util") << "...return direct op" << std::endl; - return op; - } - // if it is the any constant, we simply return the child - if (op.getAttribute(SygusAnyConstAttribute())) - { - Assert(children.size() == 1); - return children[0]; - } - std::vector<Node> schildren; - // get the kind of the operator - Kind ok = op.getKind(); - if (ok != BUILTIN) - { - if (ok == LAMBDA && doBetaReduction) - { - // Do immediate beta reduction. It suffices to use a normal substitution - // since neither op nor children have quantifiers, since they are - // generated by sygus grammars. - std::vector<Node> vars{op[0].begin(), op[0].end()}; - Assert(vars.size() == children.size()); - Node ret = op[1].substitute( - vars.begin(), vars.end(), children.begin(), children.end()); - Trace("dt-sygus-util") << "...return (beta-reduce) " << ret << std::endl; - return ret; - } - else - { - schildren.push_back(op); - } - } - schildren.insert(schildren.end(), children.begin(), children.end()); - Node ret; - if (ok == BUILTIN) - { - ret = NodeManager::currentNM()->mkNode(op, schildren); - Trace("dt-sygus-util") << "...return (builtin) " << ret << std::endl; - return ret; - } - // get the kind used for applying op - Kind otk = NodeManager::operatorToKind(op); - Trace("dt-sygus-util") << "operator kind is " << otk << std::endl; - if (otk != UNDEFINED_KIND) - { - // If it is an APPLY_UF operator, we should have at least an operator and - // a child. - Assert(otk != APPLY_UF || schildren.size() != 1); - ret = NodeManager::currentNM()->mkNode(otk, schildren); - Trace("dt-sygus-util") << "...return (op) " << ret << std::endl; - return ret; - } - Kind tok = getOperatorKindForSygusBuiltin(op); - if (schildren.size() == 1 && tok == UNDEFINED_KIND) - { - ret = schildren[0]; - } - else - { - ret = NodeManager::currentNM()->mkNode(tok, schildren); - } - Trace("dt-sygus-util") << "...return " << ret << std::endl; - return ret; -} - /** get instantiate cons */ Node getInstCons(Node n, const DType& dt, int index) { @@ -514,203 +203,6 @@ bool checkClash(Node n1, Node n2, std::vector<Node>& rew) return false; } -struct SygusToBuiltinTermAttributeId -{ -}; -typedef expr::Attribute<SygusToBuiltinTermAttributeId, Node> - SygusToBuiltinTermAttribute; - -Node sygusToBuiltin(Node n, bool isExternal) -{ - Assert(n.isConst()); - std::unordered_map<TNode, Node, TNodeHashFunction> visited; - std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it; - std::vector<TNode> visit; - TNode cur; - unsigned index; - visit.push_back(n); - do - { - cur = visit.back(); - visit.pop_back(); - it = visited.find(cur); - if (it == visited.end()) - { - if (cur.getKind() == APPLY_CONSTRUCTOR) - { - if (!isExternal && cur.hasAttribute(SygusToBuiltinTermAttribute())) - { - visited[cur] = cur.getAttribute(SygusToBuiltinTermAttribute()); - } - else - { - visited[cur] = Node::null(); - visit.push_back(cur); - for (const Node& cn : cur) - { - visit.push_back(cn); - } - } - } - else - { - // non-datatypes are themselves - visited[cur] = cur; - } - } - else if (it->second.isNull()) - { - Node ret = cur; - Assert(cur.getKind() == APPLY_CONSTRUCTOR); - const DType& dt = cur.getType().getDType(); - // Non sygus-datatype terms are also themselves. Notice we treat the - // case of non-sygus datatypes this way since it avoids computing - // the type / datatype of the node in the pre-traversal above. The - // case of non-sygus datatypes is very rare, so the extra addition to - // visited is justified performance-wise. - if (dt.isSygus()) - { - std::vector<Node> children; - for (const Node& cn : cur) - { - it = visited.find(cn); - Assert(it != visited.end()); - Assert(!it->second.isNull()); - children.push_back(it->second); - } - index = indexOf(cur.getOperator()); - ret = mkSygusTerm(dt, index, children, true, isExternal); - } - visited[cur] = ret; - // cache - if (!isExternal) - { - SygusToBuiltinTermAttribute stbt; - cur.setAttribute(stbt, ret); - } - } - } while (!visit.empty()); - Assert(visited.find(n) != visited.end()); - Assert(!visited.find(n)->second.isNull()); - return visited[n]; -} - -Node sygusToBuiltinEval(Node n, const std::vector<Node>& args) -{ - NodeManager* nm = NodeManager::currentNM(); - Evaluator eval; - // constant arguments? - bool constArgs = true; - for (const Node& a : args) - { - if (!a.isConst()) - { - constArgs = false; - break; - } - } - std::vector<Node> eargs; - bool svarsInit = false; - std::vector<Node> svars; - std::unordered_map<TNode, Node, TNodeHashFunction> visited; - std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it; - std::vector<TNode> visit; - TNode cur; - unsigned index; - visit.push_back(n); - do - { - cur = visit.back(); - visit.pop_back(); - it = visited.find(cur); - if (it == visited.end()) - { - TypeNode tn = cur.getType(); - if (!tn.isDatatype() || !tn.getDType().isSygus()) - { - visited[cur] = cur; - } - else if (cur.isConst()) - { - // convert to builtin term - Node bt = sygusToBuiltin(cur); - // run the evaluator if possible - if (!svarsInit) - { - svarsInit = true; - TypeNode type = cur.getType(); - Node varList = type.getDType().getSygusVarList(); - for (const Node& v : varList) - { - svars.push_back(v); - } - } - Assert(args.size() == svars.size()); - // try evaluation if we have constant arguments - Node ret = constArgs ? eval.eval(bt, svars, args) : Node::null(); - if (ret.isNull()) - { - // if evaluation was not available, use a substitution - ret = bt.substitute( - svars.begin(), svars.end(), args.begin(), args.end()); - } - visited[cur] = ret; - } - else - { - if (cur.getKind() == APPLY_CONSTRUCTOR) - { - visited[cur] = Node::null(); - visit.push_back(cur); - for (const Node& cn : cur) - { - visit.push_back(cn); - } - } - else - { - // it is the evaluation of this term on the arguments - if (eargs.empty()) - { - eargs.push_back(cur); - eargs.insert(eargs.end(), args.begin(), args.end()); - } - else - { - eargs[0] = cur; - } - visited[cur] = nm->mkNode(DT_SYGUS_EVAL, eargs); - } - } - } - else if (it->second.isNull()) - { - Node ret = cur; - Assert(cur.getKind() == APPLY_CONSTRUCTOR); - const DType& dt = cur.getType().getDType(); - // non sygus-datatype terms are also themselves - if (dt.isSygus()) - { - std::vector<Node> children; - for (const Node& cn : cur) - { - it = visited.find(cn); - Assert(it != visited.end()); - Assert(!it->second.isNull()); - children.push_back(it->second); - } - index = indexOf(cur.getOperator()); - // apply to arguments - ret = mkSygusTerm(dt, index, children); - } - visited[cur] = ret; - } - } while (!visit.empty()); - Assert(visited.find(n) != visited.end()); - Assert(!visited.find(n)->second.isNull()); - return visited[n]; -} - } // 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..1d106b9f1 100644 --- a/src/theory/datatypes/theory_datatypes_utils.h +++ b/src/theory/datatypes/theory_datatypes_utils.h @@ -2,9 +2,9 @@ /*! \file theory_datatypes_utils.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -27,49 +27,6 @@ namespace CVC4 { namespace theory { - -// ----------------------- sygus datatype attributes -/** sygus var num */ -struct SygusVarNumAttributeId -{ -}; -typedef expr::Attribute<SygusVarNumAttributeId, uint64_t> SygusVarNumAttribute; - -/** - * Attribute true for enumerators whose current model values were registered by - * the datatypes sygus solver, and were not excluded by sygus symmetry breaking. - * This is set by the datatypes sygus solver during LAST_CALL effort checks for - * each active sygus enumerator. - */ -struct SygusSymBreakOkAttributeId -{ -}; -typedef expr::Attribute<SygusSymBreakOkAttributeId, bool> - SygusSymBreakOkAttribute; - -/** sygus var free - * - * This attribute is used to mark whether sygus operators have free occurrences - * of variables from the formal argument list of the function-to-synthesize. - * - * We store three possible cases for sygus operators op: - * (1) op.getAttribute(SygusVarFreeAttribute())==Node::null() - * In this case, op has no free variables from the formal argument list of the - * function-to-synthesize. - * (2) op.getAttribute(SygusVarFreeAttribute())==v, where v is a bound variable. - * In this case, op has exactly one free variable, v. - * (3) op.getAttribute(SygusVarFreeAttribute())==op - * In this case, op has an arbitrary set (cardinality >1) of free variables from - * the formal argument list of the function to synthesize. - * - * This attribute is used to compute applySygusArgs below. - */ -struct SygusVarFreeAttributeId -{ -}; -typedef expr::Attribute<SygusVarFreeAttributeId, Node> SygusVarFreeAttribute; -// ----------------------- end sygus datatype attributes - namespace datatypes { namespace utils { @@ -137,116 +94,6 @@ bool isNullaryConstructor(const DTypeConstructor& c); */ bool checkClash(Node n1, Node n2, std::vector<Node>& rew); -// ------------------------ sygus utils - -/** get operator kind for sygus builtin - * - * This returns the Kind corresponding to applications of the operator op - * when building the builtin version of sygus terms. This is used by the - * function mkSygusTerm. - */ -Kind getOperatorKindForSygusBuiltin(Node op); -/** - * Returns the total version of Kind k if it is a partial operator, or - * otherwise k itself. - */ -Kind getEliminateKind(Kind k); -/** - * Returns a version of n where all partial functions such as bvudiv - * have been replaced by their total versions like bvudiv_total. - */ -Node eliminatePartialOperators(Node n); -/** make sygus term - * - * This function returns a builtin term f( children[0], ..., children[n] ) - * where f is the builtin op that the i^th constructor of sygus datatype dt - * encodes. If doBetaReduction is true, then lambdas are eagerly eliminated - * via beta reduction. - * - * If isExternal is true, then the returned term respects the original grammar - * that was provided. This includes the use of defined functions. - */ -Node mkSygusTerm(const DType& dt, - unsigned i, - const std::vector<Node>& children, - bool doBetaReduction = true, - bool isExternal = false); -/** - * Same as above, but we already have the sygus operator op. The above method - * is syntax sugar for calling this method on dt[i].getSygusOp(). - */ -Node mkSygusTerm(Node op, - const std::vector<Node>& children, - bool doBetaReduction = true); -/** - * n is a builtin term that is an application of operator op. - * - * This returns an n' such that (eval n args) is n', where n' is a instance of - * n for the appropriate substitution. - * - * For example, given a function-to-synthesize with formal argument list (x,y), - * say we have grammar: - * A -> A+A | A+x | A+(x+y) | y - * These lead to constructors with sygus ops: - * C1 / (lambda w1 w2. w1+w2) - * C2 / (lambda w1. w1+x) - * C3 / (lambda w1. w1+(x+y)) - * C4 / y - * Examples of calling this function: - * applySygusArgs( dt, C1, (APPLY_UF (lambda w1 w2. w1+w2) t1 t2), { 3, 5 } ) - * ... returns (APPLY_UF (lambda w1 w2. w1+w2) t1 t2). - * applySygusArgs( dt, C2, (APPLY_UF (lambda w1. w1+x) t1), { 3, 5 } ) - * ... returns (APPLY_UF (lambda w1. w1+3) t1). - * applySygusArgs( dt, C3, (APPLY_UF (lambda w1. w1+(x+y)) t1), { 3, 5 } ) - * ... returns (APPLY_UF (lambda w1. w1+(3+5)) t1). - * applySygusArgs( dt, C4, y, { 3, 5 } ) - * ... returns 5. - * Notice the attribute SygusVarFreeAttribute is applied to C1, C2, C3, C4, - * to cache the results of whether the evaluation of this constructor needs - * a substitution over the formal argument list of the function-to-synthesize. - */ -Node applySygusArgs(const DType& dt, - Node op, - Node n, - const std::vector<Node>& args); -/** Sygus to builtin - * - * This method converts a constant term of SyGuS datatype type to its builtin - * equivalent. For example, given input C_*( C_x(), C_y() ), this method returns - * x*y, assuming C_+, C_x, and C_y have sygus operators *, x, and y - * respectively. - * - * If isExternal is true, then the returned term respects the original grammar - * that was provided. This includes the use of defined functions. This argument - * should typically be false, unless we are e.g. exporting the value of the - * term as a final solution. - */ -Node sygusToBuiltin(Node c, bool isExternal = false); -/** Sygus to builtin eval - * - * This method returns the rewritten form of (DT_SYGUS_EVAL n args). Notice that - * n does not necessarily need to be a constant. - * - * It does so by (1) converting constant subterms of n to builtin terms and - * evaluating them on the arguments args, (2) unfolding non-constant - * applications of sygus constructors in n with respect to args and (3) - * converting all other non-constant subterms of n to applications of - * DT_SYGUS_EVAL. - * - * For example, if - * n = C_+( C_*( C_x(), C_y() ), n' ), and args = { 3, 4 } - * where n' is a variable, then this method returns: - * 12 + (DT_SYGUS_EVAL n' 3 4) - * Notice that the subterm C_*( C_x(), C_y() ) is converted to its builtin - * equivalent x*y and evaluated under the substition { x -> 3, x -> 4 } giving - * 12. The subterm n' is non-constant and thus we return its evaluation under - * 3,4, giving the term (DT_SYGUS_EVAL n' 3 4). Since the top-level constructor - * is C_+, these terms are added together to give the result. - */ -Node sygusToBuiltinEval(Node n, const std::vector<Node>& args); - -// ------------------------ end sygus utils - } // namespace utils } // namespace datatypes } // namespace theory diff --git a/src/theory/datatypes/type_enumerator.cpp b/src/theory/datatypes/type_enumerator.cpp index af686ded0..ccaba009d 100644 --- a/src/theory/datatypes/type_enumerator.cpp +++ b/src/theory/datatypes/type_enumerator.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/datatypes/type_enumerator.h b/src/theory/datatypes/type_enumerator.h index ece332bc9..1aa055bca 100644 --- a/src/theory/datatypes/type_enumerator.h +++ b/src/theory/datatypes/type_enumerator.h @@ -2,9 +2,9 @@ /*! \file type_enumerator.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/decision_manager.cpp b/src/theory/decision_manager.cpp index a2aee5d40..de5ad2fb1 100644 --- a/src/theory/decision_manager.cpp +++ b/src/theory/decision_manager.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/decision_manager.h b/src/theory/decision_manager.h index da040a7f7..fccac1190 100644 --- a/src/theory/decision_manager.h +++ b/src/theory/decision_manager.h @@ -2,9 +2,9 @@ /*! \file decision_manager.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/decision_strategy.cpp b/src/theory/decision_strategy.cpp index 504cafc16..5a98aab8c 100644 --- a/src/theory/decision_strategy.cpp +++ b/src/theory/decision_strategy.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/decision_strategy.h b/src/theory/decision_strategy.h index 65b80b7f6..d8227da18 100644 --- a/src/theory/decision_strategy.h +++ b/src/theory/decision_strategy.h @@ -2,9 +2,9 @@ /*! \file decision_strategy.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/eager_proof_generator.cpp b/src/theory/eager_proof_generator.cpp new file mode 100644 index 000000000..9c25fb3e4 --- /dev/null +++ b/src/theory/eager_proof_generator.cpp @@ -0,0 +1,125 @@ +/********************* */ +/*! \file eager_proof_generator.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 abstract proof generator class + **/ + +#include "theory/eager_proof_generator.h" + +#include "expr/proof_node_manager.h" + +namespace CVC4 { +namespace theory { + +EagerProofGenerator::EagerProofGenerator(ProofNodeManager* pnm, + context::Context* c) + : d_pnm(pnm), d_proofs(c == nullptr ? &d_context : c) +{ +} + +void EagerProofGenerator::setProofFor(Node f, std::shared_ptr<ProofNode> pf) +{ + // pf should prove f + Assert(pf->getResult() == f); + d_proofs[f] = pf; +} +void EagerProofGenerator::setProofForConflict(Node conf, + std::shared_ptr<ProofNode> pf) +{ + // Normalize based on key + Node ckey = TrustNode::getConflictProven(conf); + setProofFor(ckey, pf); +} + +void EagerProofGenerator::setProofForLemma(Node lem, + std::shared_ptr<ProofNode> pf) +{ + // Normalize based on key + Node lkey = TrustNode::getLemmaProven(lem); + setProofFor(lkey, pf); +} + +void EagerProofGenerator::setProofForPropExp(TNode lit, + Node exp, + std::shared_ptr<ProofNode> pf) +{ + // Normalize based on key + Node pekey = TrustNode::getPropExpProven(lit, exp); + setProofFor(pekey, pf); +} + +std::shared_ptr<ProofNode> EagerProofGenerator::getProofFor(Node f) +{ + NodeProofNodeMap::iterator it = d_proofs.find(f); + if (it == d_proofs.end()) + { + return nullptr; + } + return (*it).second; +} + +bool EagerProofGenerator::hasProofFor(Node f) +{ + return d_proofs.find(f) != d_proofs.end(); +} + +TrustNode EagerProofGenerator::mkTrustNode(Node n, + std::shared_ptr<ProofNode> pf, + bool isConflict) +{ + if (pf == nullptr) + { + return TrustNode::null(); + } + if (isConflict) + { + // this shouldnt modify the key + setProofForConflict(n, pf); + // we can now return the trust node + return TrustNode::mkTrustConflict(n, this); + } + // this shouldnt modify the key + setProofForLemma(n, pf); + // we can now return the trust node + return TrustNode::mkTrustLemma(n, this); +} + +TrustNode EagerProofGenerator::mkTrustNode(Node n, + PfRule id, + const std::vector<Node>& args, + bool isConflict) +{ + std::vector<std::shared_ptr<ProofNode>> children; + std::shared_ptr<ProofNode> pf = d_pnm->mkNode(id, children, args, n); + return mkTrustNode(n, pf, isConflict); +} + +TrustNode EagerProofGenerator::mkTrustedPropagation( + Node n, Node exp, std::shared_ptr<ProofNode> pf) +{ + if (pf == nullptr) + { + return TrustNode::null(); + } + setProofForPropExp(n, exp, pf); + return TrustNode::mkTrustPropExp(n, exp, this); +} + +TrustNode EagerProofGenerator::mkTrustNodeSplit(Node f) +{ + // make the lemma + Node lem = f.orNode(f.notNode()); + std::vector<Node> args; + return mkTrustNode(lem, PfRule::SPLIT, args, false); +} + +} // namespace theory +} // namespace CVC4 diff --git a/src/theory/eager_proof_generator.h b/src/theory/eager_proof_generator.h new file mode 100644 index 000000000..9a00f3612 --- /dev/null +++ b/src/theory/eager_proof_generator.h @@ -0,0 +1,178 @@ +/********************* */ +/*! \file eager_proof_generator.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 eager proof generator class + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__THEORY__EAGER_PROOF_GENERATOR_H +#define CVC4__THEORY__EAGER_PROOF_GENERATOR_H + +#include "context/cdhashmap.h" +#include "expr/node.h" +#include "expr/proof_generator.h" +#include "expr/proof_node.h" +#include "theory/trust_node.h" + +namespace CVC4 { +namespace theory { + +/** + * An eager proof generator, with explicit proof caching. + * + * The intended use of this class is to store proofs for lemmas and conflicts + * at the time they are sent out on the ProofOutputChannel. This means that the + * getProofForConflict and getProofForLemma methods are lookups in a + * (user-context depedent) map, the field d_proofs below. + * + * In detail, the method setProofForConflict(conf, pf) should be called prior to + * calling ProofOutputChannel(TrustNode(conf,X)), where X is this generator. + * Similarly for setProofForLemma. + * + * The intended usage of this class in combination with OutputChannel is + * the following: + * //----------------------------------------------------------- + * class MyEagerProofGenerator : public EagerProofGenerator + * { + * public: + * TrustNode getProvenConflictByMethodX(...) + * { + * // construct a conflict + * Node conf = [construct conflict]; + * // construct a proof for conf + * std::shared_ptr<ProofNode> pf = [construct the proof for conf]; + * // wrap the conflict in a trust node + * return mkTrustNode(conf,pf); + * } + * }; + * // [1] Make objects given user context u and output channel out. + * + * MyEagerProofGenerator epg(u); + * OutputChannel out; + * + * // [2] Assume epg realizes there is a conflict. We have it store the proof + * // internally and return the conflict node paired with epg. + * + * TrustNode pconf = epg.getProvenConflictByMethodX(...); + * + * // [3] Send the conflict on the output channel. + * + * out.trustedConflict(pconf); + * + * // [4] The trust node has information about what is proven and who can + * // prove it, where this association is valid in the remainder of the user + * // context. + * + * Node conf = pconf.getProven(); + * ProofGenerator * pg = pconf.getGenerator(); + * std::shared_ptr<ProofNode> pf = pg->getProofForConflict(conf); + * //----------------------------------------------------------- + * In other words, the proof generator epg is responsible for creating and + * storing the proof internally, and the proof output channel is responsible for + * maintaining the map that epg is who to ask for the proof of the conflict. + */ +class EagerProofGenerator : public ProofGenerator +{ + typedef context::CDHashMap<Node, std::shared_ptr<ProofNode>, NodeHashFunction> + NodeProofNodeMap; + + public: + EagerProofGenerator(ProofNodeManager* pnm, context::Context* c = nullptr); + ~EagerProofGenerator() {} + /** Get the proof for formula f. */ + std::shared_ptr<ProofNode> getProofFor(Node f) override; + /** Can we give the proof for formula f? */ + bool hasProofFor(Node f) override; + /** + * Set proof for fact f, called when pf is a proof of f. + * + * @param f The fact proven by pf, + * @param pf The proof to store in this class. + */ + void setProofFor(Node f, std::shared_ptr<ProofNode> pf); + /** + * Make trust node: wrap n in a trust node with this generator, and have it + * store the proof pf to lemma or conflict n. + * + * @param n The proven node, + * @param pf The proof of n, + * @param isConflict Whether the returned trust node is a conflict (otherwise + * it is a lemma), + * @return The trust node corresponding to the fact that this generator has + * a proof of n. + */ + TrustNode mkTrustNode(Node n, + std::shared_ptr<ProofNode> pf, + bool isConflict = false); + /** + * Make trust node from a single step proof (with no premises). This is a + * convenience function that avoids the need to explictly construct ProofNode + * by the caller. + * + * @param n The proven node, + * @param id The rule of the proof concluding n + * @param args The arguments to the proof concluding n, + * @param isConflict Whether the returned trust node is a conflict (otherwise + * it is a lemma), + * @return The trust node corresponding to the fact that this generator has + * a proof of n. + */ + TrustNode mkTrustNode(Node n, + PfRule id, + const std::vector<Node>& args, + bool isConflict = false); + /** + * Make trust node: wrap `exp => n` in a trust node with this generator, and + * have it store the proof `pf` too. + * + * @param n The implication + * @param exp A conjunction of literals that imply it + * @param pf The proof of exp => n, + * @return The trust node corresponding to the fact that this generator has + * a proof of exp => n. + */ + TrustNode mkTrustedPropagation(Node n, + Node exp, + std::shared_ptr<ProofNode> pf); + //--------------------------------------- common proofs + /** + * This returns the trust node corresponding to the splitting lemma + * (or f (not f)) and this generator. The method registers its proof in the + * map maintained by this class. + */ + TrustNode mkTrustNodeSplit(Node f); + //--------------------------------------- end common proofs + /** identify */ + std::string identify() const override { return "EagerProofGenerator"; } + + protected: + /** Set that pf is the proof for conflict conf */ + void setProofForConflict(Node conf, std::shared_ptr<ProofNode> pf); + /** Set that pf is the proof for lemma lem */ + void setProofForLemma(Node lem, std::shared_ptr<ProofNode> pf); + /** Set that pf is the proof for explained propagation */ + void setProofForPropExp(TNode lit, Node exp, std::shared_ptr<ProofNode> pf); + /** The proof node manager */ + ProofNodeManager* d_pnm; + /** A dummy context used by this class if none is provided */ + context::Context d_context; + /** + * A user-context-dependent map from lemmas and conflicts to proofs provided + * by calls to setProofForConflict and setProofForLemma above. + */ + NodeProofNodeMap d_proofs; +}; + +} // namespace theory +} // namespace CVC4 + +#endif /* CVC4__THEORY__PROOF_GENERATOR_H */ diff --git a/src/theory/engine_output_channel.cpp b/src/theory/engine_output_channel.cpp new file mode 100644 index 000000000..d83d2ba62 --- /dev/null +++ b/src/theory/engine_output_channel.cpp @@ -0,0 +1,341 @@ +/********************* */ +/*! \file engine_output_channel.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds, Guy Katz, Tim King + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 theory engine output channel. + **/ + +#include "theory/engine_output_channel.h" + +#include "proof/cnf_proof.h" +#include "proof/lemma_proof.h" +#include "proof/proof_manager.h" +#include "proof/theory_proof.h" +#include "prop/prop_engine.h" +#include "smt/smt_statistics_registry.h" +#include "theory/theory_engine.h" + +using namespace CVC4::kind; + +namespace CVC4 { +namespace theory { + +EngineOutputChannel::Statistics::Statistics(theory::TheoryId theory) + : conflicts(getStatsPrefix(theory) + "::conflicts", 0), + propagations(getStatsPrefix(theory) + "::propagations", 0), + lemmas(getStatsPrefix(theory) + "::lemmas", 0), + requirePhase(getStatsPrefix(theory) + "::requirePhase", 0), + restartDemands(getStatsPrefix(theory) + "::restartDemands", 0), + trustedConflicts(getStatsPrefix(theory) + "::trustedConflicts", 0), + trustedLemmas(getStatsPrefix(theory) + "::trustedLemmas", 0) +{ + smtStatisticsRegistry()->registerStat(&conflicts); + smtStatisticsRegistry()->registerStat(&propagations); + smtStatisticsRegistry()->registerStat(&lemmas); + smtStatisticsRegistry()->registerStat(&requirePhase); + smtStatisticsRegistry()->registerStat(&restartDemands); + smtStatisticsRegistry()->registerStat(&trustedConflicts); + smtStatisticsRegistry()->registerStat(&trustedLemmas); +} + +EngineOutputChannel::Statistics::~Statistics() +{ + smtStatisticsRegistry()->unregisterStat(&conflicts); + smtStatisticsRegistry()->unregisterStat(&propagations); + smtStatisticsRegistry()->unregisterStat(&lemmas); + smtStatisticsRegistry()->unregisterStat(&requirePhase); + smtStatisticsRegistry()->unregisterStat(&restartDemands); + smtStatisticsRegistry()->unregisterStat(&trustedConflicts); + smtStatisticsRegistry()->unregisterStat(&trustedLemmas); +} + +EngineOutputChannel::EngineOutputChannel(TheoryEngine* engine, + theory::TheoryId theory) + : d_engine(engine), d_statistics(theory), d_theory(theory) +{ +} + +void EngineOutputChannel::safePoint(ResourceManager::Resource r) +{ + spendResource(r); + if (d_engine->d_interrupted) + { + throw theory::Interrupted(); + } +} + +theory::LemmaStatus EngineOutputChannel::lemma(TNode lemma, + ProofRule rule, + bool removable, + bool preprocess, + bool sendAtoms) +{ + Debug("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" + << lemma << ")" + << ", preprocess = " << preprocess << std::endl; + ++d_statistics.lemmas; + d_engine->d_outputChannelUsed = true; + + PROOF({ registerLemmaRecipe(lemma, lemma, preprocess, d_theory); }); + + TrustNode tlem = TrustNode::mkTrustLemma(lemma); + theory::LemmaStatus result = + d_engine->lemma(tlem.getNode(), + rule, + false, + removable, + preprocess, + sendAtoms ? d_theory : theory::THEORY_LAST); + return result; +} + +void EngineOutputChannel::registerLemmaRecipe(Node lemma, + Node originalLemma, + bool preprocess, + theory::TheoryId theoryId) +{ + // During CNF conversion, conjunctions will be broken down into + // multiple lemmas. In order for the recipes to match, we have to do + // the same here. + NodeManager* nm = NodeManager::currentNM(); + + if (preprocess) lemma = d_engine->preprocess(lemma); + + bool negated = (lemma.getKind() == NOT); + Node nnLemma = negated ? lemma[0] : lemma; + + switch (nnLemma.getKind()) + { + case AND: + if (!negated) + { + for (unsigned i = 0; i < nnLemma.getNumChildren(); ++i) + registerLemmaRecipe(nnLemma[i], originalLemma, false, theoryId); + } + else + { + NodeBuilder<> builder(OR); + for (unsigned i = 0; i < nnLemma.getNumChildren(); ++i) + builder << nnLemma[i].negate(); + + Node disjunction = + (builder.getNumChildren() == 1) ? builder[0] : builder; + registerLemmaRecipe(disjunction, originalLemma, false, theoryId); + } + break; + + case EQUAL: + if (nnLemma[0].getType().isBoolean()) + { + if (!negated) + { + registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[1].negate()), + originalLemma, + false, + theoryId); + registerLemmaRecipe(nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1]), + originalLemma, + false, + theoryId); + } + else + { + registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[1]), + originalLemma, + false, + theoryId); + registerLemmaRecipe( + nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1].negate()), + originalLemma, + false, + theoryId); + } + } + break; + + case ITE: + if (!negated) + { + registerLemmaRecipe(nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1]), + originalLemma, + false, + theoryId); + registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[2]), + originalLemma, + false, + theoryId); + } + else + { + registerLemmaRecipe( + nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1].negate()), + originalLemma, + false, + theoryId); + registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[2].negate()), + originalLemma, + false, + theoryId); + } + break; + + default: break; + } + + // Theory lemmas have one step that proves the empty clause + LemmaProofRecipe proofRecipe; + Node emptyNode; + LemmaProofRecipe::ProofStep proofStep(theoryId, emptyNode); + + // Remember the original lemma, so we can report this later when asked to + proofRecipe.setOriginalLemma(originalLemma); + + // Record the assertions and rewrites + Node rewritten; + if (lemma.getKind() == OR) + { + for (unsigned i = 0; i < lemma.getNumChildren(); ++i) + { + rewritten = theory::Rewriter::rewrite(lemma[i]); + if (rewritten != lemma[i]) + { + proofRecipe.addRewriteRule(lemma[i].negate(), rewritten.negate()); + } + proofStep.addAssertion(lemma[i]); + proofRecipe.addBaseAssertion(rewritten); + } + } + else + { + rewritten = theory::Rewriter::rewrite(lemma); + if (rewritten != lemma) + { + proofRecipe.addRewriteRule(lemma.negate(), rewritten.negate()); + } + proofStep.addAssertion(lemma); + proofRecipe.addBaseAssertion(rewritten); + } + proofRecipe.addStep(proofStep); + ProofManager::getCnfProof()->setProofRecipe(&proofRecipe); +} + +theory::LemmaStatus EngineOutputChannel::splitLemma(TNode lemma, bool removable) +{ + Debug("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" + << lemma << ")" << std::endl; + ++d_statistics.lemmas; + d_engine->d_outputChannelUsed = true; + + Debug("pf::explain") << "EngineOutputChannel::splitLemma( " << lemma << " )" + << std::endl; + TrustNode tlem = TrustNode::mkTrustLemma(lemma); + theory::LemmaStatus result = d_engine->lemma( + tlem.getNode(), RULE_SPLIT, false, removable, false, d_theory); + return result; +} + +bool EngineOutputChannel::propagate(TNode literal) +{ + Debug("theory::propagate") << "EngineOutputChannel<" << d_theory + << ">::propagate(" << literal << ")" << std::endl; + ++d_statistics.propagations; + d_engine->d_outputChannelUsed = true; + return d_engine->propagate(literal, d_theory); +} + +void EngineOutputChannel::conflict(TNode conflictNode, + std::unique_ptr<Proof> proof) +{ + Trace("theory::conflict") + << "EngineOutputChannel<" << d_theory << ">::conflict(" << conflictNode + << ")" << std::endl; + Assert(!proof); // Theory shouldn't be producing proofs yet + ++d_statistics.conflicts; + d_engine->d_outputChannelUsed = true; + TrustNode tConf = TrustNode::mkTrustConflict(conflictNode); + d_engine->conflict(tConf.getNode(), d_theory); +} + +void EngineOutputChannel::demandRestart() +{ + NodeManager* curr = NodeManager::currentNM(); + Node restartVar = curr->mkSkolem( + "restartVar", + curr->booleanType(), + "A boolean variable asserted to be true to force a restart"); + Trace("theory::restart") << "EngineOutputChannel<" << d_theory + << ">::restart(" << restartVar << ")" << std::endl; + ++d_statistics.restartDemands; + lemma(restartVar, RULE_INVALID, true); +} + +void EngineOutputChannel::requirePhase(TNode n, bool phase) +{ + Debug("theory") << "EngineOutputChannel::requirePhase(" << n << ", " << phase + << ")" << std::endl; + ++d_statistics.requirePhase; + d_engine->getPropEngine()->requirePhase(n, phase); +} + +void EngineOutputChannel::setIncomplete() +{ + Trace("theory") << "setIncomplete()" << std::endl; + d_engine->setIncomplete(d_theory); +} + +void EngineOutputChannel::spendResource(ResourceManager::Resource r) +{ + d_engine->spendResource(r); +} + +void EngineOutputChannel::handleUserAttribute(const char* attr, + theory::Theory* t) +{ + d_engine->handleUserAttribute(attr, t); +} + +void EngineOutputChannel::trustedConflict(TrustNode pconf) +{ + Assert(pconf.getKind() == TrustNodeKind::CONFLICT); + Trace("theory::conflict") + << "EngineOutputChannel<" << d_theory << ">::conflict(" << pconf.getNode() + << ")" << std::endl; + if (pconf.getGenerator() != nullptr) + { + ++d_statistics.trustedConflicts; + } + ++d_statistics.conflicts; + d_engine->d_outputChannelUsed = true; + d_engine->conflict(pconf.getNode(), d_theory); +} + +LemmaStatus EngineOutputChannel::trustedLemma(TrustNode plem, + bool removable, + bool preprocess, + bool sendAtoms) +{ + Assert(plem.getKind() == TrustNodeKind::LEMMA); + if (plem.getGenerator() != nullptr) + { + ++d_statistics.trustedLemmas; + } + ++d_statistics.lemmas; + d_engine->d_outputChannelUsed = true; + // now, call the normal interface for lemma + return d_engine->lemma(plem.getNode(), + RULE_INVALID, + false, + removable, + preprocess, + sendAtoms ? d_theory : theory::THEORY_LAST); +} + +} // namespace theory +} // namespace CVC4 diff --git a/src/theory/engine_output_channel.h b/src/theory/engine_output_channel.h new file mode 100644 index 000000000..d7b26928d --- /dev/null +++ b/src/theory/engine_output_channel.h @@ -0,0 +1,118 @@ +/********************* */ +/*! \file engine_output_channel.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds, Tim King, Dejan Jovanovic + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 theory engine output channel. + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__THEORY__ENGINE_OUTPUT_CHANNEL_H +#define CVC4__THEORY__ENGINE_OUTPUT_CHANNEL_H + +#include "expr/node.h" +#include "theory/output_channel.h" +#include "theory/theory.h" +#include "util/statistics_registry.h" + +namespace CVC4 { + +class TheoryEngine; + +namespace theory { + +/** + * An output channel for Theory that passes messages back to a TheoryEngine + * for a given Theory. + * + * Notice that it has interfaces trustedConflict and trustedLemma which are + * used for ensuring that proof generators are associated with the lemmas + * and conflicts sent on this output channel. + */ +class EngineOutputChannel : public theory::OutputChannel +{ + friend class TheoryEngine; + + public: + EngineOutputChannel(TheoryEngine* engine, theory::TheoryId theory); + + void safePoint(ResourceManager::Resource r) override; + + void conflict(TNode conflictNode, + std::unique_ptr<Proof> pf = nullptr) override; + bool propagate(TNode literal) override; + + theory::LemmaStatus lemma(TNode lemma, + ProofRule rule, + bool removable = false, + bool preprocess = false, + bool sendAtoms = false) override; + + theory::LemmaStatus splitLemma(TNode lemma, bool removable = false) override; + + void demandRestart() override; + + void requirePhase(TNode n, bool phase) override; + + void setIncomplete() override; + + void spendResource(ResourceManager::Resource r) override; + + void handleUserAttribute(const char* attr, theory::Theory* t) override; + + /** + * Let pconf be the pair (Node conf, ProofGenerator * pfg). This method + * sends conf on the output channel of this class whose proof can be generated + * by the generator pfg. Apart from pfg, the interface for this method is + * the same as calling OutputChannel::lemma on conf. + */ + void trustedConflict(TrustNode pconf) override; + /** + * Let plem be the pair (Node lem, ProofGenerator * pfg). + * Send lem on the output channel of this class whose proof can be generated + * by the generator pfg. Apart from pfg, the interface for this method is + * the same as calling OutputChannel::lemma on lem. + */ + LemmaStatus trustedLemma(TrustNode plem, + bool removable = false, + bool preprocess = false, + bool sendAtoms = false) override; + + protected: + /** + * Statistics for a particular theory. + */ + class Statistics + { + public: + Statistics(theory::TheoryId theory); + ~Statistics(); + /** Number of calls to conflict, propagate, lemma, requirePhase, + * restartDemands */ + IntStat conflicts, propagations, lemmas, requirePhase, restartDemands, + trustedConflicts, trustedLemmas; + }; + /** The theory engine we're communicating with. */ + TheoryEngine* d_engine; + /** The statistics of the theory interractions. */ + Statistics d_statistics; + /** The theory owning this channel. */ + theory::TheoryId d_theory; + /** A helper function for registering lemma recipes with the proof engine */ + void registerLemmaRecipe(Node lemma, + Node originalLemma, + bool preprocess, + theory::TheoryId theoryId); +}; + +} // namespace theory +} // namespace CVC4 + +#endif /* CVC4__THEORY__ENGINE_OUTPUT_CHANNEL_H */ diff --git a/src/theory/evaluator.cpp b/src/theory/evaluator.cpp index 646f903f5..852dede78 100644 --- a/src/theory/evaluator.cpp +++ b/src/theory/evaluator.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andres Noetzli, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -117,16 +117,18 @@ Node EvalResult::toNode() const Node Evaluator::eval(TNode n, const std::vector<Node>& args, - const std::vector<Node>& vals) const + const std::vector<Node>& vals, + bool useRewriter) const { std::unordered_map<Node, Node, NodeHashFunction> visited; - return eval(n, args, vals, visited); + return eval(n, args, vals, visited, useRewriter); } Node Evaluator::eval( TNode n, const std::vector<Node>& args, const std::vector<Node>& vals, - const std::unordered_map<Node, Node, NodeHashFunction>& visited) const + const std::unordered_map<Node, Node, NodeHashFunction>& visited, + bool useRewriter) const { Trace("evaluator") << "Evaluating " << n << " under substitution " << args << " " << vals << " with visited size = " << visited.size() @@ -137,28 +139,38 @@ Node Evaluator::eval( for (const std::pair<const Node, Node>& p : visited) { Trace("evaluator") << "Add " << p.first << " == " << p.second << std::endl; - results[p.first] = evalInternal(p.second, args, vals, evalAsNode, results); + results[p.first] = evalInternal(p.second, args, vals, evalAsNode, results, useRewriter); if (results[p.first].d_tag == EvalResult::INVALID) { // could not evaluate, use the evalAsNode map - evalAsNode[p.first] = evalAsNode[p.second]; + std::unordered_map<TNode, Node, NodeHashFunction>::iterator itn = + evalAsNode.find(p.second); + Assert(itn != evalAsNode.end()); + Node val = itn->second; + if (useRewriter) + { + val = Rewriter::rewrite(val); + } + evalAsNode[p.first] = val; } } Trace("evaluator") << "Run eval internal..." << std::endl; - Node ret = evalInternal(n, args, vals, evalAsNode, results).toNode(); + Node ret = evalInternal(n, args, vals, evalAsNode, results, useRewriter).toNode(); // if we failed to evaluate - if (ret.isNull()) + if (ret.isNull() && useRewriter) { // should be stored in the evaluation-as-node map std::unordered_map<TNode, Node, NodeHashFunction>::iterator itn = evalAsNode.find(n); Assert(itn != evalAsNode.end()); - ret = itn->second; + ret = Rewriter::rewrite(itn->second); } - // should be the same as substitution + rewriting - Assert(ret - == Rewriter::rewrite( - n.substitute(args.begin(), args.end(), vals.begin(), vals.end()))); + // should be the same as substitution + rewriting, or possibly null if + // useRewriter is false + Assert((ret.isNull() && !useRewriter) + || ret + == Rewriter::rewrite(n.substitute( + args.begin(), args.end(), vals.begin(), vals.end()))); return ret; } @@ -167,7 +179,8 @@ EvalResult Evaluator::evalInternal( const std::vector<Node>& args, const std::vector<Node>& vals, std::unordered_map<TNode, Node, NodeHashFunction>& evalAsNode, - std::unordered_map<TNode, EvalResult, TNodeHashFunction>& results) const + std::unordered_map<TNode, EvalResult, TNodeHashFunction>& results, + bool useRewriter) const { std::vector<TNode> queue; queue.emplace_back(n); @@ -243,6 +256,12 @@ EvalResult Evaluator::evalInternal( // successfully evaluated, and the children that did not. Trace("evaluator") << "Evaluator: collect arguments" << std::endl; currNodeVal = reconstruct(currNodeVal, results, evalAsNode); + if (useRewriter) + { + // Rewrite the result now, if we use the rewriter. We will see below + // if we are able to turn it into a valid EvalResult. + currNodeVal = Rewriter::rewrite(currNodeVal); + } needsReconstruct = false; Trace("evaluator") << "Evaluator: now after substitution + rewriting: " << currNodeVal << std::endl; @@ -274,7 +293,6 @@ EvalResult Evaluator::evalInternal( currNodeVal = vals[pos]; // Don't need to reconstruct since range of substitution should already // be normalized. - Assert(vals[pos] == Rewriter::rewrite(vals[pos])); needsReconstruct = false; } else if (currNode.getKind() == kind::APPLY_UF) @@ -318,7 +336,7 @@ EvalResult Evaluator::evalInternal( std::unordered_map<TNode, Node, NodeHashFunction> evalAsNodeC; std::unordered_map<TNode, EvalResult, TNodeHashFunction> resultsC; results[currNode] = - evalInternal(op[1], lambdaArgs, lambdaVals, evalAsNodeC, resultsC); + evalInternal(op[1], lambdaArgs, lambdaVals, evalAsNodeC, resultsC, useRewriter); Trace("evaluator") << "Evaluated via arguments to " << results[currNode].d_tag << std::endl; if (results[currNode].d_tag == EvalResult::INVALID) @@ -894,9 +912,9 @@ Node Evaluator::reconstruct( // of the children. Node nn = nm->mkNode(n.getKind(), echildren); Trace("evaluator") << "Evaluator: reconstructed " << nn << std::endl; - // Use rewriting. Notice we do not need to substitute here since - // all substitutions should already have been applied recursively. - return Rewriter::rewrite(nn); + // Return node, without rewriting. Notice we do not need to substitute here + // since all substitutions should already have been applied recursively. + return nn; } } // namespace theory diff --git a/src/theory/evaluator.h b/src/theory/evaluator.h index b9b15c6c6..e986edf1f 100644 --- a/src/theory/evaluator.h +++ b/src/theory/evaluator.h @@ -2,9 +2,9 @@ /*! \file evaluator.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andres Noetzli, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -89,20 +89,31 @@ class Evaluator * for subterms that evaluate to constants supported in the EvalResult * class and substitution with rewriting for the others. * - * The nodes in the vals must be constant values, that is, they must return - * true for isConst(). + * The nodes in vals are typically intended to be constant, although this + * is not required. + * + * If the parameter useRewriter is true, then we may invoke calls to the + * rewriter for computing the result of this method. + * + * The result of this call is either equivalent to: + * (1) Rewriter::rewrite(n.substitute(args,vars)) + * (2) Node::null(). + * If useRewriter is true, then we are always in the first case. If + * useRewriter is false, then we may be in case (2) if computing the + * rewritten, substituted form of n could not be determined by evaluation. */ Node eval(TNode n, const std::vector<Node>& args, - const std::vector<Node>& vals) const; + const std::vector<Node>& vals, + bool useRewriter = true) const; /** * Same as above, but with a precomputed visited map. */ - Node eval( - TNode n, - const std::vector<Node>& args, - const std::vector<Node>& vals, - const std::unordered_map<Node, Node, NodeHashFunction>& visited) const; + Node eval(TNode n, + const std::vector<Node>& args, + const std::vector<Node>& vals, + const std::unordered_map<Node, Node, NodeHashFunction>& visited, + bool useRewriter = true) const; private: /** @@ -126,7 +137,8 @@ class Evaluator const std::vector<Node>& args, const std::vector<Node>& vals, std::unordered_map<TNode, Node, NodeHashFunction>& evalAsNode, - std::unordered_map<TNode, EvalResult, TNodeHashFunction>& results) const; + std::unordered_map<TNode, EvalResult, TNodeHashFunction>& results, + bool useRewriter) const; /** reconstruct * * This function reconstructs the result of evaluating n using a combination diff --git a/src/theory/example/ecdata.cpp b/src/theory/example/ecdata.cpp index 6a66f5491..bc19f657b 100644 --- a/src/theory/example/ecdata.cpp +++ b/src/theory/example/ecdata.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/example/ecdata.h b/src/theory/example/ecdata.h index c646725e8..7b8fcaef5 100644 --- a/src/theory/example/ecdata.h +++ b/src/theory/example/ecdata.h @@ -2,9 +2,9 @@ /*! \file ecdata.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/example/theory_uf_tim.cpp b/src/theory/example/theory_uf_tim.cpp index 68346d59d..07cad60e5 100644 --- a/src/theory/example/theory_uf_tim.cpp +++ b/src/theory/example/theory_uf_tim.cpp @@ -2,9 +2,9 @@ /*! \file theory_uf_tim.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/example/theory_uf_tim.h b/src/theory/example/theory_uf_tim.h index 20fd6bcfb..438fe33dc 100644 --- a/src/theory/example/theory_uf_tim.h +++ b/src/theory/example/theory_uf_tim.h @@ -2,9 +2,9 @@ /*! \file theory_uf_tim.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/ext_theory.cpp b/src/theory/ext_theory.cpp index 9d2a7ac4c..f84153c06 100644 --- a/src/theory/ext_theory.cpp +++ b/src/theory/ext_theory.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/ext_theory.h b/src/theory/ext_theory.h index 7ac79a4d6..420932bfe 100644 --- a/src/theory/ext_theory.h +++ b/src/theory/ext_theory.h @@ -2,9 +2,9 @@ /*! \file ext_theory.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King + ** Andrew Reynolds, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/fp/fp_converter.cpp b/src/theory/fp/fp_converter.cpp index 665635c38..49be75719 100644 --- a/src/theory/fp/fp_converter.cpp +++ b/src/theory/fp/fp_converter.cpp @@ -2,9 +2,9 @@ /*! \file fp_converter.cpp ** \verbatim ** Top contributors (to current version): - ** Martin Brain, Andres Noetzli, Aina Niemetz + ** Martin Brain, Mathias Preiner, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/fp/fp_converter.h b/src/theory/fp/fp_converter.h index 344dcf926..122e94ac0 100644 --- a/src/theory/fp/fp_converter.h +++ b/src/theory/fp/fp_converter.h @@ -2,9 +2,9 @@ /*! \file fp_converter.h ** \verbatim ** Top contributors (to current version): - ** Martin Brain + ** Martin Brain, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/fp/theory_fp.cpp b/src/theory/fp/theory_fp.cpp index 68f3ad35a..50c66919f 100644 --- a/src/theory/fp/theory_fp.cpp +++ b/src/theory/fp/theory_fp.cpp @@ -2,9 +2,9 @@ /*! \file theory_fp.cpp ** \verbatim ** Top contributors (to current version): - ** Martin Brain, Andres Noetzli, Andrew Reynolds + ** Martin Brain, Andres Noetzli, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/fp/theory_fp.h b/src/theory/fp/theory_fp.h index de629b000..52cd39863 100644 --- a/src/theory/fp/theory_fp.h +++ b/src/theory/fp/theory_fp.h @@ -2,9 +2,9 @@ /*! \file theory_fp.h ** \verbatim ** Top contributors (to current version): - ** Martin Brain, Tim King, Mathias Preiner + ** Martin Brain, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/fp/theory_fp_rewriter.cpp b/src/theory/fp/theory_fp_rewriter.cpp index 338c1c871..3d42591b0 100644 --- a/src/theory/fp/theory_fp_rewriter.cpp +++ b/src/theory/fp/theory_fp_rewriter.cpp @@ -2,10 +2,10 @@ /*! \file theory_fp_rewriter.cpp ** \verbatim ** Top contributors (to current version): - ** Martin Brain, Martin Brain, Andrew Reynolds + ** Martin Brain, Andres Noetzli, Andrew Reynolds ** Copyright (c) 2013 University of Oxford ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/fp/theory_fp_rewriter.h b/src/theory/fp/theory_fp_rewriter.h index 732eeab0a..f5d1c5234 100644 --- a/src/theory/fp/theory_fp_rewriter.h +++ b/src/theory/fp/theory_fp_rewriter.h @@ -2,9 +2,9 @@ /*! \file theory_fp_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Martin Brain + ** Andres Noetzli, Martin Brain, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/fp/theory_fp_type_rules.h b/src/theory/fp/theory_fp_type_rules.h index 4022cc278..e3bd5f048 100644 --- a/src/theory/fp/theory_fp_type_rules.h +++ b/src/theory/fp/theory_fp_type_rules.h @@ -2,9 +2,9 @@ /*! \file theory_fp_type_rules.h ** \verbatim ** Top contributors (to current version): - ** Martin Brain, Tim King, Martin Brain + ** Martin Brain, Tim King, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/fp/type_enumerator.h b/src/theory/fp/type_enumerator.h index bb109f823..9741a7ee0 100644 --- a/src/theory/fp/type_enumerator.h +++ b/src/theory/fp/type_enumerator.h @@ -5,7 +5,7 @@ ** Tim King, Martin Brain, Andrew Reynolds ** Copyright (c) 2009-2015 New York University and The University of Iowa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/interrupted.h b/src/theory/interrupted.h index 905a98689..d336e9314 100644 --- a/src/theory/interrupted.h +++ b/src/theory/interrupted.h @@ -2,9 +2,9 @@ /*! \file interrupted.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/logic_info.cpp b/src/theory/logic_info.cpp index 9fd28e8dc..9805f602e 100644 --- a/src/theory/logic_info.cpp +++ b/src/theory/logic_info.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/logic_info.h b/src/theory/logic_info.h index a19936c34..dd2bbe30c 100644 --- a/src/theory/logic_info.h +++ b/src/theory/logic_info.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/output_channel.h b/src/theory/output_channel.h index dc5dfc388..ff13d1b6b 100644 --- a/src/theory/output_channel.h +++ b/src/theory/output_channel.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -21,9 +21,11 @@ #include <memory> +#include "expr/proof_node.h" #include "proof/proof_manager.h" #include "smt/logic_exception.h" #include "theory/interrupted.h" +#include "theory/trust_node.h" #include "util/proof.h" #include "util/resource_manager.h" @@ -188,6 +190,33 @@ class OutputChannel { */ virtual void demandRestart() {} + //---------------------------- new proof + /** + * Let pconf be the pair (Node conf, ProofGenerator * pfg). This method + * sends conf on the output channel of this class whose proof can be generated + * by the generator pfg. Apart from pfg, the interface for this method is + * the same as OutputChannel. + */ + virtual void trustedConflict(TrustNode pconf) + { + Unreachable() << "OutputChannel::trustedConflict: no implementation" + << std::endl; + } + /** + * Let plem be the pair (Node lem, ProofGenerator * pfg). + * Send lem on the output channel of this class whose proof can be generated + * by the generator pfg. Apart from pfg, the interface for this method is + * the same as OutputChannel. + */ + virtual LemmaStatus trustedLemma(TrustNode lem, + bool removable = false, + bool preprocess = false, + bool sendAtoms = false) + { + Unreachable() << "OutputChannel::trustedLemma: no implementation" + << std::endl; + } + //---------------------------- end new proof }; /* class OutputChannel */ } // namespace theory diff --git a/src/theory/quantifiers/alpha_equivalence.cpp b/src/theory/quantifiers/alpha_equivalence.cpp index f9bf9335e..624c49698 100644 --- a/src/theory/quantifiers/alpha_equivalence.cpp +++ b/src/theory/quantifiers/alpha_equivalence.cpp @@ -2,9 +2,9 @@ /*! \file alpha_equivalence.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/alpha_equivalence.h b/src/theory/quantifiers/alpha_equivalence.h index 3f92350de..9e3645f4e 100644 --- a/src/theory/quantifiers/alpha_equivalence.h +++ b/src/theory/quantifiers/alpha_equivalence.h @@ -2,9 +2,9 @@ /*! \file alpha_equivalence.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Paul Meng + ** Andrew Reynolds, Mathias Preiner, Paul Meng ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/anti_skolem.cpp b/src/theory/quantifiers/anti_skolem.cpp index 5604d5760..f8c894c17 100644 --- a/src/theory/quantifiers/anti_skolem.cpp +++ b/src/theory/quantifiers/anti_skolem.cpp @@ -2,9 +2,9 @@ /*! \file anti_skolem.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Morgan Deters + ** Andrew Reynolds, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/anti_skolem.h b/src/theory/quantifiers/anti_skolem.h index 60b5571c5..e7577de22 100644 --- a/src/theory/quantifiers/anti_skolem.h +++ b/src/theory/quantifiers/anti_skolem.h @@ -2,9 +2,9 @@ /*! \file anti_skolem.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Mathias Preiner + ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/bv_inverter.cpp b/src/theory/quantifiers/bv_inverter.cpp index 5417ce455..6f2eea0be 100644 --- a/src/theory/quantifiers/bv_inverter.cpp +++ b/src/theory/quantifiers/bv_inverter.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Aina Niemetz, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/bv_inverter.h b/src/theory/quantifiers/bv_inverter.h index 2afb505a8..dbd04aad1 100644 --- a/src/theory/quantifiers/bv_inverter.h +++ b/src/theory/quantifiers/bv_inverter.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/bv_inverter_utils.cpp b/src/theory/quantifiers/bv_inverter_utils.cpp index e01af3f38..131e894c2 100644 --- a/src/theory/quantifiers/bv_inverter_utils.cpp +++ b/src/theory/quantifiers/bv_inverter_utils.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/bv_inverter_utils.h b/src/theory/quantifiers/bv_inverter_utils.h index 264b42ef5..11cfadcca 100644 --- a/src/theory/quantifiers/bv_inverter_utils.h +++ b/src/theory/quantifiers/bv_inverter_utils.h @@ -2,9 +2,9 @@ /*! \file bv_inverter_utils.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz + ** Aina Niemetz, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/candidate_rewrite_database.cpp b/src/theory/quantifiers/candidate_rewrite_database.cpp index 9070ed51d..fc3474df4 100644 --- a/src/theory/quantifiers/candidate_rewrite_database.cpp +++ b/src/theory/quantifiers/candidate_rewrite_database.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -14,6 +14,7 @@ #include "theory/quantifiers/candidate_rewrite_database.h" +#include "api/cvc4cpp.h" #include "options/base_options.h" #include "options/quantifiers_options.h" #include "printer/printer.h" @@ -137,8 +138,15 @@ bool CandidateRewriteDatabase::addTerm(Node sol, // options as the SmtEngine we belong to, where we ensure that // produce-models is set. bool needExport = false; - ExprManager em(nm->getOptions()); - std::unique_ptr<SmtEngine> rrChecker; + + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // This is only temporarily until we have separate options for each + // SmtEngine instance. We should reuse the same ExprManager with + // a different SmtEngine (and different options) here, eventually. + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + api::Solver slv(&nm->getOptions()); + ExprManager* em = slv.getExprManager(); + SmtEngine* rrChecker = slv.getSmtEngine(); ExprManagerMapCollection varMap; initializeChecker(rrChecker, em, varMap, crr, needExport); Result r = rrChecker->checkSat(); @@ -175,7 +183,7 @@ bool CandidateRewriteDatabase::addTerm(Node sol, Assert(!refv.isNull() && refv.getKind() != BOUND_VARIABLE); if (needExport) { - Expr erefv = refv.toExpr().exportTo(&em, varMap); + Expr erefv = refv.toExpr().exportTo(em, varMap); val = Node::fromExpr(rrChecker->getValue(erefv).exportTo( nm->toExprManager(), varMap)); } diff --git a/src/theory/quantifiers/candidate_rewrite_database.h b/src/theory/quantifiers/candidate_rewrite_database.h index a9ca659e1..9173a654b 100644 --- a/src/theory/quantifiers/candidate_rewrite_database.h +++ b/src/theory/quantifiers/candidate_rewrite_database.h @@ -2,9 +2,9 @@ /*! \file candidate_rewrite_database.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/candidate_rewrite_filter.cpp b/src/theory/quantifiers/candidate_rewrite_filter.cpp index 43edb89bf..c89fc6424 100644 --- a/src/theory/quantifiers/candidate_rewrite_filter.cpp +++ b/src/theory/quantifiers/candidate_rewrite_filter.cpp @@ -2,9 +2,9 @@ /*! \file candidate_rewrite_filter.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/candidate_rewrite_filter.h b/src/theory/quantifiers/candidate_rewrite_filter.h index 8f5fa029f..e65de51a1 100644 --- a/src/theory/quantifiers/candidate_rewrite_filter.h +++ b/src/theory/quantifiers/candidate_rewrite_filter.h @@ -2,9 +2,9 @@ /*! \file candidate_rewrite_filter.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/ceg_arith_instantiator.cpp b/src/theory/quantifiers/cegqi/ceg_arith_instantiator.cpp index bb59aa766..d6ee23bd1 100644 --- a/src/theory/quantifiers/cegqi/ceg_arith_instantiator.cpp +++ b/src/theory/quantifiers/cegqi/ceg_arith_instantiator.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/ceg_arith_instantiator.h b/src/theory/quantifiers/cegqi/ceg_arith_instantiator.h index 94e674687..c7a4f2606 100644 --- a/src/theory/quantifiers/cegqi/ceg_arith_instantiator.h +++ b/src/theory/quantifiers/cegqi/ceg_arith_instantiator.h @@ -2,9 +2,9 @@ /*! \file ceg_arith_instantiator.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Mathias Preiner + ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/ceg_bv_instantiator.cpp b/src/theory/quantifiers/cegqi/ceg_bv_instantiator.cpp index f94fee66b..cb3bcbf9c 100644 --- a/src/theory/quantifiers/cegqi/ceg_bv_instantiator.cpp +++ b/src/theory/quantifiers/cegqi/ceg_bv_instantiator.cpp @@ -2,9 +2,9 @@ /*! \file ceg_bv_instantiator.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Mathias Preiner, Aina Niemetz + ** Andrew Reynolds, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..ea75f4d0b 100644 --- a/src/theory/quantifiers/cegqi/ceg_bv_instantiator.h +++ b/src/theory/quantifiers/cegqi/ceg_bv_instantiator.h @@ -2,9 +2,9 @@ /*! \file ceg_bv_instantiator.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King + ** Andrew Reynolds, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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_bv_instantiator_utils.cpp b/src/theory/quantifiers/cegqi/ceg_bv_instantiator_utils.cpp index c1ad63fc8..3a449cbce 100644 --- a/src/theory/quantifiers/cegqi/ceg_bv_instantiator_utils.cpp +++ b/src/theory/quantifiers/cegqi/ceg_bv_instantiator_utils.cpp @@ -2,9 +2,9 @@ /*! \file ceg_bv_instantiator_utils.cpp ** \verbatim ** Top contributors (to current version): - ** Mathias Preiner, Aina Niemetz, Andrew Reynolds + ** Mathias Preiner, Aina Niemetz, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/ceg_bv_instantiator_utils.h b/src/theory/quantifiers/cegqi/ceg_bv_instantiator_utils.h index 8427f3df8..2dd1e662c 100644 --- a/src/theory/quantifiers/cegqi/ceg_bv_instantiator_utils.h +++ b/src/theory/quantifiers/cegqi/ceg_bv_instantiator_utils.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Mathias Preiner, Aina Niemetz, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/ceg_dt_instantiator.cpp b/src/theory/quantifiers/cegqi/ceg_dt_instantiator.cpp index 9fd682aaf..202d3f9a1 100644 --- a/src/theory/quantifiers/cegqi/ceg_dt_instantiator.cpp +++ b/src/theory/quantifiers/cegqi/ceg_dt_instantiator.cpp @@ -2,9 +2,9 @@ /*! \file ceg_dt_instantiator.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Andres Noetzli + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/ceg_dt_instantiator.h b/src/theory/quantifiers/cegqi/ceg_dt_instantiator.h index ef43d50a5..2fcea291f 100644 --- a/src/theory/quantifiers/cegqi/ceg_dt_instantiator.h +++ b/src/theory/quantifiers/cegqi/ceg_dt_instantiator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/ceg_epr_instantiator.cpp b/src/theory/quantifiers/cegqi/ceg_epr_instantiator.cpp index 15d426345..9fcb11c4e 100644 --- a/src/theory/quantifiers/cegqi/ceg_epr_instantiator.cpp +++ b/src/theory/quantifiers/cegqi/ceg_epr_instantiator.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/ceg_epr_instantiator.h b/src/theory/quantifiers/cegqi/ceg_epr_instantiator.h index b32fa5d4c..51463b7c4 100644 --- a/src/theory/quantifiers/cegqi/ceg_epr_instantiator.h +++ b/src/theory/quantifiers/cegqi/ceg_epr_instantiator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/ceg_instantiator.cpp b/src/theory/quantifiers/cegqi/ceg_instantiator.cpp index 186024219..7f0e93997 100644 --- a/src/theory/quantifiers/cegqi/ceg_instantiator.cpp +++ b/src/theory/quantifiers/cegqi/ceg_instantiator.cpp @@ -2,9 +2,9 @@ /*! \file ceg_instantiator.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Andres Noetzli + ** Andrew Reynolds, Piotr Trojanek, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..28266bbfa 100644 --- a/src/theory/quantifiers/cegqi/ceg_instantiator.h +++ b/src/theory/quantifiers/cegqi/ceg_instantiator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..c156cbdf8 100644 --- a/src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp +++ b/src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp @@ -2,9 +2,9 @@ /*! \file inst_strategy_cegqi.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Andres Noetzli + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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/cegqi/inst_strategy_cegqi.h b/src/theory/quantifiers/cegqi/inst_strategy_cegqi.h index 7abdf7d6d..dac5a198c 100644 --- a/src/theory/quantifiers/cegqi/inst_strategy_cegqi.h +++ b/src/theory/quantifiers/cegqi/inst_strategy_cegqi.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/vts_term_cache.cpp b/src/theory/quantifiers/cegqi/vts_term_cache.cpp index 91f65c4ef..858e471d4 100644 --- a/src/theory/quantifiers/cegqi/vts_term_cache.cpp +++ b/src/theory/quantifiers/cegqi/vts_term_cache.cpp @@ -2,9 +2,9 @@ /*! \file vts_term_cache.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/cegqi/vts_term_cache.h b/src/theory/quantifiers/cegqi/vts_term_cache.h index 1c3ec0801..8ed34e30b 100644 --- a/src/theory/quantifiers/cegqi/vts_term_cache.h +++ b/src/theory/quantifiers/cegqi/vts_term_cache.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/conjecture_generator.cpp b/src/theory/quantifiers/conjecture_generator.cpp index b25170341..21a3bd44b 100644 --- a/src/theory/quantifiers/conjecture_generator.cpp +++ b/src/theory/quantifiers/conjecture_generator.cpp @@ -2,9 +2,9 @@ /*! \file conjecture_generator.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Aina Niemetz, Morgan Deters + ** Andrew Reynolds, Mathias Preiner, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/conjecture_generator.h b/src/theory/quantifiers/conjecture_generator.h index 503961ea3..d7c314a9a 100644 --- a/src/theory/quantifiers/conjecture_generator.h +++ b/src/theory/quantifiers/conjecture_generator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/dynamic_rewrite.cpp b/src/theory/quantifiers/dynamic_rewrite.cpp index cd73ffe33..eedaec4e3 100644 --- a/src/theory/quantifiers/dynamic_rewrite.cpp +++ b/src/theory/quantifiers/dynamic_rewrite.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/dynamic_rewrite.h b/src/theory/quantifiers/dynamic_rewrite.h index 969b6bf93..6d2267adf 100644 --- a/src/theory/quantifiers/dynamic_rewrite.h +++ b/src/theory/quantifiers/dynamic_rewrite.h @@ -2,9 +2,9 @@ /*! \file dynamic_rewrite.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/candidate_generator.cpp b/src/theory/quantifiers/ematching/candidate_generator.cpp index 784453838..49d700a6a 100644 --- a/src/theory/quantifiers/ematching/candidate_generator.cpp +++ b/src/theory/quantifiers/ematching/candidate_generator.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Francois Bobot ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/candidate_generator.h b/src/theory/quantifiers/ematching/candidate_generator.h index 51c5ffa0b..c8d2b7015 100644 --- a/src/theory/quantifiers/ematching/candidate_generator.h +++ b/src/theory/quantifiers/ematching/candidate_generator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/ho_trigger.cpp b/src/theory/quantifiers/ematching/ho_trigger.cpp index 953121167..b68f9b1aa 100644 --- a/src/theory/quantifiers/ematching/ho_trigger.cpp +++ b/src/theory/quantifiers/ematching/ho_trigger.cpp @@ -2,9 +2,9 @@ /*! \file ho_trigger.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/ho_trigger.h b/src/theory/quantifiers/ematching/ho_trigger.h index 6f0ff0635..713e249a4 100644 --- a/src/theory/quantifiers/ematching/ho_trigger.h +++ b/src/theory/quantifiers/ematching/ho_trigger.h @@ -2,9 +2,9 @@ /*! \file ho_trigger.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Mathias Preiner + ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/inst_match_generator.cpp b/src/theory/quantifiers/ematching/inst_match_generator.cpp index a95944bed..176f275f0 100644 --- a/src/theory/quantifiers/ematching/inst_match_generator.cpp +++ b/src/theory/quantifiers/ematching/inst_match_generator.cpp @@ -2,9 +2,9 @@ /*! \file inst_match_generator.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/inst_match_generator.h b/src/theory/quantifiers/ematching/inst_match_generator.h index b71ff3c21..94c768d5f 100644 --- a/src/theory/quantifiers/ematching/inst_match_generator.h +++ b/src/theory/quantifiers/ematching/inst_match_generator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/inst_strategy_e_matching.cpp b/src/theory/quantifiers/ematching/inst_strategy_e_matching.cpp index 46216a17d..dcec05f5a 100644 --- a/src/theory/quantifiers/ematching/inst_strategy_e_matching.cpp +++ b/src/theory/quantifiers/ematching/inst_strategy_e_matching.cpp @@ -2,9 +2,9 @@ /*! \file inst_strategy_e_matching.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Aina Niemetz + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/inst_strategy_e_matching.h b/src/theory/quantifiers/ematching/inst_strategy_e_matching.h index 052bc910c..8f560256f 100644 --- a/src/theory/quantifiers/ematching/inst_strategy_e_matching.h +++ b/src/theory/quantifiers/ematching/inst_strategy_e_matching.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/instantiation_engine.cpp b/src/theory/quantifiers/ematching/instantiation_engine.cpp index b91a9ba63..5626c8aab 100644 --- a/src/theory/quantifiers/ematching/instantiation_engine.cpp +++ b/src/theory/quantifiers/ematching/instantiation_engine.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/instantiation_engine.h b/src/theory/quantifiers/ematching/instantiation_engine.h index 26fc3767b..d783374be 100644 --- a/src/theory/quantifiers/ematching/instantiation_engine.h +++ b/src/theory/quantifiers/ematching/instantiation_engine.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/trigger.cpp b/src/theory/quantifiers/ematching/trigger.cpp index b2284d78e..f177ebf40 100644 --- a/src/theory/quantifiers/ematching/trigger.cpp +++ b/src/theory/quantifiers/ematching/trigger.cpp @@ -2,9 +2,9 @@ /*! \file trigger.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/ematching/trigger.h b/src/theory/quantifiers/ematching/trigger.h index e955543db..fc2ad9416 100644 --- a/src/theory/quantifiers/ematching/trigger.h +++ b/src/theory/quantifiers/ematching/trigger.h @@ -2,9 +2,9 @@ /*! \file trigger.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/equality_infer.cpp b/src/theory/quantifiers/equality_infer.cpp index 66745c94a..7a4d444f7 100644 --- a/src/theory/quantifiers/equality_infer.cpp +++ b/src/theory/quantifiers/equality_infer.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/equality_infer.h b/src/theory/quantifiers/equality_infer.h index 69cd12a70..dfc0ef285 100644 --- a/src/theory/quantifiers/equality_infer.h +++ b/src/theory/quantifiers/equality_infer.h @@ -2,9 +2,9 @@ /*! \file equality_infer.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Andres Noetzli + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/equality_query.cpp b/src/theory/quantifiers/equality_query.cpp index f806234ef..94e60513c 100644 --- a/src/theory/quantifiers/equality_query.cpp +++ b/src/theory/quantifiers/equality_query.cpp @@ -2,9 +2,9 @@ /*! \file equality_query.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/equality_query.h b/src/theory/quantifiers/equality_query.h index 7766a335a..b06e42143 100644 --- a/src/theory/quantifiers/equality_query.h +++ b/src/theory/quantifiers/equality_query.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/expr_miner.cpp b/src/theory/quantifiers/expr_miner.cpp index 8645be1a1..b209fc6ff 100644 --- a/src/theory/quantifiers/expr_miner.cpp +++ b/src/theory/quantifiers/expr_miner.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -14,6 +14,7 @@ #include "theory/quantifiers/expr_miner.h" +#include "api/cvc4cpp.h" #include "options/quantifiers_options.h" #include "smt/smt_engine.h" #include "smt/smt_engine_scope.h" @@ -68,8 +69,8 @@ Node ExprMiner::convertToSkolem(Node n) return n.substitute(sfvs.begin(), sfvs.end(), sks.begin(), sks.end()); } -void ExprMiner::initializeChecker(std::unique_ptr<SmtEngine>& checker, - ExprManager& em, +void ExprMiner::initializeChecker(SmtEngine* checker, + ExprManager* em, ExprManagerMapCollection& varMap, Node query, bool& needExport) @@ -110,10 +111,16 @@ Result ExprMiner::doCheck(Node query) return Result(Result::SAT); } } + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // This is only temporarily until we have separate options for each + // SmtEngine instance. We should reuse the same ExprManager with + // a different SmtEngine (and different options) here, eventually. + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NodeManager* nm = NodeManager::currentNM(); bool needExport = false; - ExprManager em(nm->getOptions()); - std::unique_ptr<SmtEngine> smte; + api::Solver slv(&nm->getOptions()); + ExprManager* em = slv.getExprManager(); + SmtEngine* smte = slv.getSmtEngine(); ExprManagerMapCollection varMap; initializeChecker(smte, em, varMap, queryr, needExport); return smte->checkSat(); diff --git a/src/theory/quantifiers/expr_miner.h b/src/theory/quantifiers/expr_miner.h index 08d7f40b1..eebcebf88 100644 --- a/src/theory/quantifiers/expr_miner.h +++ b/src/theory/quantifiers/expr_miner.h @@ -2,9 +2,9 @@ /*! \file expr_miner.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -89,8 +89,8 @@ class ExprMiner * (for instance, model values) must be exported to the current expression * manager. */ - void initializeChecker(std::unique_ptr<SmtEngine>& smte, - ExprManager& em, + void initializeChecker(SmtEngine* smte, + ExprManager* em, ExprManagerMapCollection& varMap, Node query, bool& needExport); diff --git a/src/theory/quantifiers/expr_miner_manager.cpp b/src/theory/quantifiers/expr_miner_manager.cpp index 3db0e14ab..f99b06567 100644 --- a/src/theory/quantifiers/expr_miner_manager.cpp +++ b/src/theory/quantifiers/expr_miner_manager.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/expr_miner_manager.h b/src/theory/quantifiers/expr_miner_manager.h index b9c772f00..82c0959c6 100644 --- a/src/theory/quantifiers/expr_miner_manager.h +++ b/src/theory/quantifiers/expr_miner_manager.h @@ -2,9 +2,9 @@ /*! \file expr_miner_manager.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/extended_rewrite.cpp b/src/theory/quantifiers/extended_rewrite.cpp index 1f42c384f..c1a0b8ee9 100644 --- a/src/theory/quantifiers/extended_rewrite.cpp +++ b/src/theory/quantifiers/extended_rewrite.cpp @@ -2,9 +2,9 @@ /*! \file extended_rewrite.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli + ** Andrew Reynolds, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -488,6 +488,9 @@ Node ExtendedRewriter::extendedRewriteIte(Kind itek, Node n, bool full) { // reverse substitution to opposite child // r{ x -> t } = s implies ite( x=t ^ C, s, r ) ---> r + // We can use ordinary substitute since the result of the substitution + // is not being returned. In other words, nn is only being used to query + // whether the second branch is a generalization of the first. Node nn = t2.substitute(vars.begin(), vars.end(), subs.begin(), subs.end()); if (nn != t2) @@ -501,7 +504,9 @@ Node ExtendedRewriter::extendedRewriteIte(Kind itek, Node n, bool full) } // ite( x=t ^ C, s, r ) ---> ite( x=t ^ C, s{ x -> t }, r ) - nn = t1.substitute(vars.begin(), vars.end(), subs.begin(), subs.end()); + // must use partial substitute here, to avoid substitution into witness + std::map<Kind, bool> rkinds; + nn = partialSubstitute(t1, vars, subs, rkinds); if (nn != t1) { // If full=false, then we've duplicated a term u in the children of n. @@ -524,9 +529,11 @@ Node ExtendedRewriter::extendedRewriteIte(Kind itek, Node n, bool full) if (new_ret.isNull()) { // ite( C, t, s ) ----> ite( C, t, s { C -> false } ) - TNode tv = n[0]; - TNode ts = d_false; - Node nn = t2.substitute(tv, ts); + // use partial substitute to avoid substitution into witness + std::map<Node, Node> assign; + assign[n[0]] = d_false; + std::map<Kind, bool> rkinds; + Node nn = partialSubstitute(t2, assign, rkinds); if (nn != t2) { nn = Rewriter::rewrite(nn); @@ -561,7 +568,8 @@ Node ExtendedRewriter::extendedRewriteAndOr(Node n) return Node::null(); } Node new_ret; - // all kinds are legal to substitute over : hence we give the empty map + // we allow substitutions to recurse over any kind, except WITNESS which is + // managed by partialSubstitute. std::map<Kind, bool> bcp_kinds; new_ret = extendedRewriteBcp(AND, OR, NOT, bcp_kinds, n); if (!new_ret.isNull()) @@ -586,6 +594,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; @@ -853,20 +866,10 @@ Node ExtendedRewriter::extendedRewriteBcp( std::vector<Node> ccs_children; for (const Node& cc : ca) { - Node ccs = cc; - if (bcp_kinds.empty()) - { - Trace("ext-rew-bcp-debug") << "...do ordinary substitute" - << std::endl; - ccs = cc.substitute( - avars.begin(), avars.end(), asubs.begin(), asubs.end()); - } - else - { - Trace("ext-rew-bcp-debug") << "...do partial substitute" << std::endl; - // substitution is only applicable to compatible kinds - ccs = partialSubstitute(ccs, assign, bcp_kinds); - } + // always use partial substitute, to avoid substitution in witness + Trace("ext-rew-bcp-debug") << "...do partial substitute" << std::endl; + // substitution is only applicable to compatible kinds in bcp_kinds + Node ccs = partialSubstitute(cc, assign, bcp_kinds); childChanged = childChanged || ccs != cc; ccs_children.push_back(ccs); } @@ -1066,19 +1069,10 @@ Node ExtendedRewriter::extendedRewriteEqRes(Kind andk, Node ccs = n[j]; if (i != j) { - if (bcp_kinds.empty()) - { - ccs = ccs.substitute( - vars.begin(), vars.end(), subs.begin(), subs.end()); - } - else - { - std::map<Node, Node> assign; - // vars.size()==subs.size()==1 - assign[vars[0]] = subs[0]; - // substitution is only applicable to compatible kinds - ccs = partialSubstitute(ccs, assign, bcp_kinds); - } + // Substitution is only applicable to compatible kinds. We always + // use the partialSubstitute method to avoid substitution into + // witness terms. + ccs = partialSubstitute(ccs, vars, subs, bcp_kinds); childrenChanged = childrenChanged || n[j] != ccs; } children.push_back(ccs); @@ -1533,11 +1527,12 @@ Node ExtendedRewriter::extendedRewriteEqChain( } Node ExtendedRewriter::partialSubstitute(Node n, - std::map<Node, Node>& assign, - std::map<Kind, bool>& rkinds) + const std::map<Node, Node>& assign, + const std::map<Kind, bool>& rkinds) { std::unordered_map<TNode, Node, TNodeHashFunction> visited; std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it; + std::map<Node, Node>::const_iterator ita; std::vector<TNode> visit; TNode cur; visit.push_back(n); @@ -1549,16 +1544,19 @@ Node ExtendedRewriter::partialSubstitute(Node n, if (it == visited.end()) { - std::map<Node, Node>::iterator ita = assign.find(cur); + ita = assign.find(cur); if (ita != assign.end()) { visited[cur] = ita->second; } else { - // can only recurse on these kinds + // If rkinds is non-empty, then can only recurse on its kinds. + // We also always disallow substitution into witness. Notice that + // we disallow witness here, due to unsoundness when applying contextual + // substitutions over witness terms (see #4620). Kind k = cur.getKind(); - if (rkinds.find(k) != rkinds.end()) + if (k != WITNESS && (rkinds.empty() || rkinds.find(k) != rkinds.end())) { visited[cur] = Node::null(); visit.push_back(cur); @@ -1602,6 +1600,20 @@ Node ExtendedRewriter::partialSubstitute(Node n, return visited[n]; } +Node ExtendedRewriter::partialSubstitute(Node n, + const std::vector<Node>& vars, + const std::vector<Node>& subs, + const std::map<Kind, bool>& rkinds) +{ + Assert(vars.size() == subs.size()); + std::map<Node, Node> assign; + for (size_t i = 0, nvars = vars.size(); i < nvars; i++) + { + assign[vars[i]] = subs[i]; + } + return partialSubstitute(n, assign, rkinds); +} + Node ExtendedRewriter::solveEquality(Node n) { // TODO (#1706) : implement diff --git a/src/theory/quantifiers/extended_rewrite.h b/src/theory/quantifiers/extended_rewrite.h index 9a0ab6382..5ed6ee3f3 100644 --- a/src/theory/quantifiers/extended_rewrite.h +++ b/src/theory/quantifiers/extended_rewrite.h @@ -2,9 +2,9 @@ /*! \file extended_rewrite.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -200,11 +200,17 @@ class ExtendedRewriter /** Partial substitute * * Applies the substitution specified by assign to n, recursing only beneath - * terms whose Kind appears in rec_kinds. + * terms whose Kind appears in rkinds (when rkinds is empty), and additionally + * never recursing beneath WITNESS. */ Node partialSubstitute(Node n, - std::map<Node, Node>& assign, - std::map<Kind, bool>& rkinds); + const std::map<Node, Node>& assign, + const std::map<Kind, bool>& rkinds); + /** same as above, with vectors */ + Node partialSubstitute(Node n, + const std::vector<Node>& vars, + const std::vector<Node>& subs, + const std::map<Kind, bool>& rkinds); /** solve equality * * If this function returns a non-null node n', then n' is equivalent to n diff --git a/src/theory/quantifiers/first_order_model.cpp b/src/theory/quantifiers/first_order_model.cpp index 1498e54a6..61eb4ff39 100644 --- a/src/theory/quantifiers/first_order_model.cpp +++ b/src/theory/quantifiers/first_order_model.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/first_order_model.h b/src/theory/quantifiers/first_order_model.h index ab1f7c768..4e1ef6d7f 100644 --- a/src/theory/quantifiers/first_order_model.h +++ b/src/theory/quantifiers/first_order_model.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Paul Meng, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/fmf/bounded_integers.cpp b/src/theory/quantifiers/fmf/bounded_integers.cpp index ef572ace7..b3ea69dbc 100644 --- a/src/theory/quantifiers/fmf/bounded_integers.cpp +++ b/src/theory/quantifiers/fmf/bounded_integers.cpp @@ -2,9 +2,9 @@ /*! \file bounded_integers.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli, Tim King + ** Andrew Reynolds, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/fmf/bounded_integers.h b/src/theory/quantifiers/fmf/bounded_integers.h index 2180a7270..a21c9d81b 100644 --- a/src/theory/quantifiers/fmf/bounded_integers.h +++ b/src/theory/quantifiers/fmf/bounded_integers.h @@ -2,9 +2,9 @@ /*! \file bounded_integers.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Mathias Preiner + ** Andrew Reynolds, Mathias Preiner, Mudathir Mohamed ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/fmf/full_model_check.cpp b/src/theory/quantifiers/fmf/full_model_check.cpp index af3a94d96..802271858 100644 --- a/src/theory/quantifiers/fmf/full_model_check.cpp +++ b/src/theory/quantifiers/fmf/full_model_check.cpp @@ -2,9 +2,9 @@ /*! \file full_model_check.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Francois Bobot + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..4a6c62827 100644 --- a/src/theory/quantifiers/fmf/full_model_check.h +++ b/src/theory/quantifiers/fmf/full_model_check.h @@ -2,9 +2,9 @@ /*! \file full_model_check.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Mathias Preiner + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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/fmf/model_builder.cpp b/src/theory/quantifiers/fmf/model_builder.cpp index a3dc50dd1..c8e0ba89a 100644 --- a/src/theory/quantifiers/fmf/model_builder.cpp +++ b/src/theory/quantifiers/fmf/model_builder.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/fmf/model_builder.h b/src/theory/quantifiers/fmf/model_builder.h index c8f59defe..432686c60 100644 --- a/src/theory/quantifiers/fmf/model_builder.h +++ b/src/theory/quantifiers/fmf/model_builder.h @@ -2,9 +2,9 @@ /*! \file model_builder.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Mathias Preiner + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/fmf/model_engine.cpp b/src/theory/quantifiers/fmf/model_engine.cpp index 3fff374a7..879bfd1c1 100644 --- a/src/theory/quantifiers/fmf/model_engine.cpp +++ b/src/theory/quantifiers/fmf/model_engine.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/fmf/model_engine.h b/src/theory/quantifiers/fmf/model_engine.h index 3165b01db..a46c7cbf3 100644 --- a/src/theory/quantifiers/fmf/model_engine.h +++ b/src/theory/quantifiers/fmf/model_engine.h @@ -2,9 +2,9 @@ /*! \file model_engine.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Mathias Preiner + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/fun_def_evaluator.cpp b/src/theory/quantifiers/fun_def_evaluator.cpp index 0b48b3995..951899883 100644 --- a/src/theory/quantifiers/fun_def_evaluator.cpp +++ b/src/theory/quantifiers/fun_def_evaluator.cpp @@ -2,9 +2,9 @@ /*! \file fun_def_evaluator.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/fun_def_evaluator.h b/src/theory/quantifiers/fun_def_evaluator.h index 64c9f3f04..7e159bb26 100644 --- a/src/theory/quantifiers/fun_def_evaluator.h +++ b/src/theory/quantifiers/fun_def_evaluator.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/fun_def_process.cpp b/src/theory/quantifiers/fun_def_process.cpp index 0339b54f5..2c5eab94c 100644 --- a/src/theory/quantifiers/fun_def_process.cpp +++ b/src/theory/quantifiers/fun_def_process.cpp @@ -2,9 +2,9 @@ /*! \file fun_def_process.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/fun_def_process.h b/src/theory/quantifiers/fun_def_process.h index f98208aba..ce2d2e239 100644 --- a/src/theory/quantifiers/fun_def_process.h +++ b/src/theory/quantifiers/fun_def_process.h @@ -2,9 +2,9 @@ /*! \file fun_def_process.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/inst_match.cpp b/src/theory/quantifiers/inst_match.cpp index af425c570..69b228f8e 100644 --- a/src/theory/quantifiers/inst_match.cpp +++ b/src/theory/quantifiers/inst_match.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Francois Bobot ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/inst_match.h b/src/theory/quantifiers/inst_match.h index 324b2c736..46741d098 100644 --- a/src/theory/quantifiers/inst_match.h +++ b/src/theory/quantifiers/inst_match.h @@ -2,9 +2,9 @@ /*! \file inst_match.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Francois Bobot + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/inst_match_trie.cpp b/src/theory/quantifiers/inst_match_trie.cpp index 19ef88949..0993edbae 100644 --- a/src/theory/quantifiers/inst_match_trie.cpp +++ b/src/theory/quantifiers/inst_match_trie.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/inst_match_trie.h b/src/theory/quantifiers/inst_match_trie.h index 4854616db..a827ff697 100644 --- a/src/theory/quantifiers/inst_match_trie.h +++ b/src/theory/quantifiers/inst_match_trie.h @@ -2,9 +2,9 @@ /*! \file inst_match_trie.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/inst_strategy_enumerative.cpp b/src/theory/quantifiers/inst_strategy_enumerative.cpp index 9388f2dba..b85537e64 100644 --- a/src/theory/quantifiers/inst_strategy_enumerative.cpp +++ b/src/theory/quantifiers/inst_strategy_enumerative.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/inst_strategy_enumerative.h b/src/theory/quantifiers/inst_strategy_enumerative.h index 4d98f00ef..070878a3d 100644 --- a/src/theory/quantifiers/inst_strategy_enumerative.h +++ b/src/theory/quantifiers/inst_strategy_enumerative.h @@ -2,9 +2,9 @@ /*! \file inst_strategy_enumerative.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/instantiate.cpp b/src/theory/quantifiers/instantiate.cpp index 89e2678fc..53e9c6832 100644 --- a/src/theory/quantifiers/instantiate.cpp +++ b/src/theory/quantifiers/instantiate.cpp @@ -2,9 +2,9 @@ /*! \file instantiate.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Morgan Deters + ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/instantiate.h b/src/theory/quantifiers/instantiate.h index d10a44149..aa4f85cdc 100644 --- a/src/theory/quantifiers/instantiate.h +++ b/src/theory/quantifiers/instantiate.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/lazy_trie.cpp b/src/theory/quantifiers/lazy_trie.cpp index a50352df5..41722822e 100644 --- a/src/theory/quantifiers/lazy_trie.cpp +++ b/src/theory/quantifiers/lazy_trie.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/lazy_trie.h b/src/theory/quantifiers/lazy_trie.h index 8f822fcc0..7f8e306e9 100644 --- a/src/theory/quantifiers/lazy_trie.h +++ b/src/theory/quantifiers/lazy_trie.h @@ -2,9 +2,9 @@ /*! \file lazy_trie.h ** \verbatim ** Top contributors (to current version): - ** Haniel Barbosa, Andrew Reynolds, Tim King + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/proof_checker.cpp b/src/theory/quantifiers/proof_checker.cpp new file mode 100644 index 000000000..a1a581d1c --- /dev/null +++ b/src/theory/quantifiers/proof_checker.cpp @@ -0,0 +1,109 @@ +/********************* */ +/*! \file proof_checker.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 quantifiers proof checker + **/ + +#include "theory/quantifiers/proof_checker.h" + +#include "expr/skolem_manager.h" +#include "theory/builtin/proof_checker.h" + +using namespace CVC4::kind; + +namespace CVC4 { +namespace theory { +namespace quantifiers { + +void QuantifiersProofRuleChecker::registerTo(ProofChecker* pc) +{ + // add checkers + pc->registerChecker(PfRule::WITNESS_INTRO, this); + pc->registerChecker(PfRule::EXISTS_INTRO, this); + pc->registerChecker(PfRule::SKOLEMIZE, this); + pc->registerChecker(PfRule::INSTANTIATE, this); +} + +Node QuantifiersProofRuleChecker::checkInternal( + PfRule id, const std::vector<Node>& children, const std::vector<Node>& args) +{ + NodeManager* nm = NodeManager::currentNM(); + // compute what was proven + if (id == PfRule::WITNESS_INTRO || id == PfRule::EXISTS_INTRO) + { + Assert(children.size() == 1); + Assert(args.size() == 1); + SkolemManager* sm = nm->getSkolemManager(); + Node p = children[0]; + Node t = args[0]; + Node exists = sm->mkExistential(t, p); + if (id == PfRule::EXISTS_INTRO) + { + return exists; + } + std::vector<Node> skolems; + sm->mkSkolemize(exists, skolems, "k"); + Assert(skolems.size() == 1); + return skolems[0]; + } + else if (id == PfRule::SKOLEMIZE) + { + Assert(children.size() == 1); + Assert(args.empty()); + // can use either negated FORALL or EXISTS + if (children[0].getKind() != EXISTS + && (children[0].getKind() != NOT || children[0][0].getKind() != FORALL)) + { + return Node::null(); + } + SkolemManager* sm = nm->getSkolemManager(); + Node exists; + if (children[0].getKind() == EXISTS) + { + exists = children[0]; + } + else + { + std::vector<Node> echildren(children[0][0].begin(), children[0][0].end()); + exists = nm->mkNode(EXISTS, echildren); + } + std::vector<Node> skolems; + Node res = sm->mkSkolemize(exists, skolems, "k"); + return res; + } + else if (id == PfRule::INSTANTIATE) + { + Assert(children.size() == 1); + if (children[0].getKind() != FORALL + || args.size() != children[0][0].getNumChildren()) + { + return Node::null(); + } + Node body = children[0][1]; + std::vector<Node> vars; + std::vector<Node> subs; + for (unsigned i = 0, nargs = args.size(); i < nargs; i++) + { + vars.push_back(children[0][0][i]); + subs.push_back(args[i]); + } + Node inst = + body.substitute(vars.begin(), vars.end(), subs.begin(), subs.end()); + return inst; + } + + // no rule + return Node::null(); +} + +} // namespace quantifiers +} // namespace theory +} // namespace CVC4 diff --git a/src/theory/quantifiers/proof_checker.h b/src/theory/quantifiers/proof_checker.h new file mode 100644 index 000000000..1e107e6bb --- /dev/null +++ b/src/theory/quantifiers/proof_checker.h @@ -0,0 +1,49 @@ +/********************* */ +/*! \file proof_checker.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 Quantifiers proof checker utility + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__THEORY__QUANTIFIERS__PROOF_CHECKER_H +#define CVC4__THEORY__QUANTIFIERS__PROOF_CHECKER_H + +#include "expr/node.h" +#include "expr/proof_checker.h" +#include "expr/proof_node.h" + +namespace CVC4 { +namespace theory { +namespace quantifiers { + +/** A checker for quantifiers proofs */ +class QuantifiersProofRuleChecker : public ProofRuleChecker +{ + public: + QuantifiersProofRuleChecker() {} + ~QuantifiersProofRuleChecker() {} + + /** 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 quantifiers +} // namespace theory +} // namespace CVC4 + +#endif /* CVC4__THEORY__QUANTIFIERS__PROOF_CHECKER_H */ diff --git a/src/theory/quantifiers/quant_conflict_find.cpp b/src/theory/quantifiers/quant_conflict_find.cpp index 2d1cf6531..b3e9eb22a 100644 --- a/src/theory/quantifiers/quant_conflict_find.cpp +++ b/src/theory/quantifiers/quant_conflict_find.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_conflict_find.h b/src/theory/quantifiers/quant_conflict_find.h index 59da77739..f3ba5db6b 100644 --- a/src/theory/quantifiers/quant_conflict_find.h +++ b/src/theory/quantifiers/quant_conflict_find.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_epr.cpp b/src/theory/quantifiers/quant_epr.cpp index e03a2c120..8c3e7e5ed 100644 --- a/src/theory/quantifiers/quant_epr.cpp +++ b/src/theory/quantifiers/quant_epr.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_epr.h b/src/theory/quantifiers/quant_epr.h index 1284dde33..60700bf5b 100644 --- a/src/theory/quantifiers/quant_epr.h +++ b/src/theory/quantifiers/quant_epr.h @@ -2,9 +2,9 @@ /*! \file quant_epr.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_relevance.cpp b/src/theory/quantifiers/quant_relevance.cpp index de54fa05f..0ddbe9a05 100644 --- a/src/theory/quantifiers/quant_relevance.cpp +++ b/src/theory/quantifiers/quant_relevance.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_relevance.h b/src/theory/quantifiers/quant_relevance.h index 26a4630cd..c03f8d229 100644 --- a/src/theory/quantifiers/quant_relevance.h +++ b/src/theory/quantifiers/quant_relevance.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_rep_bound_ext.cpp b/src/theory/quantifiers/quant_rep_bound_ext.cpp index 8b3aaf589..5034d926a 100644 --- a/src/theory/quantifiers/quant_rep_bound_ext.cpp +++ b/src/theory/quantifiers/quant_rep_bound_ext.cpp @@ -2,9 +2,9 @@ /*! \file quant_rep_bound_ext.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_rep_bound_ext.h b/src/theory/quantifiers/quant_rep_bound_ext.h index 1e54786a3..1f8ad19fa 100644 --- a/src/theory/quantifiers/quant_rep_bound_ext.h +++ b/src/theory/quantifiers/quant_rep_bound_ext.h @@ -2,9 +2,9 @@ /*! \file quant_rep_bound_ext.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_split.cpp b/src/theory/quantifiers/quant_split.cpp index 5ad01009a..a61a60edf 100644 --- a/src/theory/quantifiers/quant_split.cpp +++ b/src/theory/quantifiers/quant_split.cpp @@ -2,9 +2,9 @@ /*! \file quant_split.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_split.h b/src/theory/quantifiers/quant_split.h index bea0c3439..1aa57c1c3 100644 --- a/src/theory/quantifiers/quant_split.h +++ b/src/theory/quantifiers/quant_split.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_util.cpp b/src/theory/quantifiers/quant_util.cpp index 695d1835c..a8eda10bb 100644 --- a/src/theory/quantifiers/quant_util.cpp +++ b/src/theory/quantifiers/quant_util.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quant_util.h b/src/theory/quantifiers/quant_util.h index 723a56415..db77c10e8 100644 --- a/src/theory/quantifiers/quant_util.h +++ b/src/theory/quantifiers/quant_util.h @@ -2,9 +2,9 @@ /*! \file quant_util.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quantifiers_attributes.cpp b/src/theory/quantifiers/quantifiers_attributes.cpp index 065c2ecd3..17c625652 100644 --- a/src/theory/quantifiers/quantifiers_attributes.cpp +++ b/src/theory/quantifiers/quantifiers_attributes.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Paul Meng, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quantifiers_attributes.h b/src/theory/quantifiers/quantifiers_attributes.h index 4d9e433a7..189c79470 100644 --- a/src/theory/quantifiers/quantifiers_attributes.h +++ b/src/theory/quantifiers/quantifiers_attributes.h @@ -2,9 +2,9 @@ /*! \file quantifiers_attributes.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp index df86922bc..0848032f8 100644 --- a/src/theory/quantifiers/quantifiers_rewriter.cpp +++ b/src/theory/quantifiers/quantifiers_rewriter.cpp @@ -2,9 +2,9 @@ /*! \file quantifiers_rewriter.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..da3bd2212 100644 --- a/src/theory/quantifiers/quantifiers_rewriter.h +++ b/src/theory/quantifiers/quantifiers_rewriter.h @@ -2,9 +2,9 @@ /*! \file quantifiers_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Morgan Deters, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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/query_generator.cpp b/src/theory/quantifiers/query_generator.cpp index 248128c1e..4cf65b24a 100644 --- a/src/theory/quantifiers/query_generator.cpp +++ b/src/theory/quantifiers/query_generator.cpp @@ -2,9 +2,9 @@ /*! \file query_generator.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -16,6 +16,8 @@ #include "theory/quantifiers/query_generator.h" #include <fstream> + +#include "api/cvc4cpp.h" #include "options/quantifiers_options.h" #include "smt/smt_engine.h" #include "smt/smt_engine_scope.h" @@ -157,9 +159,16 @@ void QueryGenerator::checkQuery(Node qy, unsigned spIndex) Trace("sygus-qgen-check") << " query: check " << qy << "..." << std::endl; NodeManager* nm = NodeManager::currentNM(); // make the satisfiability query + // + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // This is only temporarily until we have separate options for each + // SmtEngine instance. We should reuse the same ExprManager with + // a different SmtEngine (and different options) here, eventually. + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! bool needExport = false; - ExprManager em(nm->getOptions()); - std::unique_ptr<SmtEngine> queryChecker; + api::Solver slv(&nm->getOptions()); + ExprManager* em = slv.getExprManager(); + SmtEngine* queryChecker = slv.getSmtEngine(); ExprManagerMapCollection varMap; initializeChecker(queryChecker, em, varMap, qy, needExport); Result r = queryChecker->checkSat(); diff --git a/src/theory/quantifiers/query_generator.h b/src/theory/quantifiers/query_generator.h index 8cb7b2785..8b861a9b9 100644 --- a/src/theory/quantifiers/query_generator.h +++ b/src/theory/quantifiers/query_generator.h @@ -2,9 +2,9 @@ /*! \file query_generator.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/relevant_domain.cpp b/src/theory/quantifiers/relevant_domain.cpp index 6248e9722..8946ca44a 100644 --- a/src/theory/quantifiers/relevant_domain.cpp +++ b/src/theory/quantifiers/relevant_domain.cpp @@ -2,9 +2,9 @@ /*! \file relevant_domain.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/relevant_domain.h b/src/theory/quantifiers/relevant_domain.h index 8f348b471..aeff5716c 100644 --- a/src/theory/quantifiers/relevant_domain.h +++ b/src/theory/quantifiers/relevant_domain.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/single_inv_partition.cpp b/src/theory/quantifiers/single_inv_partition.cpp index 50831fdac..7047aa9ea 100644 --- a/src/theory/quantifiers/single_inv_partition.cpp +++ b/src/theory/quantifiers/single_inv_partition.cpp @@ -2,9 +2,9 @@ /*! \file single_inv_partition.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/single_inv_partition.h b/src/theory/quantifiers/single_inv_partition.h index cdc56d1f0..3245228d8 100644 --- a/src/theory/quantifiers/single_inv_partition.h +++ b/src/theory/quantifiers/single_inv_partition.h @@ -2,9 +2,9 @@ /*! \file single_inv_partition.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/skolemize.cpp b/src/theory/quantifiers/skolemize.cpp index a83303454..364665e7a 100644 --- a/src/theory/quantifiers/skolemize.cpp +++ b/src/theory/quantifiers/skolemize.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/skolemize.h b/src/theory/quantifiers/skolemize.h index 86af1ee1b..0fe6bef00 100644 --- a/src/theory/quantifiers/skolemize.h +++ b/src/theory/quantifiers/skolemize.h @@ -2,9 +2,9 @@ /*! \file skolemize.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/solution_filter.cpp b/src/theory/quantifiers/solution_filter.cpp index 5e1bf54f4..e98b875fd 100644 --- a/src/theory/quantifiers/solution_filter.cpp +++ b/src/theory/quantifiers/solution_filter.cpp @@ -2,9 +2,9 @@ /*! \file solution_filter.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/solution_filter.h b/src/theory/quantifiers/solution_filter.h index bd4c62a09..0be71371e 100644 --- a/src/theory/quantifiers/solution_filter.h +++ b/src/theory/quantifiers/solution_filter.h @@ -2,9 +2,9 @@ /*! \file solution_filter.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/ce_guided_single_inv.cpp b/src/theory/quantifiers/sygus/ce_guided_single_inv.cpp index ec1b9e71a..df21a06eb 100644 --- a/src/theory/quantifiers/sygus/ce_guided_single_inv.cpp +++ b/src/theory/quantifiers/sygus/ce_guided_single_inv.cpp @@ -2,9 +2,9 @@ /*! \file ce_guided_single_inv.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli, Tim King + ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/ce_guided_single_inv.h b/src/theory/quantifiers/sygus/ce_guided_single_inv.h index 19caa4c79..b16e3997a 100644 --- a/src/theory/quantifiers/sygus/ce_guided_single_inv.h +++ b/src/theory/quantifiers/sygus/ce_guided_single_inv.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.cpp b/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.cpp index 9a6728c29..d6d854c44 100644 --- a/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.cpp +++ b/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.cpp @@ -2,9 +2,9 @@ /*! \file ce_guided_single_inv_sol.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Andres Noetzli + ** Andrew Reynolds, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.h b/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.h index ed84c81b2..847fd2d9b 100644 --- a/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.h +++ b/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.h @@ -2,9 +2,9 @@ /*! \file ce_guided_single_inv_sol.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/cegis.cpp b/src/theory/quantifiers/sygus/cegis.cpp index 0c11baecc..cf9611eb2 100644 --- a/src/theory/quantifiers/sygus/cegis.cpp +++ b/src/theory/quantifiers/sygus/cegis.cpp @@ -2,9 +2,9 @@ /*! \file cegis.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/cegis.h b/src/theory/quantifiers/sygus/cegis.h index bebb91fa3..d976a5c4b 100644 --- a/src/theory/quantifiers/sygus/cegis.h +++ b/src/theory/quantifiers/sygus/cegis.h @@ -2,9 +2,9 @@ /*! \file cegis.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa, FabianWolff + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/cegis_core_connective.cpp b/src/theory/quantifiers/sygus/cegis_core_connective.cpp index cc6c051cd..5784e42c0 100644 --- a/src/theory/quantifiers/sygus/cegis_core_connective.cpp +++ b/src/theory/quantifiers/sygus/cegis_core_connective.cpp @@ -2,9 +2,9 @@ /*! \file cegis_core_connective.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -735,8 +735,9 @@ Node CegisCoreConnective::constructSolutionFromPool(Component& ccheck, { addSuccess = false; // try a new core - std::unique_ptr<SmtEngine> checkSol; - initializeSubsolver(checkSol); + std::unique_ptr<SmtEngine> checkSol( + new SmtEngine(NodeManager::currentNM()->toExprManager())); + initializeSubsolver(checkSol.get()); Trace("sygus-ccore") << "----- Check candidate " << an << std::endl; std::vector<Node> rasserts = asserts; rasserts.push_back(d_sc); @@ -775,8 +776,9 @@ Node CegisCoreConnective::constructSolutionFromPool(Component& ccheck, { // In terms of Variant #2, this is the check "if S ^ U is unsat" Trace("sygus-ccore") << "----- Check side condition" << std::endl; - std::unique_ptr<SmtEngine> checkSc; - initializeSubsolver(checkSc); + std::unique_ptr<SmtEngine> checkSc( + new SmtEngine(NodeManager::currentNM()->toExprManager())); + initializeSubsolver(checkSc.get()); std::vector<Node> scasserts; scasserts.insert(scasserts.end(), uasserts.begin(), uasserts.end()); scasserts.push_back(d_sc); diff --git a/src/theory/quantifiers/sygus/cegis_core_connective.h b/src/theory/quantifiers/sygus/cegis_core_connective.h index a55cee564..c1b4c31a2 100644 --- a/src/theory/quantifiers/sygus/cegis_core_connective.h +++ b/src/theory/quantifiers/sygus/cegis_core_connective.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/cegis_unif.cpp b/src/theory/quantifiers/sygus/cegis_unif.cpp index a76159b90..582fa067d 100644 --- a/src/theory/quantifiers/sygus/cegis_unif.cpp +++ b/src/theory/quantifiers/sygus/cegis_unif.cpp @@ -2,9 +2,9 @@ /*! \file cegis_unif.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/cegis_unif.h b/src/theory/quantifiers/sygus/cegis_unif.h index d476d5fb3..c3da1b481 100644 --- a/src/theory/quantifiers/sygus/cegis_unif.h +++ b/src/theory/quantifiers/sygus/cegis_unif.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Haniel Barbosa, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/enum_stream_substitution.cpp b/src/theory/quantifiers/sygus/enum_stream_substitution.cpp index dd9af2c43..64e604d0b 100644 --- a/src/theory/quantifiers/sygus/enum_stream_substitution.cpp +++ b/src/theory/quantifiers/sygus/enum_stream_substitution.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/enum_stream_substitution.h b/src/theory/quantifiers/sygus/enum_stream_substitution.h index 8f978dda6..b8619715d 100644 --- a/src/theory/quantifiers/sygus/enum_stream_substitution.h +++ b/src/theory/quantifiers/sygus/enum_stream_substitution.h @@ -2,9 +2,9 @@ /*! \file enum_stream_substitution.h ** \verbatim ** Top contributors (to current version): - ** Haniel Barbosa, Andrew Reynolds + ** Haniel Barbosa, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/example_eval_cache.cpp b/src/theory/quantifiers/sygus/example_eval_cache.cpp index ee5394972..c3a0604c7 100644 --- a/src/theory/quantifiers/sygus/example_eval_cache.cpp +++ b/src/theory/quantifiers/sygus/example_eval_cache.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/example_eval_cache.h b/src/theory/quantifiers/sygus/example_eval_cache.h index 6c5a65e7f..886ff6bf2 100644 --- a/src/theory/quantifiers/sygus/example_eval_cache.h +++ b/src/theory/quantifiers/sygus/example_eval_cache.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/example_infer.cpp b/src/theory/quantifiers/sygus/example_infer.cpp index 50d2bf3d2..b139389e0 100644 --- a/src/theory/quantifiers/sygus/example_infer.cpp +++ b/src/theory/quantifiers/sygus/example_infer.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Haniel Barbosa, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/example_infer.h b/src/theory/quantifiers/sygus/example_infer.h index 547d41121..ef8957eed 100644 --- a/src/theory/quantifiers/sygus/example_infer.h +++ b/src/theory/quantifiers/sygus/example_infer.h @@ -2,9 +2,9 @@ /*! \file example_infer.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/example_min_eval.cpp b/src/theory/quantifiers/sygus/example_min_eval.cpp index 8af63c97f..92cd0f3ca 100644 --- a/src/theory/quantifiers/sygus/example_min_eval.cpp +++ b/src/theory/quantifiers/sygus/example_min_eval.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/example_min_eval.h b/src/theory/quantifiers/sygus/example_min_eval.h index 28fd849de..966d4a180 100644 --- a/src/theory/quantifiers/sygus/example_min_eval.h +++ b/src/theory/quantifiers/sygus/example_min_eval.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_abduct.cpp b/src/theory/quantifiers/sygus/sygus_abduct.cpp index a58c5d841..b71a92260 100644 --- a/src/theory/quantifiers/sygus/sygus_abduct.cpp +++ b/src/theory/quantifiers/sygus/sygus_abduct.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -20,7 +20,7 @@ #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/datatypes/sygus_datatype_utils.h" #include "theory/quantifiers/quantifiers_attributes.h" #include "theory/quantifiers/quantifiers_rewriter.h" #include "theory/quantifiers/sygus/sygus_grammar_cons.h" @@ -58,6 +58,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 +79,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 +88,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 +114,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/quantifiers/sygus/sygus_abduct.h b/src/theory/quantifiers/sygus/sygus_abduct.h index 2fdce542a..046bad946 100644 --- a/src/theory/quantifiers/sygus/sygus_abduct.h +++ b/src/theory/quantifiers/sygus/sygus_abduct.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_enumerator.cpp b/src/theory/quantifiers/sygus/sygus_enumerator.cpp index ce3c94914..86bf53b23 100644 --- a/src/theory/quantifiers/sygus/sygus_enumerator.cpp +++ b/src/theory/quantifiers/sygus/sygus_enumerator.cpp @@ -2,9 +2,9 @@ /*! \file sygus_enumerator.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_enumerator.h b/src/theory/quantifiers/sygus/sygus_enumerator.h index 9803cd962..4bf4fb332 100644 --- a/src/theory/quantifiers/sygus/sygus_enumerator.h +++ b/src/theory/quantifiers/sygus/sygus_enumerator.h @@ -2,9 +2,9 @@ /*! \file sygus_enumerator.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_enumerator_basic.cpp b/src/theory/quantifiers/sygus/sygus_enumerator_basic.cpp index 2e7b80429..84337d3b5 100644 --- a/src/theory/quantifiers/sygus/sygus_enumerator_basic.cpp +++ b/src/theory/quantifiers/sygus/sygus_enumerator_basic.cpp @@ -2,9 +2,9 @@ /*! \file sygus_enumerator_basic.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa, Tim King + ** Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_enumerator_basic.h b/src/theory/quantifiers/sygus/sygus_enumerator_basic.h index 5336d898f..2931eb51f 100644 --- a/src/theory/quantifiers/sygus/sygus_enumerator_basic.h +++ b/src/theory/quantifiers/sygus/sygus_enumerator_basic.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_eval_unfold.cpp b/src/theory/quantifiers/sygus/sygus_eval_unfold.cpp index 9d327bfe1..6d147fe46 100644 --- a/src/theory/quantifiers/sygus/sygus_eval_unfold.cpp +++ b/src/theory/quantifiers/sygus/sygus_eval_unfold.cpp @@ -2,9 +2,9 @@ /*! \file sygus_eval_unfold.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -16,7 +16,7 @@ #include "expr/sygus_datatype.h" #include "options/quantifiers_options.h" -#include "theory/datatypes/theory_datatypes_utils.h" +#include "theory/datatypes/sygus_datatype_utils.h" #include "theory/quantifiers/sygus/term_database_sygus.h" using namespace std; diff --git a/src/theory/quantifiers/sygus/sygus_eval_unfold.h b/src/theory/quantifiers/sygus/sygus_eval_unfold.h index 50b361fc4..8970ce153 100644 --- a/src/theory/quantifiers/sygus/sygus_eval_unfold.h +++ b/src/theory/quantifiers/sygus/sygus_eval_unfold.h @@ -2,9 +2,9 @@ /*! \file sygus_eval_unfold.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_explain.cpp b/src/theory/quantifiers/sygus/sygus_explain.cpp index 8fb7cf2e7..85f6f3428 100644 --- a/src/theory/quantifiers/sygus/sygus_explain.cpp +++ b/src/theory/quantifiers/sygus/sygus_explain.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_explain.h b/src/theory/quantifiers/sygus/sygus_explain.h index ec29ab2a1..c4cf37833 100644 --- a/src/theory/quantifiers/sygus/sygus_explain.h +++ b/src/theory/quantifiers/sygus/sygus_explain.h @@ -2,9 +2,9 @@ /*! \file sygus_explain.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, FabianWolff + ** Andrew Reynolds, Mathias Preiner, Fabian Wolff ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp b/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp index f15b6780c..074b023a2 100644 --- a/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp +++ b/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp @@ -2,9 +2,9 @@ /*! \file sygus_grammar_cons.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -20,7 +20,7 @@ #include "options/quantifiers_options.h" #include "printer/sygus_print_callback.h" #include "theory/bv/theory_bv_utils.h" -#include "theory/datatypes/theory_datatypes_utils.h" +#include "theory/datatypes/sygus_datatype_utils.h" #include "theory/quantifiers/sygus/sygus_grammar_norm.h" #include "theory/quantifiers/sygus/sygus_process_conj.h" #include "theory/quantifiers/sygus/synth_conjecture.h" @@ -459,6 +459,10 @@ void CegGrammarConstructor::collectSygusGrammarTypesFor( // theory of strings shares the integer type TypeNode intType = NodeManager::currentNM()->integerType(); collectSygusGrammarTypesFor(intType,types); + if (range.isSequence()) + { + collectSygusGrammarTypesFor(range.getSequenceElementType(), types); + } } else if (range.isFunction()) { @@ -487,6 +491,37 @@ bool CegGrammarConstructor::isHandledType(TypeNode t) return true; } +Node CegGrammarConstructor::createLambdaWithZeroArg( + Kind k, TypeNode bArgType, std::shared_ptr<SygusPrintCallback> spc) +{ + NodeManager* nm = NodeManager::currentNM(); + std::vector<Node> opLArgs; + std::vector<Expr> opLArgsExpr; + // get the builtin type + opLArgs.push_back(nm->mkBoundVar(bArgType)); + opLArgsExpr.push_back(opLArgs.back().toExpr()); + // build zarg + Node zarg; + Assert(bArgType.isReal() || bArgType.isBitVector()); + if (bArgType.isReal()) + { + zarg = nm->mkConst(Rational(0)); + } + else + { + unsigned size = bArgType.getBitVectorSize(); + zarg = bv::utils::mkZero(size); + } + Node body = nm->mkNode(k, zarg, opLArgs.back()); + // use a print callback since we do not want to print the lambda + spc = std::make_shared<printer::SygusExprPrintCallback>(body.toExpr(), + opLArgsExpr); + // create operator + Node op = nm->mkNode(LAMBDA, nm->mkNode(BOUND_VAR_LIST, opLArgs), body); + Trace("sygus-grammar-def") << "\t...building lambda op " << op << "\n"; + return op; +} + void CegGrammarConstructor::mkSygusDefaultGrammar( TypeNode range, Node bvl, @@ -543,7 +578,7 @@ void CegGrammarConstructor::mkSygusDefaultGrammar( std::map<TypeNode, std::unordered_set<Node, NodeHashFunction>>::const_iterator itc; // maps types to the index of its "any term" grammar construction - std::map<TypeNode, unsigned> typeToGAnyTerm; + std::map<TypeNode, std::pair<unsigned, bool>> typeToGAnyTerm; options::SygusGrammarConsMode sgcm = options::sygusGrammarConsMode(); for (unsigned i = 0, size = types.size(); i < size; ++i) { @@ -589,7 +624,8 @@ void CegGrammarConstructor::mkSygusDefaultGrammar( // we construct the grammar for the Boolean type last. for (int i = (types.size() - 2); i >= 0; --i) { - Trace("sygus-grammar-def") << "Make grammar for " << types[i] << " " << unres_types[i] << std::endl; + Trace("sygus-grammar-def") << "Make grammar for " << types[i] << " " + << unres_types[i] << std::endl; TypeNode unres_t = unres_types[i]; options::SygusGrammarConsMode tsgcm = sgcm; if (tsgcm == options::SygusGrammarConsMode::ANY_TERM @@ -606,12 +642,14 @@ void CegGrammarConstructor::mkSygusDefaultGrammar( { // Add a placeholder for the "any term" version of this datatype, to be // constructed later. - typeToGAnyTerm[types[i]] = sdts.size(); std::stringstream ssat; ssat << sdts[i].d_sdt.getName() << "_any_term"; sdts.push_back(SygusDatatypeGenerator(ssat.str())); TypeNode unresAnyTerm = mkUnresolvedType(ssat.str(), unres); unres_types.push_back(unresAnyTerm); + // set tracking information for later addition at boolean type. + std::pair<unsigned, bool> p(sdts.size() - 1, false); + typeToGAnyTerm[types[i]] = p; } } Trace("sygus-grammar-def") @@ -771,7 +809,7 @@ void CegGrammarConstructor::mkSygusDefaultGrammar( sdts[i].addConstructor(kind, cargsBinary); } } - else if (types[i].isString()) + else if (types[i].isStringLike()) { // concatenation std::vector<TypeNode> cargsBinary; @@ -789,6 +827,18 @@ void CegGrammarConstructor::mkSygusDefaultGrammar( std::vector<TypeNode> cargsLen; cargsLen.push_back(unres_t); sdts[i_intType].addConstructor(STRING_LENGTH, cargsLen); + if (types[i].isSequence()) + { + TypeNode etype = types[i].getSequenceElementType(); + // retrieve element unresolved type + Assert(type_to_unres.find(etype) != type_to_unres.end()); + TypeNode unresElemType = type_to_unres[etype]; + + Trace("sygus-grammar-def") << "...add for seq.unit" << std::endl; + std::vector<TypeNode> cargsSeqUnit; + cargsSeqUnit.push_back(unresElemType); + sdts[i].addConstructor(SEQ_UNIT, cargsSeqUnit); + } } else if (types[i].isArray()) { @@ -916,7 +966,7 @@ void CegGrammarConstructor::mkSygusDefaultGrammar( cargsIte.push_back(unres_t); sdts[i].addConstructor(k, cargsIte); } - std::map<TypeNode, unsigned>::iterator itgat; + std::map<TypeNode, std::pair<unsigned, bool>>::iterator itgat; // initialize the datatypes (except for the last one, reserved for Bool) for (unsigned i = 0, size = types.size() - 1; i < size; ++i) { @@ -933,9 +983,10 @@ void CegGrammarConstructor::mkSygusDefaultGrammar( // no any term datatype, we are done continue; } + unsigned iat = itgat->second.first; Trace("sygus-grammar-def") << "Build any-term datatype for " << types[i] << "..." << std::endl; - unsigned iat = itgat->second; + // for now, only real has any term construction Assert(types[i].isReal()); // We have initialized the given type sdts[i], which should now contain @@ -1132,6 +1183,8 @@ void CegGrammarConstructor::mkSygusDefaultGrammar( // This ensures that ( c1*x + c2*y >= 0 ) has the same weight as // e.g. ( x >= 0 ) or ( y >= 0 ). sdts[iat].d_sdt.addConstructor(op, "polynomial", cargsAnyTerm, spc, 0); + // mark that predicates should be of the form (= pol 0) and (<= pol 0) + itgat->second.second = true; } else { @@ -1193,34 +1246,76 @@ void CegGrammarConstructor::mkSygusDefaultGrammar( continue; } unsigned iuse = i; - // use the any-term type if it exists + bool zarg = false; + // use the any-term type if it exists and a zero argument if it is a + // polynomial grammar itgat = typeToGAnyTerm.find(types[i]); if (itgat != typeToGAnyTerm.end()) { - iuse = itgat->second; + iuse = itgat->second.first; + zarg = itgat->second.second; + Trace("sygus-grammar-def") + << "...unres type " << unres_types[i] << " became " + << (!zarg ? "polynomial " : "") << "unres anyterm type " + << unres_types[iuse] << "\n"; } Trace("sygus-grammar-def") << "...add predicates for " << types[i] << std::endl; //add equality per type Kind k = EQUAL; Trace("sygus-grammar-def") << "...add for " << k << std::endl; std::stringstream ss; - ss << kindToString(k) << "_" << types[i]; - std::vector<TypeNode> cargsBinary; - cargsBinary.push_back(unres_types[iuse]); - cargsBinary.push_back(unres_types[iuse]); - sdtBool.addConstructor(nm->operatorOf(k), ss.str(), cargsBinary); + std::vector<TypeNode> cargs; + cargs.push_back(unres_types[iuse]); + // if polynomial grammar, generate (= anyterm 0) and (<= anyterm 0) as the + // predicates + if (zarg) + { + std::shared_ptr<SygusPrintCallback> spc; + Node op = createLambdaWithZeroArg(k, types[i], spc); + ss << "eq_" << types[i]; + sdtBool.addConstructor(op, ss.str(), cargs); + } + else + { + ss << kindToString(k) << "_" << types[i]; + cargs.push_back(unres_types[iuse]); + sdtBool.addConstructor(nm->operatorOf(k), ss.str(), cargs); + cargs.pop_back(); + } // type specific predicates + std::shared_ptr<SygusPrintCallback> spc; + std::stringstream ssop; if (types[i].isReal()) { Kind kind = LEQ; - Trace("sygus-grammar-def") << "...add for " << kind << std::endl; - sdtBool.addConstructor(kind, cargsBinary); + Trace("sygus-grammar-def") << "...add for " << k << std::endl; + if (zarg) + { + Node op = createLambdaWithZeroArg(kind, types[i], spc); + ssop << "leq_" << types[i]; + sdtBool.addConstructor(op, ssop.str(), cargs); + } + else + { + cargs.push_back(unres_types[iuse]); + sdtBool.addConstructor(kind, cargs); + } } else if (types[i].isBitVector()) { Kind kind = BITVECTOR_ULT; - Trace("sygus-grammar-def") << "...add for " << kind << std::endl; - sdtBool.addConstructor(kind, cargsBinary); + Trace("sygus-grammar-def") << "...add for " << k << std::endl; + if (zarg) + { + Node op = createLambdaWithZeroArg(kind, types[i], spc); + ssop << "leq_" << types[i]; + sdtBool.addConstructor(op, ssop.str(), cargs); + } + else + { + cargs.push_back(unres_types[iuse]); + sdtBool.addConstructor(kind, cargs); + } } else if (types[i].isDatatype()) { @@ -1254,6 +1349,8 @@ void CegGrammarConstructor::mkSygusDefaultGrammar( } // add Boolean connectives, if not in a degenerate case of (recursively) // having only constant constructors + Trace("sygus-grammar-def") + << "...add Boolean connectives for unres type " << unres_bt << std::endl; if (sdtBool.d_sdt.getNumConstructors() > consts.size()) { for (unsigned i = 0; i < 4; i++) diff --git a/src/theory/quantifiers/sygus/sygus_grammar_cons.h b/src/theory/quantifiers/sygus/sygus_grammar_cons.h index 00e9d45fb..b0c575809 100644 --- a/src/theory/quantifiers/sygus/sygus_grammar_cons.h +++ b/src/theory/quantifiers/sygus/sygus_grammar_cons.h @@ -2,9 +2,9 @@ /*! \file sygus_grammar_cons.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Yoni Zohar, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -100,7 +100,7 @@ public: * - term_irrelevant: a set of terms that should not be included in the * grammar. * - include_cons: a set of operators such that if this set is not empty, - * its elements that are in the default grammar (and only them) + * its elements that are in the default grammar (and only them) * will be included. */ static TypeNode mkSygusDefaultType( @@ -248,8 +248,25 @@ public: std::set<Type>& unres); // helper function for mkSygusTemplateType - static TypeNode mkSygusTemplateTypeRec( Node templ, Node templ_arg, TypeNode templ_arg_sygus_type, Node bvl, - const std::string& fun, unsigned& tcount ); + static TypeNode mkSygusTemplateTypeRec(Node templ, + Node templ_arg, + TypeNode templ_arg_sygus_type, + Node bvl, + const std::string& fun, + unsigned& tcount); + + /** + * Given a kind k, create a lambda operator with the given builtin input type + * and an extra zero argument of that same type. For example, for k = LEQ and + * bArgType = Int, the operator will be lambda x : Int. x + 0. Currently the + * supported input types are Real (thus also Int) and BitVector. + * + * This method also creates a print callback for the operator, saved via the + * argument spc, if the caller wishes to not print the lambda. + */ + static Node createLambdaWithZeroArg(Kind k, + TypeNode bArgType, + std::shared_ptr<SygusPrintCallback> spc); //---------------- end grammar construction }; diff --git a/src/theory/quantifiers/sygus/sygus_grammar_norm.cpp b/src/theory/quantifiers/sygus/sygus_grammar_norm.cpp index 3b2c56974..819dd6de9 100644 --- a/src/theory/quantifiers/sygus/sygus_grammar_norm.cpp +++ b/src/theory/quantifiers/sygus/sygus_grammar_norm.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Haniel Barbosa, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_grammar_norm.h b/src/theory/quantifiers/sygus/sygus_grammar_norm.h index 956228f38..7b635884b 100644 --- a/src/theory/quantifiers/sygus/sygus_grammar_norm.h +++ b/src/theory/quantifiers/sygus/sygus_grammar_norm.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Haniel Barbosa, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_grammar_red.cpp b/src/theory/quantifiers/sygus/sygus_grammar_red.cpp index d865457c3..21d0200c4 100644 --- a/src/theory/quantifiers/sygus/sygus_grammar_red.cpp +++ b/src/theory/quantifiers/sygus/sygus_grammar_red.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_grammar_red.h b/src/theory/quantifiers/sygus/sygus_grammar_red.h index f0743027e..361226678 100644 --- a/src/theory/quantifiers/sygus/sygus_grammar_red.h +++ b/src/theory/quantifiers/sygus/sygus_grammar_red.h @@ -2,9 +2,9 @@ /*! \file sygus_grammar_red.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_invariance.cpp b/src/theory/quantifiers/sygus/sygus_invariance.cpp index 388234ec2..02a0c56a6 100644 --- a/src/theory/quantifiers/sygus/sygus_invariance.cpp +++ b/src/theory/quantifiers/sygus/sygus_invariance.cpp @@ -2,9 +2,9 @@ /*! \file sygus_invariance.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_invariance.h b/src/theory/quantifiers/sygus/sygus_invariance.h index feb2d3313..23c2ff964 100644 --- a/src/theory/quantifiers/sygus/sygus_invariance.h +++ b/src/theory/quantifiers/sygus/sygus_invariance.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_module.cpp b/src/theory/quantifiers/sygus/sygus_module.cpp index 0c9d23b6c..536072c47 100644 --- a/src/theory/quantifiers/sygus/sygus_module.cpp +++ b/src/theory/quantifiers/sygus/sygus_module.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_module.h b/src/theory/quantifiers/sygus/sygus_module.h index ac3adb36a..3c41f4962 100644 --- a/src/theory/quantifiers/sygus/sygus_module.h +++ b/src/theory/quantifiers/sygus/sygus_module.h @@ -2,9 +2,9 @@ /*! \file sygus_module.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli + ** Andrew Reynolds, Mathias Preiner, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_pbe.cpp b/src/theory/quantifiers/sygus/sygus_pbe.cpp index 7c1451771..0921fba30 100644 --- a/src/theory/quantifiers/sygus/sygus_pbe.cpp +++ b/src/theory/quantifiers/sygus/sygus_pbe.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Haniel Barbosa, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_pbe.h b/src/theory/quantifiers/sygus/sygus_pbe.h index 3aa668e0d..ebe58f80b 100644 --- a/src/theory/quantifiers/sygus/sygus_pbe.h +++ b/src/theory/quantifiers/sygus/sygus_pbe.h @@ -2,9 +2,9 @@ /*! \file sygus_pbe.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_process_conj.cpp b/src/theory/quantifiers/sygus/sygus_process_conj.cpp index 1b3844578..6df8619f7 100644 --- a/src/theory/quantifiers/sygus/sygus_process_conj.cpp +++ b/src/theory/quantifiers/sygus/sygus_process_conj.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_process_conj.h b/src/theory/quantifiers/sygus/sygus_process_conj.h index d096befed..80426f924 100644 --- a/src/theory/quantifiers/sygus/sygus_process_conj.h +++ b/src/theory/quantifiers/sygus/sygus_process_conj.h @@ -2,9 +2,9 @@ /*! \file sygus_process_conj.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_repair_const.cpp b/src/theory/quantifiers/sygus/sygus_repair_const.cpp index aa0dc8e5e..d34903805 100644 --- a/src/theory/quantifiers/sygus/sygus_repair_const.cpp +++ b/src/theory/quantifiers/sygus/sygus_repair_const.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Haniel Barbosa, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -14,6 +14,7 @@ #include "theory/quantifiers/sygus/sygus_repair_const.h" +#include "api/cvc4cpp.h" #include "options/base_options.h" #include "options/quantifiers_options.h" #include "printer/printer.h" @@ -100,36 +101,6 @@ bool SygusRepairConst::isActive() const return !d_base_inst.isNull() && d_allow_constant_grammar; } -void SygusRepairConst::initializeChecker(std::unique_ptr<SmtEngine>& checker, - ExprManager& em, - ExprManagerMapCollection& varMap, - Node query, - bool& needExport) -{ - if (options::sygusRepairConstTimeout.wasSetByUser()) - { - // To support a separate timeout for the subsolver, we need to create - // a separate ExprManager with its own options. This requires that - // the expressions sent to the subsolver can be exported from on - // ExprManager to another. - initializeSubsolverWithExport(checker, - em, - varMap, - query.toExpr(), - true, - options::sygusRepairConstTimeout()); - // renable options disabled by sygus - checker->setOption("miniscope-quant", true); - checker->setOption("miniscope-quant-fv", true); - checker->setOption("quant-split", true); - } - else - { - needExport = false; - initializeSubsolver(checker, query.toExpr()); - } -} - bool SygusRepairConst::repairSolution(const std::vector<Node>& candidates, const std::vector<Node>& candidate_values, std::vector<Node>& repair_cv, @@ -258,11 +229,48 @@ bool SygusRepairConst::repairSolution(Node sygusBody, Trace("sygus-engine") << "Repairing previous solution..." << std::endl; // make the satisfiability query + // + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // This is only temporarily until we have separate options for each + // SmtEngine instance. We should reuse the same ExprManager with + // a different SmtEngine (and different options) here, eventually. + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! bool needExport = true; + std::unique_ptr<SmtEngine> simpleSmte; + std::unique_ptr<api::Solver> slv; + ExprManager* em = nullptr; + SmtEngine* repcChecker = nullptr; ExprManagerMapCollection varMap; - ExprManager em(nm->getOptions()); - std::unique_ptr<SmtEngine> repcChecker; - initializeChecker(repcChecker, em, varMap, fo_body, needExport); + + if (options::sygusRepairConstTimeout.wasSetByUser()) + { + // To support a separate timeout for the subsolver, we need to create + // a separate ExprManager with its own options. This requires that + // the expressions sent to the subsolver can be exported from on + // ExprManager to another. + slv.reset(new api::Solver(&nm->getOptions())); + em = slv->getExprManager(); + repcChecker = slv->getSmtEngine(); + initializeSubsolverWithExport(repcChecker, + em, + varMap, + fo_body.toExpr(), + true, + options::sygusRepairConstTimeout()); + // renable options disabled by sygus + repcChecker->setOption("miniscope-quant", true); + repcChecker->setOption("miniscope-quant-fv", true); + repcChecker->setOption("quant-split", true); + } + else + { + needExport = false; + em = nm->toExprManager(); + simpleSmte.reset(new SmtEngine(em)); + repcChecker = simpleSmte.get(); + initializeSubsolver(repcChecker, fo_body.toExpr()); + } + Result r = repcChecker->checkSat(); Trace("sygus-repair-const") << "...got : " << r << std::endl; if (r.asSatisfiabilityResult().isSat() == Result::UNSAT @@ -279,7 +287,7 @@ bool SygusRepairConst::repairSolution(Node sygusBody, Node fov_m; if (needExport) { - Expr e_fov = fov.toExpr().exportTo(&em, varMap); + Expr e_fov = fov.toExpr().exportTo(em, varMap); fov_m = Node::fromExpr( repcChecker->getValue(e_fov).exportTo(nm->toExprManager(), varMap)); } diff --git a/src/theory/quantifiers/sygus/sygus_repair_const.h b/src/theory/quantifiers/sygus/sygus_repair_const.h index 6be5ce5e6..e02ca1f3e 100644 --- a/src/theory/quantifiers/sygus/sygus_repair_const.h +++ b/src/theory/quantifiers/sygus/sygus_repair_const.h @@ -2,9 +2,9 @@ /*! \file sygus_repair_const.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -209,26 +209,6 @@ class SygusRepairConst * If n is in the given logic, this method returns true. */ bool getFitToLogicExcludeVar(LogicInfo& logic, Node n, Node& exvar); - /** initialize checker - * - * This function initializes the smt engine checker to check the - * satisfiability of the argument "query" - * - * The arguments em and varMap are used for supporting cases where we - * want checker to use a different expression manager instead of the current - * expression manager. The motivation for this so that different options can - * be set for the subcall. - * - * We update the flag needExport to true if checker is using the expression - * manager em. In this case, subsequent expressions extracted from smte - * (for instance, model values) must be exported to the current expression - * manager. - */ - void initializeChecker(std::unique_ptr<SmtEngine>& checker, - ExprManager& em, - ExprManagerMapCollection& varMap, - Node query, - bool& needExport); }; } /* CVC4::theory::quantifiers namespace */ diff --git a/src/theory/quantifiers/sygus/sygus_stats.cpp b/src/theory/quantifiers/sygus/sygus_stats.cpp index e8e7c0357..ccec37b25 100644 --- a/src/theory/quantifiers/sygus/sygus_stats.cpp +++ b/src/theory/quantifiers/sygus/sygus_stats.cpp @@ -2,9 +2,9 @@ /*! \file sygus_stats.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Morgan Deters + ** Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_stats.h b/src/theory/quantifiers/sygus/sygus_stats.h index 80499f7a4..11f3c9e60 100644 --- a/src/theory/quantifiers/sygus/sygus_stats.h +++ b/src/theory/quantifiers/sygus/sygus_stats.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_unif.cpp b/src/theory/quantifiers/sygus/sygus_unif.cpp index dfbbdfebf..ee30de50e 100644 --- a/src/theory/quantifiers/sygus/sygus_unif.cpp +++ b/src/theory/quantifiers/sygus/sygus_unif.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Aina Niemetz, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_unif.h b/src/theory/quantifiers/sygus/sygus_unif.h index f6e85abcd..8201ead6e 100644 --- a/src/theory/quantifiers/sygus/sygus_unif.h +++ b/src/theory/quantifiers/sygus/sygus_unif.h @@ -2,9 +2,9 @@ /*! \file sygus_unif.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_unif_io.cpp b/src/theory/quantifiers/sygus/sygus_unif_io.cpp index 1fc7903fa..ce13b6744 100644 --- a/src/theory/quantifiers/sygus/sygus_unif_io.cpp +++ b/src/theory/quantifiers/sygus/sygus_unif_io.cpp @@ -2,9 +2,9 @@ /*! \file sygus_unif_io.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa, Aina Niemetz + ** Andrew Reynolds, Mathias Preiner, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_unif_io.h b/src/theory/quantifiers/sygus/sygus_unif_io.h index 06197ce66..055f77ea4 100644 --- a/src/theory/quantifiers/sygus/sygus_unif_io.h +++ b/src/theory/quantifiers/sygus/sygus_unif_io.h @@ -2,9 +2,9 @@ /*! \file sygus_unif_io.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Mathias Preiner, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_unif_rl.cpp b/src/theory/quantifiers/sygus/sygus_unif_rl.cpp index 1bdae0b20..9fb0702b1 100644 --- a/src/theory/quantifiers/sygus/sygus_unif_rl.cpp +++ b/src/theory/quantifiers/sygus/sygus_unif_rl.cpp @@ -2,9 +2,9 @@ /*! \file sygus_unif_rl.cpp ** \verbatim ** Top contributors (to current version): - ** Haniel Barbosa, Andrew Reynolds + ** Haniel Barbosa, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_unif_rl.h b/src/theory/quantifiers/sygus/sygus_unif_rl.h index 827919308..38122fc1b 100644 --- a/src/theory/quantifiers/sygus/sygus_unif_rl.h +++ b/src/theory/quantifiers/sygus/sygus_unif_rl.h @@ -2,9 +2,9 @@ /*! \file sygus_unif_rl.h ** \verbatim ** Top contributors (to current version): - ** Haniel Barbosa, Andrew Reynolds + ** Haniel Barbosa, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_unif_strat.cpp b/src/theory/quantifiers/sygus/sygus_unif_strat.cpp index c2448abb4..07e623b28 100644 --- a/src/theory/quantifiers/sygus/sygus_unif_strat.cpp +++ b/src/theory/quantifiers/sygus/sygus_unif_strat.cpp @@ -2,9 +2,9 @@ /*! \file sygus_unif_strat.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/sygus_unif_strat.h b/src/theory/quantifiers/sygus/sygus_unif_strat.h index e32fbe022..64e6e1f6b 100644 --- a/src/theory/quantifiers/sygus/sygus_unif_strat.h +++ b/src/theory/quantifiers/sygus/sygus_unif_strat.h @@ -2,9 +2,9 @@ /*! \file sygus_unif_strat.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa, Andres Noetzli + ** Andrew Reynolds, Haniel Barbosa, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/synth_conjecture.cpp b/src/theory/quantifiers/sygus/synth_conjecture.cpp index bb5307c79..7e6e74209 100644 --- a/src/theory/quantifiers/sygus/synth_conjecture.cpp +++ b/src/theory/quantifiers/sygus/synth_conjecture.cpp @@ -2,9 +2,9 @@ /*! \file synth_conjecture.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa, Tim King + ** Andrew Reynolds, Mathias Preiner, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -21,7 +21,7 @@ #include "printer/printer.h" #include "prop/prop_engine.h" #include "smt/smt_statistics_registry.h" -#include "theory/datatypes/theory_datatypes_utils.h" +#include "theory/datatypes/sygus_datatype_utils.h" #include "theory/quantifiers/first_order_model.h" #include "theory/quantifiers/instantiate.h" #include "theory/quantifiers/quantifiers_attributes.h" diff --git a/src/theory/quantifiers/sygus/synth_conjecture.h b/src/theory/quantifiers/sygus/synth_conjecture.h index 3faf944eb..d17a8cf11 100644 --- a/src/theory/quantifiers/sygus/synth_conjecture.h +++ b/src/theory/quantifiers/sygus/synth_conjecture.h @@ -2,9 +2,9 @@ /*! \file synth_conjecture.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Haniel Barbosa, Tim King + ** Andrew Reynolds, Mathias Preiner, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/synth_engine.cpp b/src/theory/quantifiers/sygus/synth_engine.cpp index b0a562b42..590fdaa56 100644 --- a/src/theory/quantifiers/sygus/synth_engine.cpp +++ b/src/theory/quantifiers/sygus/synth_engine.cpp @@ -2,9 +2,9 @@ /*! \file synth_engine.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Morgan Deters + ** Andrew Reynolds, Mathias Preiner, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -169,8 +169,9 @@ void SynthEngine::assignConjecture(Node q) if (!sip.isPurelySingleInvocation() && sip.isNonGroundSingleInvocation()) { // create new smt engine to do quantifier elimination - std::unique_ptr<SmtEngine> smt_qe; - initializeSubsolver(smt_qe); + std::unique_ptr<SmtEngine> smt_qe( + new SmtEngine(NodeManager::currentNM()->toExprManager())); + initializeSubsolver(smt_qe.get()); Trace("cegqi-qep") << "Property is non-ground single invocation, run " "QE to obtain single invocation." << std::endl; diff --git a/src/theory/quantifiers/sygus/synth_engine.h b/src/theory/quantifiers/sygus/synth_engine.h index 4b47235da..c5e97f4ea 100644 --- a/src/theory/quantifiers/sygus/synth_engine.h +++ b/src/theory/quantifiers/sygus/synth_engine.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/term_database_sygus.cpp b/src/theory/quantifiers/sygus/term_database_sygus.cpp index f53637ebb..ac1c7d342 100644 --- a/src/theory/quantifiers/sygus/term_database_sygus.cpp +++ b/src/theory/quantifiers/sygus/term_database_sygus.cpp @@ -2,9 +2,9 @@ /*! \file term_database_sygus.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli + ** Andrew Reynolds, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -21,7 +21,7 @@ #include "options/quantifiers_options.h" #include "printer/printer.h" #include "theory/arith/arith_msum.h" -#include "theory/datatypes/theory_datatypes_utils.h" +#include "theory/datatypes/sygus_datatype_utils.h" #include "theory/quantifiers/quantifiers_attributes.h" #include "theory/quantifiers/term_database.h" #include "theory/quantifiers/term_util.h" diff --git a/src/theory/quantifiers/sygus/term_database_sygus.h b/src/theory/quantifiers/sygus/term_database_sygus.h index acc875780..97cdc6ddd 100644 --- a/src/theory/quantifiers/sygus/term_database_sygus.h +++ b/src/theory/quantifiers/sygus/term_database_sygus.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Andres Noetzli, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/transition_inference.cpp b/src/theory/quantifiers/sygus/transition_inference.cpp index 97dd18492..afc223f26 100644 --- a/src/theory/quantifiers/sygus/transition_inference.cpp +++ b/src/theory/quantifiers/sygus/transition_inference.cpp @@ -2,9 +2,9 @@ /*! \file transition_inference.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/transition_inference.h b/src/theory/quantifiers/sygus/transition_inference.h index a6276e70d..5d6e16e81 100644 --- a/src/theory/quantifiers/sygus/transition_inference.h +++ b/src/theory/quantifiers/sygus/transition_inference.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/type_info.cpp b/src/theory/quantifiers/sygus/type_info.cpp index 7235fd65c..ba5b23866 100644 --- a/src/theory/quantifiers/sygus/type_info.cpp +++ b/src/theory/quantifiers/sygus/type_info.cpp @@ -2,9 +2,9 @@ /*! \file type_info.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -17,7 +17,7 @@ #include "base/check.h" #include "expr/dtype.h" #include "expr/sygus_datatype.h" -#include "theory/datatypes/theory_datatypes_utils.h" +#include "theory/datatypes/sygus_datatype_utils.h" #include "theory/quantifiers/sygus/term_database_sygus.h" using namespace CVC4::kind; diff --git a/src/theory/quantifiers/sygus/type_info.h b/src/theory/quantifiers/sygus/type_info.h index 9ac93f7ae..c2b122a15 100644 --- a/src/theory/quantifiers/sygus/type_info.h +++ b/src/theory/quantifiers/sygus/type_info.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/type_node_id_trie.cpp b/src/theory/quantifiers/sygus/type_node_id_trie.cpp index ffe2f533d..09bb51a2a 100644 --- a/src/theory/quantifiers/sygus/type_node_id_trie.cpp +++ b/src/theory/quantifiers/sygus/type_node_id_trie.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus/type_node_id_trie.h b/src/theory/quantifiers/sygus/type_node_id_trie.h index d0798c7a9..098acf1f3 100644 --- a/src/theory/quantifiers/sygus/type_node_id_trie.h +++ b/src/theory/quantifiers/sygus/type_node_id_trie.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus_inst.cpp b/src/theory/quantifiers/sygus_inst.cpp index 696860302..56fee3319 100644 --- a/src/theory/quantifiers/sygus_inst.cpp +++ b/src/theory/quantifiers/sygus_inst.cpp @@ -2,7 +2,7 @@ /*! \file sygus_inst.cpp ** \verbatim ** Top contributors (to current version): - ** Mathias Preiner + ** Mathias Preiner, Andrew Reynolds ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. @@ -18,7 +18,7 @@ #include <unordered_set> #include "expr/node_algorithm.h" -#include "theory/datatypes/theory_datatypes_utils.h" +#include "theory/datatypes/sygus_datatype_utils.h" #include "theory/quantifiers/sygus/sygus_enumerator.h" #include "theory/quantifiers/sygus/sygus_grammar_cons.h" #include "theory/quantifiers/sygus/synth_engine.h" diff --git a/src/theory/quantifiers/sygus_sampler.cpp b/src/theory/quantifiers/sygus_sampler.cpp index e9c858814..7ad2c54eb 100644 --- a/src/theory/quantifiers/sygus_sampler.cpp +++ b/src/theory/quantifiers/sygus_sampler.cpp @@ -2,9 +2,9 @@ /*! \file sygus_sampler.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli + ** Andrew Reynolds, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/sygus_sampler.h b/src/theory/quantifiers/sygus_sampler.h index 429b6f511..6a454cab3 100644 --- a/src/theory/quantifiers/sygus_sampler.h +++ b/src/theory/quantifiers/sygus_sampler.h @@ -2,9 +2,9 @@ /*! \file sygus_sampler.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, FabianWolff, Tim King + ** Andrew Reynolds, Mathias Preiner, Fabian Wolff ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp index 444d6f329..7caa103a0 100644 --- a/src/theory/quantifiers/term_database.cpp +++ b/src/theory/quantifiers/term_database.cpp @@ -2,9 +2,9 @@ /*! \file term_database.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Morgan Deters + ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h index 7caf29d20..a81cd2e05 100644 --- a/src/theory/quantifiers/term_database.h +++ b/src/theory/quantifiers/term_database.h @@ -2,9 +2,9 @@ /*! \file term_database.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/term_enumeration.cpp b/src/theory/quantifiers/term_enumeration.cpp index 0336700ad..30ee1c4a9 100644 --- a/src/theory/quantifiers/term_enumeration.cpp +++ b/src/theory/quantifiers/term_enumeration.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/term_enumeration.h b/src/theory/quantifiers/term_enumeration.h index 279680b1f..dd387ac4f 100644 --- a/src/theory/quantifiers/term_enumeration.h +++ b/src/theory/quantifiers/term_enumeration.h @@ -2,9 +2,9 @@ /*! \file term_enumeration.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/term_util.cpp b/src/theory/quantifiers/term_util.cpp index c8c72344f..f657062ed 100644 --- a/src/theory/quantifiers/term_util.cpp +++ b/src/theory/quantifiers/term_util.cpp @@ -2,9 +2,9 @@ /*! \file term_util.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Andres Noetzli + ** Andrew Reynolds, Morgan Deters, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/term_util.h b/src/theory/quantifiers/term_util.h index 315b4b1d0..c4e0a8586 100644 --- a/src/theory/quantifiers/term_util.h +++ b/src/theory/quantifiers/term_util.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/theory_quantifiers.cpp b/src/theory/quantifiers/theory_quantifiers.cpp index 9242bec7c..5a8cde21e 100644 --- a/src/theory/quantifiers/theory_quantifiers.cpp +++ b/src/theory/quantifiers/theory_quantifiers.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/theory_quantifiers.h b/src/theory/quantifiers/theory_quantifiers.h index 991a47ad0..0dab150ed 100644 --- a/src/theory/quantifiers/theory_quantifiers.h +++ b/src/theory/quantifiers/theory_quantifiers.h @@ -2,9 +2,9 @@ /*! \file theory_quantifiers.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andrew Reynolds + ** Tim King, Morgan Deters, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers/theory_quantifiers_type_rules.h b/src/theory/quantifiers/theory_quantifiers_type_rules.h index e2c9043a1..1fdef3359 100644 --- a/src/theory/quantifiers/theory_quantifiers_type_rules.h +++ b/src/theory/quantifiers/theory_quantifiers_type_rules.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp index ca4768ee4..6dce6ce1e 100644 --- a/src/theory/quantifiers_engine.cpp +++ b/src/theory/quantifiers_engine.cpp @@ -2,9 +2,9 @@ /*! \file quantifiers_engine.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -1091,13 +1091,6 @@ bool QuantifiersEngine::getInstWhenNeedsCheck( Theory::Effort e ) { { performCheck = true; } - if( e==Theory::EFFORT_LAST_CALL ){ - //with bounded integers, skip every other last call, - // since matching loops may occur with infinite quantification - if( d_ierCounter_lc%2==0 && options::fmfBound() ){ - performCheck = false; - } - } return performCheck; } diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h index 5d4ff6afe..a4d858b16 100644 --- a/src/theory/quantifiers_engine.h +++ b/src/theory/quantifiers_engine.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/rep_set.cpp b/src/theory/rep_set.cpp index 243846b33..7e2c47ba7 100644 --- a/src/theory/rep_set.cpp +++ b/src/theory/rep_set.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/rep_set.h b/src/theory/rep_set.h index 58f449202..55871e5ce 100644 --- a/src/theory/rep_set.h +++ b/src/theory/rep_set.h @@ -2,9 +2,9 @@ /*! \file rep_set.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Tim King + ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/rewriter.cpp b/src/theory/rewriter.cpp index ca552de66..07bc695ec 100644 --- a/src/theory/rewriter.cpp +++ b/src/theory/rewriter.cpp @@ -2,9 +2,9 @@ /*! \file rewriter.cpp ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Liana Hadarean, Morgan Deters + ** Dejan Jovanovic, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/rewriter.h b/src/theory/rewriter.h index 32a8005d1..e021ac9e7 100644 --- a/src/theory/rewriter.h +++ b/src/theory/rewriter.h @@ -2,9 +2,9 @@ /*! \file rewriter.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Tim King + ** Andres Noetzli, Dejan Jovanovic, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/rewriter_attributes.h b/src/theory/rewriter_attributes.h index 93120735e..1e5e882fe 100644 --- a/src/theory/rewriter_attributes.h +++ b/src/theory/rewriter_attributes.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/rewriter_tables_template.h b/src/theory/rewriter_tables_template.h index 9f6b07389..4ef96cc5e 100644 --- a/src/theory/rewriter_tables_template.h +++ b/src/theory/rewriter_tables_template.h @@ -2,9 +2,9 @@ /*! \file rewriter_tables_template.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Tim King, Liana Hadarean + ** Dejan Jovanovic, Tim King, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sep/theory_sep.cpp b/src/theory/sep/theory_sep.cpp index d90be94f9..4becfe731 100644 --- a/src/theory/sep/theory_sep.cpp +++ b/src/theory/sep/theory_sep.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Dejan Jovanovic, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sep/theory_sep.h b/src/theory/sep/theory_sep.h index ce1498f52..935170adf 100644 --- a/src/theory/sep/theory_sep.h +++ b/src/theory/sep/theory_sep.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sep/theory_sep_rewriter.cpp b/src/theory/sep/theory_sep_rewriter.cpp index 09429cb13..e993d05dd 100644 --- a/src/theory/sep/theory_sep_rewriter.cpp +++ b/src/theory/sep/theory_sep_rewriter.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sep/theory_sep_rewriter.h b/src/theory/sep/theory_sep_rewriter.h index 0d1de3463..99020ce41 100644 --- a/src/theory/sep/theory_sep_rewriter.h +++ b/src/theory/sep/theory_sep_rewriter.h @@ -2,9 +2,9 @@ /*! \file theory_sep_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andres Noetzli, Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sep/theory_sep_type_rules.h b/src/theory/sep/theory_sep_type_rules.h index 29adeda5a..2c1035834 100644 --- a/src/theory/sep/theory_sep_type_rules.h +++ b/src/theory/sep/theory_sep_type_rules.h @@ -2,9 +2,9 @@ /*! \file theory_sep_type_rules.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King + ** Andrew Reynolds, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/cardinality_extension.cpp b/src/theory/sets/cardinality_extension.cpp index f37e06918..dc3c77353 100644 --- a/src/theory/sets/cardinality_extension.cpp +++ b/src/theory/sets/cardinality_extension.cpp @@ -2,9 +2,9 @@ /*! \file cardinality_extension.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mudathir Mohamed, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/cardinality_extension.h b/src/theory/sets/cardinality_extension.h index 284cf37d0..570530108 100644 --- a/src/theory/sets/cardinality_extension.h +++ b/src/theory/sets/cardinality_extension.h @@ -2,9 +2,9 @@ /*! \file cardinality_extension.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mudathir Mohamed ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/inference_manager.cpp b/src/theory/sets/inference_manager.cpp index 595dd16c3..224eee57e 100644 --- a/src/theory/sets/inference_manager.cpp +++ b/src/theory/sets/inference_manager.cpp @@ -2,9 +2,9 @@ /*! \file inference_manager.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Paul Meng ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/inference_manager.h b/src/theory/sets/inference_manager.h index 29b0e2bca..2a5a7703c 100644 --- a/src/theory/sets/inference_manager.h +++ b/src/theory/sets/inference_manager.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/normal_form.h b/src/theory/sets/normal_form.h index c36692f00..56f09e2a5 100644 --- a/src/theory/sets/normal_form.h +++ b/src/theory/sets/normal_form.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Kshitij Bansal, Andrew Reynolds, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/rels_utils.h b/src/theory/sets/rels_utils.h index 79757d311..007b7ce80 100644 --- a/src/theory/sets/rels_utils.h +++ b/src/theory/sets/rels_utils.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/skolem_cache.cpp b/src/theory/sets/skolem_cache.cpp index a70e6dc51..cf5e8835a 100644 --- a/src/theory/sets/skolem_cache.cpp +++ b/src/theory/sets/skolem_cache.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/skolem_cache.h b/src/theory/sets/skolem_cache.h index f1f2a82c0..1a8d09c1a 100644 --- a/src/theory/sets/skolem_cache.h +++ b/src/theory/sets/skolem_cache.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/solver_state.cpp b/src/theory/sets/solver_state.cpp index 9e695bf56..057d3a791 100644 --- a/src/theory/sets/solver_state.cpp +++ b/src/theory/sets/solver_state.cpp @@ -2,9 +2,9 @@ /*! \file solver_state.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mudathir Mohamed ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/solver_state.h b/src/theory/sets/solver_state.h index b95081b69..0b301dbb7 100644 --- a/src/theory/sets/solver_state.h +++ b/src/theory/sets/solver_state.h @@ -2,9 +2,9 @@ /*! \file solver_state.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mudathir Mohamed ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/theory_sets.cpp b/src/theory/sets/theory_sets.cpp index b5c2590d5..7eea7926b 100644 --- a/src/theory/sets/theory_sets.cpp +++ b/src/theory/sets/theory_sets.cpp @@ -2,9 +2,9 @@ /*! \file theory_sets.cpp ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal, Andrew Reynolds, Tim King + ** Andrew Reynolds, Kshitij Bansal, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/theory_sets.h b/src/theory/sets/theory_sets.h index 1bb515cc6..2fd1c2145 100644 --- a/src/theory/sets/theory_sets.h +++ b/src/theory/sets/theory_sets.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Kshitij Bansal, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/theory_sets_private.cpp b/src/theory/sets/theory_sets_private.cpp index bbe46b2a6..83b5b1c25 100644 --- a/src/theory/sets/theory_sets_private.cpp +++ b/src/theory/sets/theory_sets_private.cpp @@ -2,9 +2,9 @@ /*! \file theory_sets_private.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Kshitij Bansal, Paul Meng + ** Andrew Reynolds, Mudathir Mohamed, Kshitij Bansal ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/theory_sets_private.h b/src/theory/sets/theory_sets_private.h index fc9650204..83c58f094 100644 --- a/src/theory/sets/theory_sets_private.h +++ b/src/theory/sets/theory_sets_private.h @@ -2,9 +2,9 @@ /*! \file theory_sets_private.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Kshitij Bansal, Paul Meng + ** Andrew Reynolds, Kshitij Bansal, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/theory_sets_rels.cpp b/src/theory/sets/theory_sets_rels.cpp index 2f0997982..f4b1d3be9 100644 --- a/src/theory/sets/theory_sets_rels.cpp +++ b/src/theory/sets/theory_sets_rels.cpp @@ -2,9 +2,9 @@ /*! \file theory_sets_rels.cpp ** \verbatim ** Top contributors (to current version): - ** Paul Meng, Andrew Reynolds, Tim King + ** Andrew Reynolds, Paul Meng, Piotr Trojanek ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/theory_sets_rels.h b/src/theory/sets/theory_sets_rels.h index 3a0458309..0d8ace50f 100644 --- a/src/theory/sets/theory_sets_rels.h +++ b/src/theory/sets/theory_sets_rels.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Paul Meng, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/theory_sets_rewriter.cpp b/src/theory/sets/theory_sets_rewriter.cpp index 114dfa9a6..c26a3852c 100644 --- a/src/theory/sets/theory_sets_rewriter.cpp +++ b/src/theory/sets/theory_sets_rewriter.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Kshitij Bansal, Paul Meng ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/theory_sets_rewriter.h b/src/theory/sets/theory_sets_rewriter.h index 3d96e4ece..7d1a6c188 100644 --- a/src/theory/sets/theory_sets_rewriter.h +++ b/src/theory/sets/theory_sets_rewriter.h @@ -2,9 +2,9 @@ /*! \file theory_sets_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal + ** Kshitij Bansal, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sets/theory_sets_type_enumerator.cpp b/src/theory/sets/theory_sets_type_enumerator.cpp index ded5975a5..5a949a95b 100644 --- a/src/theory/sets/theory_sets_type_enumerator.cpp +++ b/src/theory/sets/theory_sets_type_enumerator.cpp @@ -2,7 +2,7 @@ /*! \file theory_sets_type_enumerator.cpp ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal, Tim King, Andrew Reynolds, Mudathir Mahgoub + ** Mudathir Mohamed ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. diff --git a/src/theory/sets/theory_sets_type_enumerator.h b/src/theory/sets/theory_sets_type_enumerator.h index 306d96b52..fc6faa337 100644 --- a/src/theory/sets/theory_sets_type_enumerator.h +++ b/src/theory/sets/theory_sets_type_enumerator.h @@ -2,7 +2,7 @@ /*! \file theory_sets_type_enumerator.h ** \verbatim ** Top contributors (to current version): - ** Kshitij Bansal, Tim King, Andrew Reynolds, Mudathir Mahgoub + ** Mudathir Mohamed, Mathias Preiner, Tim King ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. diff --git a/src/theory/sets/theory_sets_type_rules.h b/src/theory/sets/theory_sets_type_rules.h index 9d2dd882f..753dcaf76 100644 --- a/src/theory/sets/theory_sets_type_rules.h +++ b/src/theory/sets/theory_sets_type_rules.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Kshitij Bansal, Andrew Reynolds, Paul Meng ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/shared_terms_database.cpp b/src/theory/shared_terms_database.cpp index a13ac207a..52ce34756 100644 --- a/src/theory/shared_terms_database.cpp +++ b/src/theory/shared_terms_database.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/shared_terms_database.h b/src/theory/shared_terms_database.h index 0c73195c5..0bfd8e094 100644 --- a/src/theory/shared_terms_database.h +++ b/src/theory/shared_terms_database.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Mathias Preiner, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/smt_engine_subsolver.cpp b/src/theory/smt_engine_subsolver.cpp index 6b856462a..f529d3fea 100644 --- a/src/theory/smt_engine_subsolver.cpp +++ b/src/theory/smt_engine_subsolver.cpp @@ -2,9 +2,9 @@ /*! \file smt_engine_subsolver.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli + ** Andrew Reynolds, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -15,6 +15,7 @@ #include "theory/smt_engine_subsolver.h" +#include "api/cvc4cpp.h" #include "smt/smt_engine.h" #include "smt/smt_engine_scope.h" #include "theory/rewriter.h" @@ -40,16 +41,14 @@ Result quickCheck(Node& query) return Result(Result::SAT_UNKNOWN, Result::REQUIRES_FULL_CHECK); } -void initializeSubsolver(std::unique_ptr<SmtEngine>& smte) +void initializeSubsolver(SmtEngine* smte) { - NodeManager* nm = NodeManager::currentNM(); - smte.reset(new SmtEngine(nm->toExprManager())); smte->setIsInternalSubsolver(); smte->setLogic(smt::currentSmtEngine()->getLogicInfo()); } -void initializeSubsolverWithExport(std::unique_ptr<SmtEngine>& smte, - ExprManager& em, +void initializeSubsolverWithExport(SmtEngine* smte, + ExprManager* em, ExprManagerMapCollection& varMap, Node query, bool needsTimeout, @@ -62,14 +61,13 @@ void initializeSubsolverWithExport(std::unique_ptr<SmtEngine>& smte, // OptionException. try { - smte.reset(new SmtEngine(&em)); smte->setIsInternalSubsolver(); if (needsTimeout) { smte->setTimeLimit(timeout, true); } smte->setLogic(smt::currentSmtEngine()->getLogicInfo()); - Expr equery = query.toExpr().exportTo(&em, varMap); + Expr equery = query.toExpr().exportTo(em, varMap); smte->assertFormula(equery); } catch (const CVC4::ExportUnsupportedException& e) @@ -82,13 +80,13 @@ void initializeSubsolverWithExport(std::unique_ptr<SmtEngine>& smte, } } -void initializeSubsolver(std::unique_ptr<SmtEngine>& smte, Node query) +void initializeSubsolver(SmtEngine* smte, Node query) { initializeSubsolver(smte); smte->assertFormula(query.toExpr()); } -Result checkWithSubsolver(std::unique_ptr<SmtEngine>& smte, Node query) +Result checkWithSubsolver(SmtEngine* smte, Node query) { Assert(query.getType().isBoolean()); Result r = quickCheck(query); @@ -130,19 +128,33 @@ Result checkWithSubsolver(Node query, } return r; } - std::unique_ptr<SmtEngine> smte; + + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // This is only temporarily until we have separate options for each + // SmtEngine instance. We should reuse the same ExprManager with + // a different SmtEngine (and different options) here, eventually. + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + std::unique_ptr<SmtEngine> simpleSmte; + std::unique_ptr<api::Solver> slv; + ExprManager* em = nullptr; + SmtEngine* smte = nullptr; ExprManagerMapCollection varMap; NodeManager* nm = NodeManager::currentNM(); - ExprManager em(nm->getOptions()); bool needsExport = false; if (needsTimeout) { + slv.reset(new api::Solver(&nm->getOptions())); + em = slv->getExprManager(); + smte = slv->getSmtEngine(); needsExport = true; initializeSubsolverWithExport( smte, em, varMap, query, needsTimeout, timeout); } else { + em = nm->toExprManager(); + simpleSmte.reset(new SmtEngine(em)); + smte = simpleSmte.get(); initializeSubsolver(smte, query); } r = smte->checkSat(); @@ -153,7 +165,7 @@ Result checkWithSubsolver(Node query, Expr val; if (needsExport) { - Expr ev = v.toExpr().exportTo(&em, varMap); + Expr ev = v.toExpr().exportTo(em, varMap); val = smte->getValue(ev).exportTo(nm->toExprManager(), varMap); } else diff --git a/src/theory/smt_engine_subsolver.h b/src/theory/smt_engine_subsolver.h index a1fc67385..b606657bb 100644 --- a/src/theory/smt_engine_subsolver.h +++ b/src/theory/smt_engine_subsolver.h @@ -2,9 +2,9 @@ /*! \file smt_engine_subsolver.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Haniel Barbosa ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -34,7 +34,7 @@ namespace theory { * This function initializes the smt engine smte as a subsolver, e.g. it * creates a new SMT engine and sets the options of the current SMT engine. */ -void initializeSubsolver(std::unique_ptr<SmtEngine>& smte); +void initializeSubsolver(SmtEngine* smte); /** * Initialize Smt subsolver with exporting @@ -52,14 +52,14 @@ void initializeSubsolver(std::unique_ptr<SmtEngine>& smte); * manager. * * @param smte The smt engine pointer to initialize - * @param em Reference to the expression manager to use + * @param em Reference to the expression manager used by smte * @param varMap Map used for exporting expressions * @param query The query to check * @param needsTimeout Whether we would like to set a timeout * @param timeout The timeout (in milliseconds) */ -void initializeSubsolverWithExport(std::unique_ptr<SmtEngine>& smte, - ExprManager& em, +void initializeSubsolverWithExport(SmtEngine* smte, + ExprManager* em, ExprManagerMapCollection& varMap, Node query, bool needsTimeout = false, @@ -73,7 +73,7 @@ void initializeSubsolverWithExport(std::unique_ptr<SmtEngine>& smte, * exporting since the Options and ExprManager are tied together. * TODO: eliminate this dependency (cvc4-projects #120). */ -void initializeSubsolver(std::unique_ptr<SmtEngine>& smte, Node query); +void initializeSubsolver(SmtEngine* smte, Node query); /** * This returns the result of checking the satisfiability of formula query. @@ -81,7 +81,7 @@ void initializeSubsolver(std::unique_ptr<SmtEngine>& smte, Node query); * If necessary, smte is initialized to the SMT engine that checked its * satisfiability. */ -Result checkWithSubsolver(std::unique_ptr<SmtEngine>& smte, Node query); +Result checkWithSubsolver(SmtEngine* smte, Node query); /** * This returns the result of checking the satisfiability of formula query. diff --git a/src/theory/sort_inference.cpp b/src/theory/sort_inference.cpp index 42364f080..144f5b54d 100644 --- a/src/theory/sort_inference.cpp +++ b/src/theory/sort_inference.cpp @@ -2,9 +2,9 @@ /*! \file sort_inference.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Paul Meng, Kshitij Bansal + ** Andrew Reynolds, Paul Meng, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/sort_inference.h b/src/theory/sort_inference.h index ecf86376c..07a0901f0 100644 --- a/src/theory/sort_inference.h +++ b/src/theory/sort_inference.h @@ -2,9 +2,9 @@ /*! \file sort_inference.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Paul Meng + ** Andrew Reynolds, Paul Meng, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/arith_entail.cpp b/src/theory/strings/arith_entail.cpp index 71680264d..adcbe590e 100644 --- a/src/theory/strings/arith_entail.cpp +++ b/src/theory/strings/arith_entail.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/arith_entail.h b/src/theory/strings/arith_entail.h index 266f726c7..e3dd7e2e5 100644 --- a/src/theory/strings/arith_entail.h +++ b/src/theory/strings/arith_entail.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/base_solver.cpp b/src/theory/strings/base_solver.cpp index 16c83de78..952f26691 100644 --- a/src/theory/strings/base_solver.cpp +++ b/src/theory/strings/base_solver.cpp @@ -2,9 +2,9 @@ /*! \file base_solver.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -15,6 +15,7 @@ #include "theory/strings/base_solver.h" +#include "expr/sequence.h" #include "options/strings_options.h" #include "theory/strings/theory_strings_utils.h" #include "theory/strings/word.h" @@ -27,11 +28,8 @@ namespace CVC4 { namespace theory { namespace strings { -BaseSolver::BaseSolver(context::Context* c, - context::UserContext* u, - SolverState& s, - InferenceManager& im) - : d_state(s), d_im(im), d_congruent(c) +BaseSolver::BaseSolver(SolverState& s, InferenceManager& im) + : d_state(s), d_im(im), d_congruent(s.getSatContext()) { d_false = NodeManager::currentNM()->mkConst(false); d_cardSize = utils::getAlphabetCardinality(); @@ -57,7 +55,7 @@ void BaseSolver::checkInit() if (!tn.isRegExp()) { Node emps; - if (tn.isString()) + if (tn.isStringLike()) { d_stringsEqc.push_back(eqc); emps = Word::mkEmptyWord(tn); @@ -67,19 +65,75 @@ void BaseSolver::checkInit() while (!eqc_i.isFinished()) { Node n = *eqc_i; - if (n.isConst()) + Kind k = n.getKind(); + // process constant-like terms + if (utils::isConstantLike(n)) { - d_eqcInfo[eqc].d_bestContent = n; - d_eqcInfo[eqc].d_base = n; - d_eqcInfo[eqc].d_exp = Node::null(); + Node prev = d_eqcInfo[eqc].d_bestContent; + if (!prev.isNull()) + { + // we have either (seq.unit x) = C, or (seq.unit x) = (seq.unit y) + // where C is a sequence constant. + Node cval = + prev.isConst() ? prev : (n.isConst() ? n : Node::null()); + std::vector<Node> exp; + exp.push_back(prev.eqNode(n)); + Node s, t; + if (cval.isNull()) + { + // injectivity of seq.unit + s = prev[0]; + t = n[0]; + } + else + { + // should not have two constants in the same equivalence class + Assert(cval.getType().isSequence()); + std::vector<Node> cchars = Word::getChars(cval); + if (cchars.size() == 1) + { + Node oval = prev.isConst() ? n : prev; + Assert(oval.getKind() == SEQ_UNIT); + s = oval[0]; + t = cchars[0] + .getConst<ExprSequence>() + .getSequence() + .getVec()[0]; + // oval is congruent (ignored) in this context + d_congruent.insert(oval); + } + else + { + // (seq.unit x) = C => false if |C| != 1. + d_im.sendInference( + exp, d_false, Inference::UNIT_CONST_CONFLICT); + return; + } + } + if (!d_state.areEqual(s, t)) + { + // (seq.unit x) = (seq.unit y) => x=y, or + // (seq.unit x) = (seq.unit c) => x=c + Assert(s.getType() == t.getType()); + d_im.sendInference(exp, s.eqNode(t), Inference::UNIT_INJ); + } + } + // update best content + if (prev.isNull() || n.isConst()) + { + d_eqcInfo[eqc].d_bestContent = n; + d_eqcInfo[eqc].d_bestScore = 0; + d_eqcInfo[eqc].d_base = n; + d_eqcInfo[eqc].d_exp = Node::null(); + } } - else if (tn.isInteger()) + if (tn.isInteger()) { // do nothing } + // process indexing else if (n.getNumChildren() > 0) { - Kind k = n.getKind(); if (k != EQUAL) { if (d_congruent.find(n) == d_congruent.end()) @@ -90,7 +144,7 @@ void BaseSolver::checkInit() { // check if we have inferred a new equality by removal of empty // components - if (n.getKind() == STRING_CONCAT && !d_state.areEqual(nc, n)) + if (k == STRING_CONCAT && !d_state.areEqual(nc, n)) { std::vector<Node> exp; size_t count[2] = {0, 0}; @@ -191,7 +245,7 @@ void BaseSolver::checkInit() } } } - else + else if (!n.isConst()) { if (d_congruent.find(n) == d_congruent.end()) { @@ -323,8 +377,10 @@ void BaseSolver::checkConstantEquivalenceClasses(TermIndex* ti, Node nrr = d_state.getRepresentative(n[count]); Assert(!d_eqcInfo[nrr].d_bestContent.isNull() && d_eqcInfo[nrr].d_bestContent.isConst()); + // must flatten to avoid nested AND in explanations + utils::flattenOp(AND, d_eqcInfo[nrr].d_exp, exp); + // now explain equality to base d_im.addToExplanation(n[count], d_eqcInfo[nrr].d_base, exp); - exp.push_back(d_eqcInfo[nrr].d_exp); } else { @@ -352,10 +408,15 @@ void BaseSolver::checkConstantEquivalenceClasses(TermIndex* ti, Node nct = utils::mkNConcat(vecnc, n.getType()); Assert(!nct.isConst()); bei.d_bestContent = nct; + bei.d_bestScore = contentSize; bei.d_base = n; - bei.d_exp = utils::mkAnd(exp); + if (!exp.empty()) + { + bei.d_exp = utils::mkAnd(exp); + } Trace("strings-debug") - << "Set eqc best content " << n << " to " << nct << std::endl; + << "Set eqc best content " << n << " to " << nct + << ", explanation = " << bei.d_exp << std::endl; } } } @@ -370,11 +431,12 @@ void BaseSolver::checkConstantEquivalenceClasses(TermIndex* ti, BaseEqcInfo& bei = d_eqcInfo[nr]; if (!bei.d_bestContent.isConst()) { - Trace("strings-debug") - << "Set eqc const " << n << " to " << c << std::endl; bei.d_bestContent = c; bei.d_base = n; bei.d_exp = utils::mkAnd(exp); + Trace("strings-debug") + << "Set eqc const " << n << " to " << c + << ", explanation = " << bei.d_exp << std::endl; } else if (c != bei.d_bestContent) { @@ -432,11 +494,39 @@ void BaseSolver::checkCardinality() // are pairwise propagated to be equal. We do not require disequalities // between the lengths of each collection, since we split on disequalities // between lengths of string terms that are disequal (DEQ-LENGTH-SP). - std::vector<std::vector<Node> > cols; - std::vector<Node> lts; + std::map<TypeNode, std::vector<std::vector<Node> > > cols; + std::map<TypeNode, std::vector<Node> > lts; d_state.separateByLength(d_stringsEqc, cols, lts); + for (std::pair<const TypeNode, std::vector<std::vector<Node> > >& c : cols) + { + checkCardinalityType(c.first, c.second, lts[c.first]); + } +} + +void BaseSolver::checkCardinalityType(TypeNode tn, + std::vector<std::vector<Node> >& cols, + std::vector<Node>& lts) +{ + Trace("strings-card") << "Check cardinality (type " << tn << ")..." + << std::endl; NodeManager* nm = NodeManager::currentNM(); - Trace("strings-card") << "Check cardinality...." << std::endl; + uint32_t typeCardSize; + if (tn.isString()) // string-only + { + typeCardSize = d_cardSize; + } + else + { + Assert(tn.isSequence()); + TypeNode etn = tn.getSequenceElementType(); + if (etn.isInterpretedFinite()) + { + // infinite cardinality, we are fine + return; + } + // TODO (cvc4-projects #23): how to handle sequence for finite types? + return; + } // for each collection for (unsigned i = 0, csize = cols.size(); i < csize; ++i) { @@ -451,15 +541,15 @@ void BaseSolver::checkCardinality() // size > c^k unsigned card_need = 1; double curr = static_cast<double>(cols[i].size()); - while (curr > d_cardSize) + while (curr > typeCardSize) { - curr = curr / static_cast<double>(d_cardSize); + curr = curr / static_cast<double>(typeCardSize); card_need++; } Trace("strings-card") << "Need length " << card_need - << " for this number of strings (where alphabet size is " << d_cardSize - << ")." << std::endl; + << " for this number of strings (where alphabet size is " + << typeCardSize << ") given type " << tn << "." << std::endl; // check if we need to split bool needsSplit = true; if (lr.isConst()) @@ -472,8 +562,10 @@ void BaseSolver::checkCardinality() else { // find the minimimum constant that we are unknown to be disequal from, or - // otherwise stop if we increment such that cardinality does not apply - unsigned r = 0; + // otherwise stop if we increment such that cardinality does not apply. + // We always start with r=1 since by the invariants of our term registry, + // a term is either equal to the empty string, or has length >= 1. + unsigned r = 1; bool success = true; while (r < card_need && success) { @@ -530,8 +622,8 @@ void BaseSolver::checkCardinality() Node k_node = nm->mkConst(Rational(int_k)); // add cardinality lemma Node dist = nm->mkNode(DISTINCT, cols[i]); - std::vector<Node> vec_node; - vec_node.push_back(dist); + std::vector<Node> expn; + expn.push_back(dist); for (std::vector<Node>::iterator itr1 = cols[i].begin(); itr1 != cols[i].end(); ++itr1) @@ -540,7 +632,7 @@ void BaseSolver::checkCardinality() if (len != lr) { Node len_eq_lr = len.eqNode(lr); - vec_node.push_back(len_eq_lr); + expn.push_back(len_eq_lr); } } Node len = nm->mkNode(STRING_LENGTH, cols[i][0]); @@ -551,7 +643,7 @@ void BaseSolver::checkCardinality() { std::vector<Node> emptyVec; d_im.sendInference( - emptyVec, vec_node, cons, Inference::CARDINALITY, true); + emptyVec, expn, cons, Inference::CARDINALITY, true); return; } } diff --git a/src/theory/strings/base_solver.h b/src/theory/strings/base_solver.h index 1960b8352..5dcb75560 100644 --- a/src/theory/strings/base_solver.h +++ b/src/theory/strings/base_solver.h @@ -2,9 +2,9 @@ /*! \file base_solver.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -41,10 +41,7 @@ class BaseSolver using NodeSet = context::CDHashSet<Node, NodeHashFunction>; public: - BaseSolver(context::Context* c, - context::UserContext* u, - SolverState& s, - InferenceManager& im); + BaseSolver(SolverState& s, InferenceManager& im); ~BaseSolver(); //-----------------------inference steps @@ -200,6 +197,19 @@ class BaseSolver std::vector<Node>& vecc, bool ensureConst = true, bool isConst = true); + /** + * Check cardinality for type tn. This adds a lemma corresponding to + * cardinality for terms of type tn, if applicable. + * + * @param tn The string-like type of terms we are considering, + * @param cols The list of collections of equivalence classes. This is a + * partition of all string equivalence classes, grouped by those with equal + * lengths. + * @param lts The length of each of the collections in cols. + */ + void checkCardinalityType(TypeNode tn, + std::vector<std::vector<Node> >& cols, + std::vector<Node>& lts); /** The solver state object */ SolverState& d_state; /** The (custom) output channel of the theory of strings */ diff --git a/src/theory/strings/core_solver.cpp b/src/theory/strings/core_solver.cpp index 604abb1d7..a38d16279 100644 --- a/src/theory/strings/core_solver.cpp +++ b/src/theory/strings/core_solver.cpp @@ -1,10 +1,10 @@ /********************* */ -/*! \file theory_strings.cpp +/*! \file core_solver.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tianyi Liang, Morgan Deters + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -707,15 +707,17 @@ void CoreSolver::getNormalForms(Node eqc, while( !eqc_i.isFinished() ){ Node n = (*eqc_i); if( !d_bsolver.isCongruent(n) ){ - if (n.isConst() || n.getKind() == STRING_CONCAT) + Kind nk = n.getKind(); + bool isCLike = utils::isConstantLike(n); + if (isCLike || nk == STRING_CONCAT) { Trace("strings-process-debug") << "Get Normal Form : Process term " << n << " in eqc " << eqc << std::endl; NormalForm nf_curr; - if (n.isConst()) + if (isCLike) { nf_curr.init(n); } - else if (n.getKind() == STRING_CONCAT) + else if (nk == STRING_CONCAT) { // set the base to n, we construct the other portions of nf_curr in // the following. @@ -791,7 +793,8 @@ void CoreSolver::getNormalForms(Node eqc, } //if not equal to self std::vector<Node>& currv = nf_curr.d_nf; - if (currv.size() > 1 || (currv.size() == 1 && currv[0].isConst())) + if (currv.size() > 1 + || (currv.size() == 1 && utils::isConstantLike(currv[0]))) { // if in a build with assertions, check that normal form is acyclic if (Configuration::isAssertionBuild()) @@ -2239,8 +2242,6 @@ bool CoreSolver::isNormalFormPair( Node n1, Node n2 ) { void CoreSolver::checkNormalFormsDeq() { eq::EqualityEngine* ee = d_state.getEqualityEngine(); - std::vector< std::vector< Node > > cols; - std::vector< Node > lts; std::map< Node, std::map< Node, bool > > processed; const context::CDList<Node>& deqs = d_state.getDisequalityList(); @@ -2270,9 +2271,18 @@ void CoreSolver::checkNormalFormsDeq() } } - if (!d_im.hasProcessed()) + if (d_im.hasProcessed()) { - d_state.separateByLength(d_strings_eqc, cols, lts); + // added splitting lemma above + return; + } + // otherwise, look at pairs of equivalence classes with equal lengths + std::map<TypeNode, std::vector<std::vector<Node> > > colsT; + std::map<TypeNode, std::vector<Node> > ltsT; + d_state.separateByLength(d_strings_eqc, colsT, ltsT); + for (std::pair<const TypeNode, std::vector<std::vector<Node> > >& ct : colsT) + { + std::vector<std::vector<Node> >& cols = ct.second; for( unsigned i=0; i<cols.size(); i++ ){ if (cols[i].size() > 1 && !d_im.hasPendingLemma()) { diff --git a/src/theory/strings/core_solver.h b/src/theory/strings/core_solver.h index 029f1c850..db1f5ecf6 100644 --- a/src/theory/strings/core_solver.h +++ b/src/theory/strings/core_solver.h @@ -1,10 +1,10 @@ /********************* */ -/*! \file theory_strings.h +/*! \file core_solver.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/eqc_info.cpp b/src/theory/strings/eqc_info.cpp index 3c0dbc2a7..31d7f8b01 100644 --- a/src/theory/strings/eqc_info.cpp +++ b/src/theory/strings/eqc_info.cpp @@ -2,9 +2,9 @@ /*! \file eqc_info.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/eqc_info.h b/src/theory/strings/eqc_info.h index 241b7d523..108264969 100644 --- a/src/theory/strings/eqc_info.h +++ b/src/theory/strings/eqc_info.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/extf_solver.cpp b/src/theory/strings/extf_solver.cpp index dd4144313..4ee2f4919 100644 --- a/src/theory/strings/extf_solver.cpp +++ b/src/theory/strings/extf_solver.cpp @@ -1,10 +1,10 @@ /********************* */ -/*! \file ext_solver.cpp +/*! \file extf_solver.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -56,6 +56,8 @@ ExtfSolver::ExtfSolver(context::Context* c, d_extt.addFunctionKind(kind::STRING_STOI); d_extt.addFunctionKind(kind::STRING_STRREPL); d_extt.addFunctionKind(kind::STRING_STRREPLALL); + d_extt.addFunctionKind(kind::STRING_REPLACE_RE); + d_extt.addFunctionKind(kind::STRING_REPLACE_RE_ALL); d_extt.addFunctionKind(kind::STRING_STRCTN); d_extt.addFunctionKind(kind::STRING_IN_REGEXP); d_extt.addFunctionKind(kind::STRING_LEQ); @@ -63,6 +65,7 @@ ExtfSolver::ExtfSolver(context::Context* c, d_extt.addFunctionKind(kind::STRING_TOLOWER); d_extt.addFunctionKind(kind::STRING_TOUPPER); d_extt.addFunctionKind(kind::STRING_REV); + d_extt.addFunctionKind(kind::SEQ_UNIT); d_true = NodeManager::currentNM()->mkConst(true); d_false = NodeManager::currentNM()->mkConst(false); @@ -136,16 +139,18 @@ bool ExtfSolver::doReduction(int effort, Node n) } } } - else + else if (k == STRING_SUBSTR) { - if (k == STRING_SUBSTR) - { - r_effort = 1; - } - else if (k != STRING_IN_REGEXP) - { - r_effort = 2; - } + r_effort = 1; + } + else if (k == SEQ_UNIT) + { + // never necessary to reduce seq.unit + return false; + } + else if (k != STRING_IN_REGEXP) + { + r_effort = 2; } if (effort != r_effort) { @@ -180,8 +185,9 @@ bool ExtfSolver::doReduction(int effort, Node n) NodeManager* nm = NodeManager::currentNM(); Assert(k == STRING_SUBSTR || k == STRING_STRCTN || k == STRING_STRIDOF || k == STRING_ITOS || k == STRING_STOI || k == STRING_STRREPL - || k == STRING_STRREPLALL || k == STRING_LEQ || k == STRING_TOLOWER - || k == STRING_TOUPPER || k == STRING_REV); + || k == STRING_STRREPLALL || k == STRING_REPLACE_RE + || k == STRING_REPLACE_RE_ALL || k == STRING_LEQ + || k == STRING_TOLOWER || k == STRING_TOUPPER || k == STRING_REV); std::vector<Node> new_nodes; Node res = d_preproc.simplify(n, new_nodes); Assert(res != n); diff --git a/src/theory/strings/extf_solver.h b/src/theory/strings/extf_solver.h index fb9b836db..d99a881f6 100644 --- a/src/theory/strings/extf_solver.h +++ b/src/theory/strings/extf_solver.h @@ -1,10 +1,10 @@ /********************* */ -/*! \file ext_solver.h +/*! \file extf_solver.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/infer_info.cpp b/src/theory/strings/infer_info.cpp index e26a49e4e..c75e03440 100644 --- a/src/theory/strings/infer_info.cpp +++ b/src/theory/strings/infer_info.cpp @@ -2,9 +2,9 @@ /*! \file infer_info.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -26,6 +26,8 @@ const char* toString(Inference i) case Inference::I_CONST_MERGE: return "I_CONST_MERGE"; case Inference::I_CONST_CONFLICT: return "I_CONST_CONFLICT"; case Inference::I_NORM: return "I_NORM"; + case Inference::UNIT_INJ: return "UNIT_INJ"; + case Inference::UNIT_CONST_CONFLICT: return "UNIT_CONST_CONFLICT"; case Inference::CARD_SP: return "CARD_SP"; case Inference::CARDINALITY: return "CARDINALITY"; case Inference::I_CYCLE_E: return "I_CYCLE_E"; diff --git a/src/theory/strings/infer_info.h b/src/theory/strings/infer_info.h index 5aecf52cb..2a42b9fab 100644 --- a/src/theory/strings/infer_info.h +++ b/src/theory/strings/infer_info.h @@ -2,9 +2,9 @@ /*! \file infer_info.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -59,6 +59,10 @@ enum class Inference : uint32_t // equal after e.g. removing strings that are currently empty. For example: // y = "" ^ z = "" => x ++ y = z ++ x I_NORM, + // injectivity of seq.unit + UNIT_INJ, + // unit constant conflict + UNIT_CONST_CONFLICT, // A split due to cardinality CARD_SP, // The cardinality inference for strings, see Liang et al CAV 2014. diff --git a/src/theory/strings/inference_manager.cpp b/src/theory/strings/inference_manager.cpp index 9fb1011ee..91af2a434 100644 --- a/src/theory/strings/inference_manager.cpp +++ b/src/theory/strings/inference_manager.cpp @@ -2,9 +2,9 @@ /*! \file inference_manager.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/inference_manager.h b/src/theory/strings/inference_manager.h index cebd88a7f..4e50a6cb7 100644 --- a/src/theory/strings/inference_manager.h +++ b/src/theory/strings/inference_manager.h @@ -2,9 +2,9 @@ /*! \file inference_manager.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/kinds b/src/theory/strings/kinds index 27ffe5d26..96ba82a44 100644 --- a/src/theory/strings/kinds +++ b/src/theory/strings/kinds @@ -23,6 +23,10 @@ operator STRING_LEQ 2 "string less than or equal" operator STRING_STRIDOF 3 "string indexof" operator STRING_STRREPL 3 "string replace" operator STRING_STRREPLALL 3 "string replace all" +operator STRING_REPLACE_RE 3 "string replace regular expression match" +operator STRING_REPLACE_RE_ALL 3 "string replace all regular expression matches" +typerule STRING_REPLACE_RE "SimpleTypeRule<RString, AString, ARegExp, AString>" +typerule STRING_REPLACE_RE_ALL "SimpleTypeRule<RString, AString, ARegExp, AString>" operator STRING_PREFIX 2 "string prefixof" operator STRING_SUFFIX 2 "string suffixof" operator STRING_IS_DIGIT 1 "string isdigit, returns true if argument is a string of length one that represents a digit" @@ -58,12 +62,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" @@ -144,4 +163,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/normal_form.cpp b/src/theory/strings/normal_form.cpp index 05be5f12a..2466b6d21 100644 --- a/src/theory/strings/normal_form.cpp +++ b/src/theory/strings/normal_form.cpp @@ -2,9 +2,9 @@ /*! \file normal_form.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/normal_form.h b/src/theory/strings/normal_form.h index 35a7fadb3..bd60b0252 100644 --- a/src/theory/strings/normal_form.h +++ b/src/theory/strings/normal_form.h @@ -2,9 +2,9 @@ /*! \file normal_form.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/regexp_elim.cpp b/src/theory/strings/regexp_elim.cpp index d4f301e23..37920d248 100644 --- a/src/theory/strings/regexp_elim.cpp +++ b/src/theory/strings/regexp_elim.cpp @@ -2,9 +2,9 @@ /*! \file regexp_elim.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tianyi Liang + ** Andrew Reynolds, Tianyi Liang, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -27,10 +27,6 @@ using namespace CVC4::theory::strings; RegExpElimination::RegExpElimination() { - d_zero = NodeManager::currentNM()->mkConst(Rational(0)); - d_one = NodeManager::currentNM()->mkConst(Rational(1)); - d_neg_one = NodeManager::currentNM()->mkConst(Rational(-1)); - d_regExpType = NodeManager::currentNM()->regExpType(); } Node RegExpElimination::eliminate(Node atom) @@ -53,6 +49,7 @@ Node RegExpElimination::eliminateConcat(Node atom) Node x = atom[0]; Node lenx = nm->mkNode(STRING_LENGTH, x); Node re = atom[1]; + Node zero = nm->mkConst(Rational(0)); std::vector<Node> children; utils::getConcat(re, children); @@ -80,7 +77,7 @@ Node RegExpElimination::eliminateConcat(Node atom) hasPivotIndex = true; pivotIndex = i; // set to zero for the sum below - fl = d_zero; + fl = zero; } else { @@ -100,7 +97,7 @@ Node RegExpElimination::eliminateConcat(Node atom) Node sum = nm->mkNode(PLUS, childLengths); std::vector<Node> conc; conc.push_back(nm->mkNode(hasPivotIndex ? GEQ : EQUAL, lenx, sum)); - Node currEnd = d_zero; + Node currEnd = zero; for (unsigned i = 0, size = childLengths.size(); i < size; i++) { if (hasPivotIndex && i == pivotIndex) @@ -190,7 +187,7 @@ Node RegExpElimination::eliminateConcat(Node atom) // set of string terms are found, in order, in string x. // prev_end stores the current (symbolic) index in x that we are // searching. - Node prev_end = d_zero; + Node prev_end = zero; // the symbolic index we start searching, for each child in sep_children. std::vector<Node> prev_ends; unsigned gap_minsize_end = gap_minsize.back(); @@ -232,7 +229,7 @@ Node RegExpElimination::eliminateConcat(Node atom) prev_end = nm->mkNode(PLUS, prev_end, k); } Node curr = nm->mkNode(STRING_STRIDOF, x, sc, prev_end); - Node idofFind = curr.eqNode(d_neg_one).negate(); + Node idofFind = curr.eqNode(nm->mkConst(Rational(-1))).negate(); conj.push_back(idofFind); prev_end = nm->mkNode(PLUS, curr, lensc); } @@ -308,7 +305,7 @@ Node RegExpElimination::eliminateConcat(Node atom) for (const Node& v : non_greedy_find_vars) { Node bound = nm->mkNode( - AND, nm->mkNode(LEQ, d_zero, v), nm->mkNode(LT, v, lenx)); + AND, nm->mkNode(LEQ, zero, v), nm->mkNode(LT, v, lenx)); children2.push_back(bound); } children2.push_back(res); @@ -341,7 +338,7 @@ Node RegExpElimination::eliminateConcat(Node atom) // if the first or last child is constant string, we can split the membership // into a conjunction of two memberships. - Node sStartIndex = d_zero; + Node sStartIndex = zero; Node sLength = lenx; std::vector<Node> sConstraints; std::vector<Node> rexpElimChildren; @@ -356,7 +353,7 @@ Node RegExpElimination::eliminateConcat(Node atom) Assert(children[index + (r == 0 ? 1 : -1)].getKind() != STRING_TO_REGEXP); Node s = c[0]; Node lens = nm->mkNode(STRING_LENGTH, s); - Node sss = r == 0 ? d_zero : nm->mkNode(MINUS, lenx, lens); + Node sss = r == 0 ? zero : nm->mkNode(MINUS, lenx, lens); Node ss = nm->mkNode(STRING_SUBSTR, x, sss, lens); sConstraints.push_back(ss.eqNode(s)); if (r == 0) @@ -383,7 +380,7 @@ Node RegExpElimination::eliminateConcat(Node atom) Assert(rexpElimChildren.size() + sConstraints.size() == nchildren); Node ss = nm->mkNode(STRING_SUBSTR, x, sStartIndex, sLength); Assert(!rexpElimChildren.empty()); - Node regElim = utils::mkConcat(rexpElimChildren, d_regExpType); + Node regElim = utils::mkConcat(rexpElimChildren, nm->regExpType()); sConstraints.push_back(nm->mkNode(STRING_IN_REGEXP, ss, regElim)); Node ret = nm->mkNode(AND, sConstraints); // e.g. @@ -402,7 +399,7 @@ Node RegExpElimination::eliminateConcat(Node atom) std::vector<Node> echildren; if (i == 0) { - k = d_zero; + k = zero; } else if (i + 1 == nchildren) { @@ -413,7 +410,7 @@ Node RegExpElimination::eliminateConcat(Node atom) k = nm->mkBoundVar(nm->integerType()); Node bound = nm->mkNode(AND, - nm->mkNode(LEQ, d_zero, k), + nm->mkNode(LEQ, zero, k), nm->mkNode(LEQ, k, nm->mkNode(MINUS, lenx, lens))); echildren.push_back(bound); } @@ -423,16 +420,16 @@ Node RegExpElimination::eliminateConcat(Node atom) { std::vector<Node> rprefix; rprefix.insert(rprefix.end(), children.begin(), children.begin() + i); - Node rpn = utils::mkConcat(rprefix, d_regExpType); + Node rpn = utils::mkConcat(rprefix, nm->regExpType()); Node substrPrefix = nm->mkNode( - STRING_IN_REGEXP, nm->mkNode(STRING_SUBSTR, x, d_zero, k), rpn); + STRING_IN_REGEXP, nm->mkNode(STRING_SUBSTR, x, zero, k), rpn); echildren.push_back(substrPrefix); } if (i + 1 < nchildren) { std::vector<Node> rsuffix; rsuffix.insert(rsuffix.end(), children.begin() + i + 1, children.end()); - Node rps = utils::mkConcat(rsuffix, d_regExpType); + Node rps = utils::mkConcat(rsuffix, nm->regExpType()); Node ks = nm->mkNode(PLUS, k, lens); Node substrSuffix = nm->mkNode( STRING_IN_REGEXP, @@ -470,6 +467,7 @@ Node RegExpElimination::eliminateStar(Node atom) Node x = atom[0]; Node lenx = nm->mkNode(STRING_LENGTH, x); Node re = atom[1]; + Node zero = nm->mkConst(Rational(0)); // for regular expression star, // if the period is a fixed constant, we can turn it into a bounded // quantifier @@ -488,7 +486,8 @@ Node RegExpElimination::eliminateStar(Node atom) bool lenOnePeriod = true; std::vector<Node> char_constraints; Node index = nm->mkBoundVar(nm->integerType()); - Node substr_ch = nm->mkNode(STRING_SUBSTR, x, index, d_one); + Node substr_ch = + nm->mkNode(STRING_SUBSTR, x, index, nm->mkConst(Rational(1))); substr_ch = Rewriter::rewrite(substr_ch); // handle the case where it is purely characters for (const Node& r : disj) @@ -526,7 +525,7 @@ Node RegExpElimination::eliminateStar(Node atom) { Assert(!char_constraints.empty()); Node bound = nm->mkNode( - AND, nm->mkNode(LEQ, d_zero, index), nm->mkNode(LT, index, lenx)); + AND, nm->mkNode(LEQ, zero, index), nm->mkNode(LT, index, lenx)); Node conc = char_constraints.size() == 1 ? char_constraints[0] : nm->mkNode(OR, char_constraints); Node body = nm->mkNode(OR, bound.negate(), conc); @@ -554,7 +553,7 @@ Node RegExpElimination::eliminateStar(Node atom) // lens is a positive constant, so it is safe to use total div/mod here. Node bound = nm->mkNode( AND, - nm->mkNode(LEQ, d_zero, index), + nm->mkNode(LEQ, zero, index), nm->mkNode(LT, index, nm->mkNode(INTS_DIVISION_TOTAL, lenx, lens))); Node conc = nm->mkNode(STRING_SUBSTR, x, nm->mkNode(MULT, index, lens), lens) @@ -563,9 +562,7 @@ Node RegExpElimination::eliminateStar(Node atom) Node bvl = nm->mkNode(BOUND_VAR_LIST, index); Node res = nm->mkNode(FORALL, bvl, body); res = nm->mkNode( - AND, - nm->mkNode(INTS_MODULUS_TOTAL, lenx, lens).eqNode(d_zero), - res); + AND, nm->mkNode(INTS_MODULUS_TOTAL, lenx, lens).eqNode(zero), res); // e.g. // x in ("abc")* ---> // forall k. 0 <= k < (len( x ) div 3) => substr(x,3*k,3) = "abc" ^ diff --git a/src/theory/strings/regexp_elim.h b/src/theory/strings/regexp_elim.h index 61ce8a920..e5f2fa854 100644 --- a/src/theory/strings/regexp_elim.h +++ b/src/theory/strings/regexp_elim.h @@ -2,9 +2,9 @@ /*! \file regexp_elim.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -40,25 +40,19 @@ class RegExpElimination * form (str.in.re x R). If this method returns a non-null node ret, then ret * is equivalent to atom. */ - Node eliminate(Node atom); + static Node eliminate(Node atom); private: - /** common terms */ - Node d_zero; - Node d_one; - Node d_neg_one; - /** The type of regular expressions */ - TypeNode d_regExpType; /** return elimination * * This method is called when atom is rewritten to atomElim, and returns * atomElim. id is an identifier indicating the reason for the elimination. */ - Node returnElim(Node atom, Node atomElim, const char* id); + static Node returnElim(Node atom, Node atomElim, const char* id); /** elimination for regular expression concatenation */ - Node eliminateConcat(Node atom); + static Node eliminateConcat(Node atom); /** elimination for regular expression star */ - Node eliminateStar(Node atom); + static Node eliminateStar(Node atom); }; /* class RegExpElimination */ } // namespace strings diff --git a/src/theory/strings/regexp_entail.cpp b/src/theory/strings/regexp_entail.cpp index 8830b7f93..7e1f42f37 100644 --- a/src/theory/strings/regexp_entail.cpp +++ b/src/theory/strings/regexp_entail.cpp @@ -2,9 +2,9 @@ /*! \file regexp_entail.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli, Tianyi Liang + ** Andrew Reynolds, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -48,6 +48,8 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, do_next = false; Node xc = mchildren[mchildren.size() - 1]; Node rc = children[children.size() - 1]; + Trace("regexp-ext-rewrite-debug") + << "* " << xc << " in " << rc << std::endl; Assert(rc.getKind() != REGEXP_CONCAT); Assert(xc.getKind() != STRING_CONCAT); if (rc.getKind() == STRING_TO_REGEXP) @@ -57,7 +59,15 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, children.pop_back(); mchildren.pop_back(); do_next = true; - Trace("regexp-ext-rewrite-debug") << "...strip equal" << std::endl; + Trace("regexp-ext-rewrite-debug") << "- strip equal" << std::endl; + } + else if (rc[0].isConst() && Word::isEmpty(rc[0])) + { + Trace("regexp-ext-rewrite-debug") + << "- ignore empty RE" << std::endl; + // ignore and continue + children.pop_back(); + do_next = true; } else if (xc.isConst() && rc[0].isConst()) { @@ -65,8 +75,8 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, size_t index; Node s = Word::splitConstant(xc, rc[0], index, t == 0); Trace("regexp-ext-rewrite-debug") - << "CRE: Regexp const split : " << xc << " " << rc[0] << " -> " - << s << " " << index << " " << t << std::endl; + << "- CRE: Regexp const split : " << xc << " " << rc[0] + << " -> " << s << " " << index << " " << t << std::endl; if (s.isNull()) { Trace("regexp-ext-rewrite-debug") @@ -76,7 +86,7 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, else { Trace("regexp-ext-rewrite-debug") - << "...strip equal const" << std::endl; + << "- strip equal const" << std::endl; children.pop_back(); mchildren.pop_back(); if (index == 0) @@ -88,6 +98,7 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, children.push_back(nm->mkNode(STRING_TO_REGEXP, s)); } } + Trace("regexp-ext-rewrite-debug") << "- split const" << std::endl; do_next = true; } } @@ -97,7 +108,7 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, CVC4::String s = xc.getConst<String>(); if (Word::isEmpty(xc)) { - Trace("regexp-ext-rewrite-debug") << "...ignore empty" << std::endl; + Trace("regexp-ext-rewrite-debug") << "- ignore empty" << std::endl; // ignore and continue mchildren.pop_back(); do_next = true; @@ -127,6 +138,8 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, } else { + Trace("regexp-ext-rewrite-debug") + << "...return false" << std::endl; return nm->mkConst(false); } } @@ -135,19 +148,23 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, // see if any/each child does not work bool result_valid = true; Node result; - Node emp_s = nm->mkConst(::CVC4::String("")); + Node emp_s = nm->mkConst(String("")); for (unsigned i = 0; i < rc.getNumChildren(); i++) { std::vector<Node> mchildren_s; std::vector<Node> children_s; mchildren_s.push_back(xc); utils::getConcat(rc[i], children_s); + Trace("regexp-ext-rewrite-debug") << push; Node ret = simpleRegexpConsume(mchildren_s, children_s, t); + Trace("regexp-ext-rewrite-debug") << pop; if (!ret.isNull()) { // one conjunct cannot be satisfied, return false if (rc.getKind() == REGEXP_INTER) { + Trace("regexp-ext-rewrite-debug") + << "...return " << ret << std::endl; return ret; } } @@ -182,10 +199,15 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, { // all disjuncts cannot be satisfied, return false Assert(rc.getKind() == REGEXP_UNION); + Trace("regexp-ext-rewrite-debug") + << "...return false" << std::endl; return nm->mkConst(false); } else { + Trace("regexp-ext-rewrite-debug") + << "- same result, try again, children now " << children + << std::endl; // all branches led to the same result children.pop_back(); mchildren.pop_back(); @@ -210,17 +232,19 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, std::vector<Node> children_s; utils::getConcat(rc[0], children_s); Trace("regexp-ext-rewrite-debug") - << "...recursive call on body of star" << std::endl; + << "- recursive call on body of star" << std::endl; + Trace("regexp-ext-rewrite-debug") << push; Node ret = simpleRegexpConsume(mchildren_s, children_s, t); + Trace("regexp-ext-rewrite-debug") << pop; if (!ret.isNull()) { Trace("regexp-ext-rewrite-debug") - << "CRE : regexp star infeasable " << xc << " " << rc + << "- CRE : regexp star infeasable " << xc << " " << rc << std::endl; children.pop_back(); if (!children.empty()) { - Trace("regexp-ext-rewrite-debug") << "...continue" << std::endl; + Trace("regexp-ext-rewrite-debug") << "- continue" << std::endl; do_next = true; } } @@ -244,16 +268,22 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, std::reverse(mchildren_ss.begin(), mchildren_ss.end()); std::reverse(children_ss.begin(), children_ss.end()); } - if (simpleRegexpConsume(mchildren_ss, children_ss, t) - .isNull()) + Trace("regexp-ext-rewrite-debug") + << "- recursive call required repeat star" << std::endl; + Trace("regexp-ext-rewrite-debug") << push; + Node rets = simpleRegexpConsume(mchildren_ss, children_ss, t); + Trace("regexp-ext-rewrite-debug") << pop; + if (rets.isNull()) { can_skip = true; } } if (!can_skip) { + TypeNode stype = nm->stringType(); + Node prev = utils::mkConcat(mchildren, stype); Trace("regexp-ext-rewrite-debug") - << "...can't skip" << std::endl; + << "- can't skip" << std::endl; // take the result of fully consuming once if (t == 1) { @@ -262,12 +292,15 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, mchildren.clear(); mchildren.insert( mchildren.end(), mchildren_s.begin(), mchildren_s.end()); - do_next = true; + Node curr = utils::mkConcat(mchildren, stype); + do_next = (prev != curr); + Trace("regexp-ext-rewrite-debug") + << "- do_next = " << do_next << std::endl; } else { Trace("regexp-ext-rewrite-debug") - << "...can skip " << rc << " from " << xc << std::endl; + << "- can skip " << rc << " from " << xc << std::endl; } } } @@ -276,7 +309,7 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, if (!do_next) { Trace("regexp-ext-rewrite") - << "Cannot consume : " << xc << " " << rc << std::endl; + << "- cannot consume : " << xc << " " << rc << std::endl; } } } @@ -286,6 +319,7 @@ Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren, std::reverse(mchildren.begin(), mchildren.end()); } } + Trace("regexp-ext-rewrite-debug") << "...finished, return null" << std::endl; return Node::null(); } diff --git a/src/theory/strings/regexp_entail.h b/src/theory/strings/regexp_entail.h index ef3f2d34e..9fb797c45 100644 --- a/src/theory/strings/regexp_entail.h +++ b/src/theory/strings/regexp_entail.h @@ -2,9 +2,9 @@ /*! \file regexp_entail.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli, Tianyi Liang + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/regexp_operation.cpp b/src/theory/strings/regexp_operation.cpp index b99124ac3..a91210a7b 100644 --- a/src/theory/strings/regexp_operation.cpp +++ b/src/theory/strings/regexp_operation.cpp @@ -2,9 +2,9 @@ /*! \file regexp_operation.cpp ** \verbatim ** Top contributors (to current version): - ** Tianyi Liang, Andrew Reynolds, Tim King + ** Tianyi Liang, Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -40,7 +40,7 @@ RegExpOpr::RegExpOpr() std::vector<Node>{})), d_sigma_star(NodeManager::currentNM()->mkNode(kind::REGEXP_STAR, d_sigma)) { - d_emptyString = Word::mkEmptyWord(CONST_STRING); + d_emptyString = Word::mkEmptyWord(NodeManager::currentNM()->stringType()); d_emptySingleton = NodeManager::currentNM()->mkNode(STRING_TO_REGEXP, d_emptyString); diff --git a/src/theory/strings/regexp_operation.h b/src/theory/strings/regexp_operation.h index 689c35f3d..d0b0755eb 100644 --- a/src/theory/strings/regexp_operation.h +++ b/src/theory/strings/regexp_operation.h @@ -2,9 +2,9 @@ /*! \file regexp_operation.h ** \verbatim ** Top contributors (to current version): - ** Tianyi Liang, Andrew Reynolds + ** Andrew Reynolds, Tianyi Liang, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/regexp_solver.cpp b/src/theory/strings/regexp_solver.cpp index db7e2d836..53c6c9acc 100644 --- a/src/theory/strings/regexp_solver.cpp +++ b/src/theory/strings/regexp_solver.cpp @@ -2,9 +2,9 @@ /*! \file regexp_solver.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tianyi Liang, Morgan Deters + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -599,7 +599,8 @@ bool RegExpSolver::deriveRegExp(Node x, Trace("regexp-derive") << "RegExpSolver::deriveRegExp: x=" << x << ", r= " << r << std::endl; CVC4::String s = getHeadConst(x); - if (!s.empty() && d_regexp_opr.checkConstRegExp(r)) + // only allow RE_DERIVE for concrete constant regular expressions + if (!s.empty() && d_regexp_opr.getRegExpConstType(r) == RE_C_CONRETE_CONSTANT) { Node conc = Node::null(); Node dc = r; @@ -671,6 +672,7 @@ Node RegExpSolver::getNormalSymRegExp(Node r, std::vector<Node>& nf_exp) case REGEXP_UNION: case REGEXP_INTER: case REGEXP_STAR: + case REGEXP_COMPLEMENT: { std::vector<Node> vec_nodes; for (const Node& cr : r) diff --git a/src/theory/strings/regexp_solver.h b/src/theory/strings/regexp_solver.h index b44c6c8d9..9e9ba5845 100644 --- a/src/theory/strings/regexp_solver.h +++ b/src/theory/strings/regexp_solver.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tianyi Liang, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/rewrites.cpp b/src/theory/strings/rewrites.cpp index 2953a2b3c..68b510de6 100644 --- a/src/theory/strings/rewrites.cpp +++ b/src/theory/strings/rewrites.cpp @@ -2,9 +2,9 @@ /*! \file rewrites.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -111,6 +111,9 @@ const char* toString(Rewrite r) case Rewrite::RPL_RPL_EMPTY: return "RPL_RPL_EMPTY"; case Rewrite::RPL_RPL_LEN_ID: return "RPL_RPL_LEN_ID"; case Rewrite::RPL_X_Y_X_SIMP: return "RPL_X_Y_X_SIMP"; + case Rewrite::REPLACE_RE_EVAL: return "REPLACE_RE_EVAL"; + case Rewrite::REPLACE_RE_ALL_EVAL: return "REPLACE_RE_ALL_EVAL"; + case Rewrite::REPLACE_RE_EMP_RE: return "REPLACE_RE_EMP_RE"; case Rewrite::SPLIT_EQ: return "SPLIT_EQ"; case Rewrite::SPLIT_EQ_STRIP_L: return "SPLIT_EQ_STRIP_L"; case Rewrite::SPLIT_EQ_STRIP_R: return "SPLIT_EQ_STRIP_R"; @@ -199,7 +202,9 @@ const char* toString(Rewrite r) case Rewrite::LEN_CONCAT: return "LEN_CONCAT"; case Rewrite::LEN_REPL_INV: return "LEN_REPL_INV"; case Rewrite::LEN_CONV_INV: return "LEN_CONV_INV"; + case Rewrite::LEN_SEQ_UNIT: return "LEN_SEQ_UNIT"; 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..ccbdbc0cd 100644 --- a/src/theory/strings/rewrites.h +++ b/src/theory/strings/rewrites.h @@ -2,9 +2,9 @@ /*! \file rewrites.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -116,6 +116,9 @@ enum class Rewrite : uint32_t RPL_RPL_EMPTY, RPL_RPL_LEN_ID, RPL_X_Y_X_SIMP, + REPLACE_RE_EVAL, + REPLACE_RE_ALL_EVAL, + REPLACE_RE_EMP_RE, SPLIT_EQ, SPLIT_EQ_STRIP_L, SPLIT_EQ_STRIP_R, @@ -202,7 +205,9 @@ enum class Rewrite : uint32_t LEN_CONCAT, LEN_REPL_INV, LEN_CONV_INV, - CHARAT_ELIM + LEN_SEQ_UNIT, + CHARAT_ELIM, + SEQ_UNIT_EVAL }; /** diff --git a/src/theory/strings/sequences_rewriter.cpp b/src/theory/strings/sequences_rewriter.cpp index 2d2ec0af0..bb0fa1d97 100644 --- a/src/theory/strings/sequences_rewriter.cpp +++ b/src/theory/strings/sequences_rewriter.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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)); } } @@ -576,6 +576,11 @@ Node SequencesRewriter::rewriteLength(Node node) Node retNode = nm->mkNode(STRING_LENGTH, node[0][0]); return returnRewrite(node, retNode, Rewrite::LEN_CONV_INV); } + else if (nk0 == SEQ_UNIT) + { + Node retNode = nm->mkConst(Rational(1)); + return returnRewrite(node, retNode, Rewrite::LEN_SEQ_UNIT); + } return node; } @@ -602,7 +607,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 +649,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); } } } @@ -1315,9 +1320,13 @@ Node SequencesRewriter::rewriteMembership(TNode node) } else { + Node prev = retNode; retNode = nm->mkNode( STRING_IN_REGEXP, utils::mkConcat(mchildren, stype), r); - success = true; + // Iterate again if the node changed. It may not have changed if + // nothing was consumed from mchildren (e.g. if the body of the + // re.* accepts the empty string. + success = (retNode != prev); } } } @@ -1413,6 +1422,14 @@ RewriteResponse SequencesRewriter::postRewrite(TNode node) { retNode = rewriteReplaceAll(node); } + else if (nk == kind::STRING_REPLACE_RE) + { + retNode = rewriteReplaceRe(node); + } + else if (nk == kind::STRING_REPLACE_RE_ALL) + { + retNode = rewriteReplaceReAll(node); + } else if (nk == STRING_REV) { retNode = rewriteStrReverse(node); @@ -1461,6 +1478,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 @@ -1820,6 +1841,7 @@ Node SequencesRewriter::rewriteContains(Node node) nb << emp.eqNode(t); for (const Node& c : vec) { + Assert(c.getType() == t.getType()); nb << c.eqNode(t); } @@ -2910,6 +2932,121 @@ Node SequencesRewriter::rewriteReplaceInternal(Node node) return Node::null(); } +Node SequencesRewriter::rewriteReplaceRe(Node node) +{ + Assert(node.getKind() == STRING_REPLACE_RE); + NodeManager* nm = NodeManager::currentNM(); + Node x = node[0]; + Node y = node[1]; + Node z = node[2]; + + if (x.isConst()) + { + // str.replace_re("ZABCZ", re.++("A", _*, "C"), y) ---> "Z" ++ y ++ "Z" + std::pair<size_t, size_t> match = firstMatch(x, y); + if (match.first != string::npos) + { + String s = x.getConst<String>(); + Node ret = nm->mkNode(STRING_CONCAT, + nm->mkConst(s.substr(0, match.first)), + z, + nm->mkConst(s.substr(match.second))); + return returnRewrite(node, ret, Rewrite::REPLACE_RE_EVAL); + } + else + { + return returnRewrite(node, x, Rewrite::REPLACE_RE_EVAL); + } + } + // str.replace_re( x, y, z ) ---> z ++ x if "" in y ---> true + String emptyStr(""); + if (RegExpEntail::testConstStringInRegExp(emptyStr, 0, y)) + { + Node ret = nm->mkNode(STRING_CONCAT, z, x); + return returnRewrite(node, ret, Rewrite::REPLACE_RE_EMP_RE); + } + return node; +} + +Node SequencesRewriter::rewriteReplaceReAll(Node node) +{ + Assert(node.getKind() == STRING_REPLACE_RE_ALL); + NodeManager* nm = NodeManager::currentNM(); + Node x = node[0]; + Node y = node[1]; + Node z = node[2]; + + if (x.isConst()) + { + // str.replace_re_all("ZABCZAB", re.++("A", _*, "C"), y) ---> + // "Z" ++ y ++ "Z" ++ y + TypeNode t = x.getType(); + Node emp = Word::mkEmptyWord(t); + Node yp = Rewriter::rewrite( + nm->mkNode(REGEXP_DIFF, y, nm->mkNode(STRING_TO_REGEXP, emp))); + std::vector<Node> res; + String rem = x.getConst<String>(); + std::pair<size_t, size_t> match(0, 0); + while (rem.size() >= 0) + { + match = firstMatch(nm->mkConst(rem), yp); + if (match.first == string::npos) + { + break; + } + res.push_back(nm->mkConst(rem.substr(0, match.first))); + res.push_back(z); + rem = rem.substr(match.second); + } + res.push_back(nm->mkConst(rem)); + Node ret = utils::mkConcat(res, t); + return returnRewrite(node, ret, Rewrite::REPLACE_RE_ALL_EVAL); + } + + return node; +} + +std::pair<size_t, size_t> SequencesRewriter::firstMatch(Node n, Node r) +{ + Assert(n.isConst() && n.getType().isStringLike()); + Assert(r.getType().isRegExp()); + NodeManager* nm = NodeManager::currentNM(); + + std::vector<Node> emptyVec; + Node sigmaStar = nm->mkNode(REGEXP_STAR, nm->mkNode(REGEXP_SIGMA, emptyVec)); + Node re = nm->mkNode(REGEXP_CONCAT, r, sigmaStar); + String s = n.getConst<String>(); + + if (s.size() == 0) + { + if (RegExpEntail::testConstStringInRegExp(s, 0, r)) + { + return std::make_pair(0, 0); + } + else + { + return std::make_pair(string::npos, string::npos); + } + } + + for (size_t i = 0, size = s.size(); i < size; i++) + { + if (RegExpEntail::testConstStringInRegExp(s, i, re)) + { + for (size_t j = i; j <= size; j++) + { + String substr = s.substr(i, j - i); + if (RegExpEntail::testConstStringInRegExp(substr, 0, r)) + { + return std::make_pair(i, j); + } + } + } + } + + return std::make_pair(string::npos, string::npos); +} + Node SequencesRewriter::rewriteStrReverse(Node node) { Assert(node.getKind() == STRING_REV); @@ -3040,7 +3177,7 @@ Node SequencesRewriter::canonicalStrForSymbolicLength(Node len, TypeNode stype) Assert(ratLen.getDenominator() == 1); Integer intLen = ratLen.getNumerator(); uint32_t u = intLen.getUnsignedInt(); - if (stype.isString()) + if (stype.isString()) // string-only { res = nm->mkConst(String(std::string(u, 'A'))); } @@ -3095,6 +3232,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 = 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..8da672cb5 100644 --- a/src/theory/strings/sequences_rewriter.h +++ b/src/theory/strings/sequences_rewriter.h @@ -2,9 +2,9 @@ /*! \file sequences_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli, Tianyi Liang + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -204,6 +204,33 @@ class SequencesRewriter : public TheoryRewriter * str.replaceall. If it returns a non-null ret, then node rewrites to ret. */ Node rewriteReplaceInternal(Node node); + /** rewrite regular expression replace + * + * This method implements rewrite rules that apply to terms of the form + * str.replace_re(s, r, t). + * + * @param node The node to rewrite + * @return The rewritten node + */ + Node rewriteReplaceRe(Node node); + /** rewrite regular expression replace + * + * This method implements rewrite rules that apply to terms of the form + * str.replace_re_all(s, r, t). + * + * @param node The node to rewrite + * @return The rewritten node + */ + Node rewriteReplaceReAll(Node node); + /** + * Returns the first, shortest sequence in n that matches r. + * + * @param n The constant string or sequence to search in. + * @param r The regular expression to search for. + * @return A pair holding the start position and the end position of the + * match or a pair of string::npos if r does not appear in n. + */ + std::pair<size_t, size_t> firstMatch(Node n, Node r); /** rewrite string reverse * * This is the entry point for post-rewriting terms n of the form @@ -224,6 +251,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/sequences_stats.cpp b/src/theory/strings/sequences_stats.cpp index c830a68bd..502d05353 100644 --- a/src/theory/strings/sequences_stats.cpp +++ b/src/theory/strings/sequences_stats.cpp @@ -2,7 +2,7 @@ /*! \file sequences_stats.cpp ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. diff --git a/src/theory/strings/sequences_stats.h b/src/theory/strings/sequences_stats.h index 8a1564587..85f830fa2 100644 --- a/src/theory/strings/sequences_stats.h +++ b/src/theory/strings/sequences_stats.h @@ -2,7 +2,7 @@ /*! \file sequences_stats.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level source directory) and their institutional affiliations. diff --git a/src/theory/strings/skolem_cache.cpp b/src/theory/strings/skolem_cache.cpp index 4af75f1cc..8fb854d91 100644 --- a/src/theory/strings/skolem_cache.cpp +++ b/src/theory/strings/skolem_cache.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -82,12 +82,13 @@ Node SkolemCache::mkTypedSkolemCached( } NodeManager* nm = NodeManager::currentNM(); + SkolemManager* sm = nm->getSkolemManager(); Node sk; switch (id) { // exists k. k = a case SK_PURIFY: - sk = ProofSkolemCache::mkPurifySkolem(a, c, "string purify skolem"); + sk = sm->mkPurifySkolem(a, c, "string purify skolem"); break; // these are eliminated by normalizeStringSkolem case SK_ID_V_SPT: @@ -113,7 +114,7 @@ Node SkolemCache::mkTypedSkolemCached( Notice() << "Don't know how to handle Skolem ID " << id << std::endl; Node v = nm->mkBoundVar(tn); Node cond = nm->mkConst(true); - sk = ProofSkolemCache::mkSkolem(v, cond, c, "string skolem"); + sk = sm->mkSkolem(v, cond, c, "string skolem"); } break; } diff --git a/src/theory/strings/skolem_cache.h b/src/theory/strings/skolem_cache.h index 0ebbb3277..302c69e83 100644 --- a/src/theory/strings/skolem_cache.h +++ b/src/theory/strings/skolem_cache.h @@ -2,9 +2,9 @@ /*! \file skolem_cache.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli + ** Andrew Reynolds, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -22,7 +22,7 @@ #include <unordered_set> #include "expr/node.h" -#include "expr/proof_skolem_cache.h" +#include "expr/skolem_manager.h" namespace CVC4 { namespace theory { @@ -102,6 +102,16 @@ class SkolemCache // of b in a as the witness for contains( a, b ). SK_FIRST_CTN_PRE, SK_FIRST_CTN_POST, + // For sequence a and regular expression b, + // in_re(a, re.++(_*, b, _*)) => + // exists k_pre, k_match, k_post. + // a = k_pre ++ k_match ++ k_post ^ + // ~in_re(k_pre ++ substr(k_match, 0, str.len(k_match) - 1), + // re.++(_*, b, _*)) ^ + // in_re(k2, y) + SK_FIRST_MATCH_PRE, + SK_FIRST_MATCH, + SK_FIRST_MATCH_POST, // For integer b, // len( a ) > b => // exists k. a = k ++ a' ^ len( k ) = b @@ -120,6 +130,14 @@ class SkolemCache // k(x) is the end index of the x^th occurrence of b in a // where n is the number of occurrences of b in a, and k(0)=0. SK_OCCUR_INDEX, + // For function k: Int -> Int + // exists k. + // forall 0 <= x < n, + // k(x) is the length of the x^th occurrence of b in a (excluding + // matches of empty strings) + // where b is a regular expression, n is the number of occurrences of b + // in a, and k(0)=0. + SK_OCCUR_LEN, }; /** * Returns a skolem of type string that is cached for (a,b,id) and has diff --git a/src/theory/strings/solver_state.cpp b/src/theory/strings/solver_state.cpp index 622e919f7..06a86935f 100644 --- a/src/theory/strings/solver_state.cpp +++ b/src/theory/strings/solver_state.cpp @@ -2,9 +2,9 @@ /*! \file solver_state.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tianyi Liang, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -297,31 +297,39 @@ std::pair<bool, Node> SolverState::entailmentCheck(options::TheoryOfMode mode, return d_valuation.entailmentCheck(mode, lit); } -void SolverState::separateByLength(const std::vector<Node>& n, - std::vector<std::vector<Node> >& cols, - std::vector<Node>& lts) +void SolverState::separateByLength( + const std::vector<Node>& n, + std::map<TypeNode, std::vector<std::vector<Node>>>& cols, + std::map<TypeNode, std::vector<Node>>& lts) { unsigned leqc_counter = 0; - std::map<Node, unsigned> eqc_to_leqc; - std::map<unsigned, Node> leqc_to_eqc; + // map (length, type) to an equivalence class identifier + std::map<std::pair<Node, TypeNode>, unsigned> eqc_to_leqc; + // backwards map + std::map<unsigned, std::pair<Node, TypeNode>> leqc_to_eqc; + // Collection of eqc for each identifier. Notice that some identifiers may + // not have an associated length in the mappings above, if the length of + // an equivalence class is unknown. std::map<unsigned, std::vector<Node> > eqc_to_strings; NodeManager* nm = NodeManager::currentNM(); for (const Node& eqc : n) { Assert(d_ee.getRepresentative(eqc) == eqc); + TypeNode tnEqc = eqc.getType(); EqcInfo* ei = getOrMakeEqcInfo(eqc, false); Node lt = ei ? ei->d_lengthTerm : Node::null(); if (!lt.isNull()) { lt = nm->mkNode(STRING_LENGTH, lt); Node r = d_ee.getRepresentative(lt); - if (eqc_to_leqc.find(r) == eqc_to_leqc.end()) + std::pair<Node, TypeNode> lkey(r, tnEqc); + if (eqc_to_leqc.find(lkey) == eqc_to_leqc.end()) { - eqc_to_leqc[r] = leqc_counter; - leqc_to_eqc[leqc_counter] = r; + eqc_to_leqc[lkey] = leqc_counter; + leqc_to_eqc[leqc_counter] = lkey; leqc_counter++; } - eqc_to_strings[eqc_to_leqc[r]].push_back(eqc); + eqc_to_strings[eqc_to_leqc[lkey]].push_back(eqc); } else { @@ -331,9 +339,11 @@ void SolverState::separateByLength(const std::vector<Node>& n, } for (const std::pair<const unsigned, std::vector<Node> >& p : eqc_to_strings) { - cols.push_back(std::vector<Node>()); - cols.back().insert(cols.back().end(), p.second.begin(), p.second.end()); - lts.push_back(leqc_to_eqc[p.first]); + Assert(!p.second.empty()); + // get the type of the collection + TypeNode stn = p.second[0].getType(); + cols[stn].emplace_back(p.second.begin(), p.second.end()); + lts[stn].push_back(leqc_to_eqc[p.first].first); } } diff --git a/src/theory/strings/solver_state.h b/src/theory/strings/solver_state.h index d43c600f4..2eee90ca4 100644 --- a/src/theory/strings/solver_state.h +++ b/src/theory/strings/solver_state.h @@ -2,9 +2,9 @@ /*! \file solver_state.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tianyi Liang, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -171,11 +171,14 @@ class SolverState * * Separate the string representatives in argument n into a partition cols * whose collections have equal length. The i^th vector in cols has length - * lts[i] for all elements in col. + * lts[i] for all elements in col. These vectors are furthmore separated + * by string-like type. */ - void separateByLength(const std::vector<Node>& n, - std::vector<std::vector<Node> >& cols, - std::vector<Node>& lts); + void separateByLength( + const std::vector<Node>& n, + std::map<TypeNode, std::vector<std::vector<Node>>>& cols, + std::map<TypeNode, std::vector<Node>>& lts); + private: /** Common constants */ Node d_zero; diff --git a/src/theory/strings/strategy.cpp b/src/theory/strings/strategy.cpp new file mode 100644 index 000000000..549bba9d6 --- /dev/null +++ b/src/theory/strings/strategy.cpp @@ -0,0 +1,161 @@ +/********************* */ +/*! \file strategy.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds, Tianyi Liang, Morgan Deters + ** 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 strategy of the theory of strings. + **/ + +#include "theory/strings/strategy.h" + +#include "options/strings_options.h" + +namespace CVC4 { +namespace theory { +namespace strings { + +std::ostream& operator<<(std::ostream& out, InferStep s) +{ + switch (s) + { + case BREAK: out << "break"; break; + case CHECK_INIT: out << "check_init"; break; + case CHECK_CONST_EQC: out << "check_const_eqc"; break; + case CHECK_EXTF_EVAL: out << "check_extf_eval"; break; + case CHECK_CYCLES: out << "check_cycles"; break; + case CHECK_FLAT_FORMS: out << "check_flat_forms"; break; + case CHECK_NORMAL_FORMS_EQ: out << "check_normal_forms_eq"; break; + case CHECK_NORMAL_FORMS_DEQ: out << "check_normal_forms_deq"; break; + case CHECK_CODES: out << "check_codes"; break; + case CHECK_LENGTH_EQC: out << "check_length_eqc"; break; + case CHECK_EXTF_REDUCTION: out << "check_extf_reduction"; break; + case CHECK_MEMBERSHIP: out << "check_membership"; break; + case CHECK_CARDINALITY: out << "check_cardinality"; break; + default: out << "?"; break; + } + return out; +} + +Strategy::Strategy() : d_strategy_init(false) {} + +Strategy::~Strategy() {} + +bool Strategy::isStrategyInit() const { return d_strategy_init; } + +bool Strategy::hasStrategyEffort(Theory::Effort e) const +{ + return d_strat_steps.find(e) != d_strat_steps.end(); +} + +std::vector<std::pair<InferStep, int> >::iterator Strategy::stepBegin( + Theory::Effort e) +{ + std::map<Theory::Effort, std::pair<unsigned, unsigned> >::const_iterator it = + d_strat_steps.find(e); + Assert(it != d_strat_steps.end()); + return d_infer_steps.begin() + it->second.first; +} + +std::vector<std::pair<InferStep, int> >::iterator Strategy::stepEnd( + Theory::Effort e) +{ + std::map<Theory::Effort, std::pair<unsigned, unsigned> >::const_iterator it = + d_strat_steps.find(e); + Assert(it != d_strat_steps.end()); + return d_infer_steps.begin() + it->second.second; +} + +void Strategy::addStrategyStep(InferStep s, int effort, bool addBreak) +{ + // must run check init first + Assert((s == CHECK_INIT) == d_infer_steps.empty()); + d_infer_steps.push_back(std::pair<InferStep, int>(s, effort)); + if (addBreak) + { + d_infer_steps.push_back(std::pair<InferStep, int>(BREAK, 0)); + } +} + +void Strategy::initializeStrategy() +{ + // initialize the strategy if not already done so + if (!d_strategy_init) + { + std::map<Theory::Effort, unsigned> step_begin; + std::map<Theory::Effort, unsigned> step_end; + d_strategy_init = true; + // beginning indices + step_begin[Theory::EFFORT_FULL] = 0; + if (options::stringEager()) + { + step_begin[Theory::EFFORT_STANDARD] = 0; + } + // add the inference steps + addStrategyStep(CHECK_INIT); + addStrategyStep(CHECK_CONST_EQC); + addStrategyStep(CHECK_EXTF_EVAL, 0); + // we must check cycles before using flat forms + addStrategyStep(CHECK_CYCLES); + if (options::stringFlatForms()) + { + addStrategyStep(CHECK_FLAT_FORMS); + } + addStrategyStep(CHECK_EXTF_REDUCTION, 1); + if (options::stringEager()) + { + // do only the above inferences at standard effort, if applicable + step_end[Theory::EFFORT_STANDARD] = d_infer_steps.size() - 1; + } + if (!options::stringEagerLen()) + { + addStrategyStep(CHECK_REGISTER_TERMS_PRE_NF); + } + addStrategyStep(CHECK_NORMAL_FORMS_EQ); + addStrategyStep(CHECK_EXTF_EVAL, 1); + if (!options::stringEagerLen() && options::stringLenNorm()) + { + addStrategyStep(CHECK_LENGTH_EQC, 0, false); + addStrategyStep(CHECK_REGISTER_TERMS_NF); + } + addStrategyStep(CHECK_NORMAL_FORMS_DEQ); + addStrategyStep(CHECK_CODES); + if (options::stringEagerLen() && options::stringLenNorm()) + { + addStrategyStep(CHECK_LENGTH_EQC); + } + if (options::stringExp() && !options::stringGuessModel()) + { + addStrategyStep(CHECK_EXTF_REDUCTION, 2); + } + addStrategyStep(CHECK_MEMBERSHIP); + addStrategyStep(CHECK_CARDINALITY); + step_end[Theory::EFFORT_FULL] = d_infer_steps.size() - 1; + if (options::stringExp() && options::stringGuessModel()) + { + step_begin[Theory::EFFORT_LAST_CALL] = d_infer_steps.size(); + // these two steps are run in parallel + addStrategyStep(CHECK_EXTF_REDUCTION, 2, false); + addStrategyStep(CHECK_EXTF_EVAL, 3); + step_end[Theory::EFFORT_LAST_CALL] = d_infer_steps.size() - 1; + } + // set the beginning/ending ranges + for (const std::pair<const Theory::Effort, unsigned>& it_begin : step_begin) + { + Theory::Effort e = it_begin.first; + std::map<Theory::Effort, unsigned>::iterator it_end = step_end.find(e); + Assert(it_end != step_end.end()); + d_strat_steps[e] = + std::pair<unsigned, unsigned>(it_begin.second, it_end->second); + } + } +} + +} // namespace strings +} // namespace theory +} // namespace CVC4 diff --git a/src/theory/strings/strategy.h b/src/theory/strings/strategy.h new file mode 100644 index 000000000..9afb6a92f --- /dev/null +++ b/src/theory/strings/strategy.h @@ -0,0 +1,116 @@ +/********************* */ +/*! \file strategy.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 Strategy of the theory of strings + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__THEORY__STRINGS__STRATEGY_H +#define CVC4__THEORY__STRINGS__STRATEGY_H + +#include <map> +#include <vector> + +#include "theory/theory.h" + +namespace CVC4 { +namespace theory { +namespace strings { + +/** inference steps + * + * Corresponds to a step in the overall strategy of the strings solver. For + * details on the individual steps, see documentation on the inference schemas + * within Strategy. + */ +enum InferStep +{ + // indicates that the strategy should break if lemmas or facts are added + BREAK, + // check initial + CHECK_INIT, + // check constant equivalence classes + CHECK_CONST_EQC, + // check extended function evaluation + CHECK_EXTF_EVAL, + // check cycles + CHECK_CYCLES, + // check flat forms + CHECK_FLAT_FORMS, + // check register terms pre-normal forms + CHECK_REGISTER_TERMS_PRE_NF, + // check normal forms equalities + CHECK_NORMAL_FORMS_EQ, + // check normal forms disequalities + CHECK_NORMAL_FORMS_DEQ, + // check codes + CHECK_CODES, + // check lengths for equivalence classes + CHECK_LENGTH_EQC, + // check register terms for normal forms + CHECK_REGISTER_TERMS_NF, + // check extended function reductions + CHECK_EXTF_REDUCTION, + // check regular expression memberships + CHECK_MEMBERSHIP, + // check cardinality + CHECK_CARDINALITY, +}; +std::ostream& operator<<(std::ostream& out, InferStep i); + +/** + * The strategy of theory of strings. + * + * This stores a sequence of the above enum that indicates the calls to + * runInferStep to make on the theory of strings, given by parent. + */ +class Strategy +{ + public: + Strategy(); + ~Strategy(); + /** is this strategy initialized? */ + bool isStrategyInit() const; + /** do we have a strategy for effort e? */ + bool hasStrategyEffort(Theory::Effort e) const; + /** begin and end iterators for effort e */ + std::vector<std::pair<InferStep, int> >::iterator stepBegin(Theory::Effort e); + std::vector<std::pair<InferStep, int> >::iterator stepEnd(Theory::Effort e); + /** initialize the strategy + * + * This initializes the above information based on the options. This makes + * a series of calls to addStrategyStep above. + */ + void initializeStrategy(); + + private: + /** add strategy step + * + * This adds (s,effort) as a strategy step to the vectors d_infer_steps and + * d_infer_step_effort. This indicates that a call to runInferStep should + * be run as the next step in the strategy. If addBreak is true, we add + * a BREAK to the strategy following this step. + */ + void addStrategyStep(InferStep s, int effort = 0, bool addBreak = true); + /** is strategy initialized */ + bool d_strategy_init; + /** the strategy */ + std::vector<std::pair<InferStep, int> > d_infer_steps; + /** the range (begin, end) of steps to run at given efforts */ + std::map<Theory::Effort, std::pair<unsigned, unsigned> > d_strat_steps; +}; /* class Strategy */ + +} // namespace strings +} // namespace theory +} // namespace CVC4 + +#endif /* CVC4__THEORY__STRINGS__STRATEGY_H */ diff --git a/src/theory/strings/strings_entail.cpp b/src/theory/strings/strings_entail.cpp index 311eda554..9f502e1f6 100644 --- a/src/theory/strings/strings_entail.cpp +++ b/src/theory/strings/strings_entail.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -37,8 +37,6 @@ bool StringsEntail::canConstantContainConcat(Node c, int& lastc) { Assert(c.isConst()); - CVC4::String t = c.getConst<String>(); - const std::vector<unsigned>& tvec = t.getVec(); Assert(n.getKind() == STRING_CONCAT); // must find constant components in order size_t pos = 0; @@ -50,19 +48,20 @@ bool StringsEntail::canConstantContainConcat(Node c, { firstc = firstc == -1 ? i : firstc; lastc = i; - CVC4::String s = n[i].getConst<String>(); - size_t new_pos = t.find(s, pos); + size_t new_pos = Word::find(c, n[i], pos); if (new_pos == std::string::npos) { return false; } else { - pos = new_pos + s.size(); + pos = new_pos + Word::getLength(n[i]); } } else if (n[i].getKind() == STRING_ITOS && ArithEntail::check(n[i][0])) { + Assert(c.getType().isString()); + const std::vector<unsigned>& tvec = c.getConst<String>().getVec(); // find the first occurrence of a digit starting at pos while (pos < tvec.size() && !String::isDigit(tvec[pos])) { @@ -116,7 +115,8 @@ bool StringsEntail::stripSymbolicLength(std::vector<Node>& n1, { Assert(dir == 1 || dir == -1); Assert(nr.empty()); - Node zero = NodeManager::currentNM()->mkConst(CVC4::Rational(0)); + NodeManager* nm = NodeManager::currentNM(); + Node zero = nm->mkConst(CVC4::Rational(0)); bool ret = false; bool success; unsigned sindex = 0; @@ -139,18 +139,16 @@ bool StringsEntail::stripSymbolicLength(std::vector<Node>& n1, if (lbr.sgn() > 0) { Assert(ArithEntail::check(curr, true)); - CVC4::String s = n1[sindex_use].getConst<String>(); - Node ncl = - NodeManager::currentNM()->mkConst(CVC4::Rational(s.size())); - Node next_s = - NodeManager::currentNM()->mkNode(MINUS, lowerBound, ncl); + Node s = n1[sindex_use]; + size_t slen = Word::getLength(s); + Node ncl = nm->mkConst(CVC4::Rational(slen)); + Node next_s = nm->mkNode(MINUS, lowerBound, ncl); next_s = Rewriter::rewrite(next_s); Assert(next_s.isConst()); // we can remove the entire constant if (next_s.getConst<Rational>().sgn() >= 0) { - curr = Rewriter::rewrite( - NodeManager::currentNM()->mkNode(MINUS, curr, ncl)); + curr = Rewriter::rewrite(nm->mkNode(MINUS, curr, ncl)); success = true; sindex++; } @@ -160,25 +158,20 @@ bool StringsEntail::stripSymbolicLength(std::vector<Node>& n1, // lower bound minus the length of a concrete string is negative, // hence lowerBound cannot be larger than long max Assert(lbr < Rational(String::maxSize())); - curr = Rewriter::rewrite( - NodeManager::currentNM()->mkNode(MINUS, curr, lowerBound)); + curr = Rewriter::rewrite(nm->mkNode(MINUS, curr, lowerBound)); uint32_t lbsize = lbr.getNumerator().toUnsignedInt(); - Assert(lbsize < s.size()); + Assert(lbsize < slen); if (dir == 1) { // strip partially from the front - nr.push_back( - NodeManager::currentNM()->mkConst(s.prefix(lbsize))); - n1[sindex_use] = NodeManager::currentNM()->mkConst( - s.suffix(s.size() - lbsize)); + nr.push_back(Word::prefix(s, lbsize)); + n1[sindex_use] = Word::suffix(s, slen - lbsize); } else { // strip partially from the back - nr.push_back( - NodeManager::currentNM()->mkConst(s.suffix(lbsize))); - n1[sindex_use] = NodeManager::currentNM()->mkConst( - s.prefix(s.size() - lbsize)); + nr.push_back(Word::suffix(s, lbsize)); + n1[sindex_use] = Word::prefix(s, slen - lbsize); } ret = true; } @@ -496,8 +489,6 @@ bool StringsEntail::stripConstantEndpoints(std::vector<Node>& n1, { Assert(nb.empty()); Assert(ne.empty()); - - NodeManager* nm = NodeManager::currentNM(); bool changed = false; // for ( forwards, backwards ) direction for (unsigned r = 0; r < 2; r++) @@ -509,7 +500,7 @@ bool StringsEntail::stripConstantEndpoints(std::vector<Node>& n1, bool removeComponent = false; Node n1cmp = n1[index0]; - if (n1cmp.isConst() && n1cmp.getConst<String>().size() == 0) + if (n1cmp.isConst() && Word::isEmpty(n1cmp)) { return false; } @@ -522,14 +513,15 @@ bool StringsEntail::stripConstantEndpoints(std::vector<Node>& n1, << ", dir = " << dir << std::endl; if (n1cmp.isConst()) { - CVC4::String s = n1cmp.getConst<String>(); + Node s = n1cmp; + size_t slen = Word::getLength(s); // overlap is an overapproximation of the number of characters // n2[index1] can match in s - unsigned overlap = s.size(); + unsigned overlap = Word::getLength(s); if (n2[index1].isConst()) { - CVC4::String t = n2[index1].getConst<String>(); - std::size_t ret = r == 0 ? s.find(t) : s.rfind(t); + Node t = n2[index1]; + std::size_t ret = r == 0 ? Word::find(s, t) : Word::rfind(s, t); if (ret == std::string::npos) { if (n1.size() == 1) @@ -545,7 +537,7 @@ bool StringsEntail::stripConstantEndpoints(std::vector<Node>& n1, // This is used to partially strip off the endpoint // e.g. str.contains( str.++( "abc", x ), str.++( "cd", y ) ) --> // str.contains( str.++( "c", x ), str.++( "cd", y ) ) - overlap = r == 0 ? s.overlap(t) : t.overlap(s); + overlap = r == 0 ? Word::overlap(s, t) : Word::overlap(t, s); } else { @@ -553,19 +545,20 @@ bool StringsEntail::stripConstantEndpoints(std::vector<Node>& n1, // if there is no overlap // e.g. str.contains( str.++( str.substr( "c", i, j ), x), "a" ) // --> str.contains( x, "a" ) - removeComponent = ((r == 0 ? s.overlap(t) : t.overlap(s)) == 0); + removeComponent = + ((r == 0 ? Word::overlap(s, t) : Word::overlap(t, s)) == 0); } } else if (sss.empty()) // only if not substr { - Assert(ret < s.size()); + Assert(ret < slen); // can strip off up to the find position, e.g. // str.contains( str.++( "abc", x ), str.++( "b", y ) ) --> // str.contains( str.++( "bc", x ), str.++( "b", y ) ), // and // str.contains( str.++( x, "abbd" ), str.++( y, "b" ) ) --> // str.contains( str.++( x, "abb" ), str.++( y, "b" ) ) - overlap = s.size() - ret; + overlap = slen - ret; } } else @@ -573,7 +566,7 @@ bool StringsEntail::stripConstantEndpoints(std::vector<Node>& n1, // inconclusive } // process the overlap - if (overlap < s.size()) + if (overlap < slen) { changed = true; if (overlap == 0) @@ -586,13 +579,13 @@ bool StringsEntail::stripConstantEndpoints(std::vector<Node>& n1, // component if (r == 0) { - nb.push_back(nm->mkConst(s.prefix(s.size() - overlap))); - n1[index0] = nm->mkConst(s.suffix(overlap)); + nb.push_back(Word::prefix(s, slen - overlap)); + n1[index0] = Word::suffix(s, overlap); } else { - ne.push_back(nm->mkConst(s.suffix(s.size() - overlap))); - n1[index0] = nm->mkConst(s.prefix(overlap)); + ne.push_back(Word::suffix(s, slen - overlap)); + n1[index0] = Word::prefix(s, overlap); } } } @@ -601,8 +594,8 @@ bool StringsEntail::stripConstantEndpoints(std::vector<Node>& n1, { if (n2[index1].isConst()) { + Assert(n2[index1].getType().isString()); CVC4::String t = n2[index1].getConst<String>(); - if (n1.size() == 1) { // if n1.size()==1, then if n2[index1] is not a number, we can drop diff --git a/src/theory/strings/strings_entail.h b/src/theory/strings/strings_entail.h index 379c09043..3eb77c5f5 100644 --- a/src/theory/strings/strings_entail.h +++ b/src/theory/strings/strings_entail.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/strings_fmf.cpp b/src/theory/strings/strings_fmf.cpp index 87ce5e7c6..9530171f0 100644 --- a/src/theory/strings/strings_fmf.cpp +++ b/src/theory/strings/strings_fmf.cpp @@ -2,9 +2,9 @@ /*! \file strings_fmf.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/strings_fmf.h b/src/theory/strings/strings_fmf.h index 9dfb1f590..f66c23d5b 100644 --- a/src/theory/strings/strings_fmf.h +++ b/src/theory/strings/strings_fmf.h @@ -2,9 +2,9 @@ /*! \file strings_fmf.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/strings_rewriter.cpp b/src/theory/strings/strings_rewriter.cpp index bd749576e..76391cc0d 100644 --- a/src/theory/strings/strings_rewriter.cpp +++ b/src/theory/strings/strings_rewriter.cpp @@ -2,9 +2,9 @@ /*! \file strings_rewriter.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli, Tianyi Liang + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/strings_rewriter.h b/src/theory/strings/strings_rewriter.h index ce4be476d..aadb11f1c 100644 --- a/src/theory/strings/strings_rewriter.h +++ b/src/theory/strings/strings_rewriter.h @@ -2,9 +2,9 @@ /*! \file strings_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Andres Noetzli, Tianyi Liang + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/strings/term_registry.cpp b/src/theory/strings/term_registry.cpp index 6330d7c10..b4fbbed98 100644 --- a/src/theory/strings/term_registry.cpp +++ b/src/theory/strings/term_registry.cpp @@ -2,9 +2,9 @@ /*! \file term_registry.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tianyi Liang, Morgan Deters + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -15,6 +15,7 @@ #include "theory/strings/term_registry.h" #include "expr/attribute.h" +#include "options/smt_options.h" #include "options/strings_options.h" #include "smt/logic_exception.h" #include "theory/rewriter.h" @@ -35,23 +36,25 @@ struct StringsProxyVarAttributeId typedef expr::Attribute<StringsProxyVarAttributeId, bool> StringsProxyVarAttribute; -TermRegistry::TermRegistry(context::Context* c, - context::UserContext* u, +TermRegistry::TermRegistry(SolverState& s, eq::EqualityEngine& ee, OutputChannel& out, - SequencesStatistics& statistics) - : d_ee(ee), + SequencesStatistics& statistics, + ProofNodeManager* pnm) + : d_state(s), + d_ee(ee), d_out(out), d_statistics(statistics), d_hasStrCode(false), - d_functionsTerms(c), - d_inputVars(u), - d_preregisteredTerms(u), - d_registeredTerms(u), - d_registeredTypes(u), - d_proxyVar(u), - d_proxyVarToLength(u), - d_lengthLemmaTermsCache(u) + d_functionsTerms(s.getSatContext()), + d_inputVars(s.getUserContext()), + d_preregisteredTerms(s.getUserContext()), + d_registeredTerms(s.getUserContext()), + d_registeredTypes(s.getUserContext()), + d_proxyVar(s.getUserContext()), + d_proxyVarToLength(s.getUserContext()), + d_lengthLemmaTermsCache(s.getUserContext()), + d_epg(nullptr) { NodeManager* nm = NodeManager::currentNM(); d_zero = nm->mkConst(Rational(0)); @@ -62,6 +65,64 @@ TermRegistry::TermRegistry(context::Context* c, TermRegistry::~TermRegistry() {} +Node TermRegistry::eagerReduce(Node t, SkolemCache* sc) +{ + NodeManager* nm = NodeManager::currentNM(); + Node lemma; + Kind tk = t.getKind(); + if (tk == STRING_TO_CODE) + { + // ite( str.len(s)==1, 0 <= str.code(s) < |A|, str.code(s)=-1 ) + Node code_len = utils::mkNLength(t[0]).eqNode(nm->mkConst(Rational(1))); + Node code_eq_neg1 = t.eqNode(nm->mkConst(Rational(-1))); + Node code_range = nm->mkNode( + AND, + nm->mkNode(GEQ, t, nm->mkConst(Rational(0))), + nm->mkNode( + LT, t, nm->mkConst(Rational(utils::getAlphabetCardinality())))); + lemma = nm->mkNode(ITE, code_len, code_range, code_eq_neg1); + } + else if (tk == STRING_STRIDOF) + { + // (and (>= (str.indexof x y n) (- 1)) (<= (str.indexof x y n) (str.len + // x))) + Node l = utils::mkNLength(t[0]); + lemma = nm->mkNode(AND, + nm->mkNode(GEQ, t, nm->mkConst(Rational(-1))), + nm->mkNode(LEQ, t, l)); + } + else if (tk == STRING_STOI) + { + // (>= (str.to_int x) (- 1)) + lemma = nm->mkNode(GEQ, t, nm->mkConst(Rational(-1))); + } + else if (tk == STRING_STRCTN) + { + // ite( (str.contains s r), (= s (str.++ sk1 r sk2)), (not (= s r))) + Node sk1 = + sc->mkSkolemCached(t[0], t[1], SkolemCache::SK_FIRST_CTN_PRE, "sc1"); + Node sk2 = + sc->mkSkolemCached(t[0], t[1], SkolemCache::SK_FIRST_CTN_POST, "sc2"); + lemma = t[0].eqNode(utils::mkNConcat(sk1, t[1], sk2)); + lemma = nm->mkNode(ITE, t, lemma, t[0].eqNode(t[1]).notNode()); + } + return lemma; +} + +Node TermRegistry::lengthPositive(Node t) +{ + NodeManager* nm = NodeManager::currentNM(); + Node zero = nm->mkConst(Rational(0)); + Node emp = Word::mkEmptyWord(t.getType()); + Node tlen = nm->mkNode(STRING_LENGTH, t); + Node tlenEqZero = tlen.eqNode(zero); + Node tEqEmp = t.eqNode(emp); + Node caseEmpty = nm->mkNode(AND, tlenEqZero, tEqEmp); + Node caseNEmpty = nm->mkNode(GT, tlen, zero); + // (or (and (= (str.len t) 0) (= t "")) (> (str.len t) 0)) + return nm->mkNode(OR, caseEmpty, caseNEmpty); +} + void TermRegistry::preRegisterTerm(TNode n) { if (d_preregisteredTerms.find(n) != d_preregisteredTerms.end()) @@ -76,9 +137,10 @@ void TermRegistry::preRegisterTerm(TNode n) if (!options::stringExp()) { if (k == STRING_STRIDOF || k == STRING_ITOS || k == STRING_STOI - || k == STRING_STRREPL || k == STRING_STRREPLALL || k == STRING_STRCTN - || k == STRING_LEQ || k == STRING_TOLOWER || k == STRING_TOUPPER - || k == STRING_REV) + || k == STRING_STRREPL || k == STRING_STRREPLALL + || k == STRING_REPLACE_RE || k == STRING_REPLACE_RE_ALL + || k == STRING_STRCTN || k == STRING_LEQ || k == STRING_TOLOWER + || k == STRING_TOUPPER || k == STRING_REV) { std::stringstream ss; ss << "Term of kind " << k @@ -201,7 +263,6 @@ void TermRegistry::registerTerm(Node n, int effort) d_registeredTerms.insert(n); // ensure the type is registered registerType(tn); - NodeManager* nm = NodeManager::currentNM(); Debug("strings-register") << "TheoryStrings::registerTerm() " << n << ", effort = " << effort << std::endl; Node regTermLem; @@ -212,28 +273,10 @@ void TermRegistry::registerTerm(Node n, int effort) // for concat/const/replace, introduce proxy var and state length relation regTermLem = getRegisterTermLemma(n); } - else if (n.getKind() == STRING_TO_CODE) - { - // ite( str.len(s)==1, 0 <= str.code(s) < |A|, str.code(s)=-1 ) - Node code_len = utils::mkNLength(n[0]).eqNode(d_one); - Node code_eq_neg1 = n.eqNode(d_negOne); - Node code_range = nm->mkNode( - AND, - nm->mkNode(GEQ, n, d_zero), - nm->mkNode( - LT, n, nm->mkConst(Rational(utils::getAlphabetCardinality())))); - regTermLem = nm->mkNode(ITE, code_len, code_range, code_eq_neg1); - } - else if (n.getKind() == STRING_STRIDOF) + else if (n.getKind() != STRING_STRCTN) { - Node len = utils::mkNLength(n[0]); - regTermLem = nm->mkNode(AND, - nm->mkNode(GEQ, n, nm->mkConst(Rational(-1))), - nm->mkNode(LEQ, n, len)); - } - else if (n.getKind() == STRING_STOI) - { - regTermLem = nm->mkNode(GEQ, n, nm->mkConst(Rational(-1))); + // we don't send out eager reduction lemma for str.contains currently + regTermLem = eagerReduce(n, &d_skCache); } if (!regTermLem.isNull()) { @@ -323,7 +366,9 @@ Node TermRegistry::getRegisterTermLemma(Node n) d_proxyVarToLength[sk] = lsum; Node ceq = Rewriter::rewrite(skl.eqNode(lsum)); - return nm->mkNode(AND, eq, ceq); + Node ret = nm->mkNode(AND, eq, ceq); + + return ret; } void TermRegistry::registerTermAtomic(Node n, LengthStatus s) @@ -406,17 +451,15 @@ Node TermRegistry::getRegisterTermAtomicLemma(Node n, } Assert(s == LENGTH_SPLIT); - std::vector<Node> lems; + // get the positive length lemma + Node lenLemma = lengthPositive(n); // split whether the string is empty Node n_len_eq_z = n_len.eqNode(d_zero); Node n_len_eq_z_2 = n.eqNode(emp); Node case_empty = nm->mkNode(AND, n_len_eq_z, n_len_eq_z_2); - case_empty = Rewriter::rewrite(case_empty); - Node case_nempty = nm->mkNode(GT, n_len, d_zero); - if (!case_empty.isConst()) + Node case_emptyr = Rewriter::rewrite(case_empty); + if (!case_emptyr.isConst()) { - Node lem = nm->mkNode(OR, case_empty, case_nempty); - lems.push_back(lem); // prefer trying the empty case first // notice that requirePhase must only be called on rewritten literals that // occur in the CNF stream. @@ -427,24 +470,15 @@ Node TermRegistry::getRegisterTermAtomicLemma(Node n, Assert(!n_len_eq_z_2.isConst()); reqPhase[n_len_eq_z_2] = true; } - else if (!case_empty.getConst<bool>()) - { - // the rewriter knows that n is non-empty - lems.push_back(case_nempty); - } else { // If n = "" ---> true or len( n ) = 0 ----> true, then we expect that // n ---> "". Since this method is only called on non-constants n, it must // be that n = "" ^ len( n ) = 0 does not rewrite to true. - Assert(false); + Assert(!case_emptyr.getConst<bool>()); } - if (lems.empty()) - { - return Node::null(); - } - return lems.size() == 1 ? lems[0] : nm->mkNode(AND, lems); + return lenLemma; } Node TermRegistry::getSymbolicDefinition(Node n, std::vector<Node>& exp) const diff --git a/src/theory/strings/term_registry.h b/src/theory/strings/term_registry.h index b68e44b81..d0589be90 100644 --- a/src/theory/strings/term_registry.h +++ b/src/theory/strings/term_registry.h @@ -1,10 +1,10 @@ /********************* */ -/*! \file theory_strings.h +/*! \file term_registry.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tianyi Liang, Tim King + ** Andrew Reynolds, Tim King, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -19,10 +19,13 @@ #include "context/cdhashset.h" #include "context/cdlist.h" +#include "expr/proof_node_manager.h" +#include "theory/eager_proof_generator.h" #include "theory/output_channel.h" #include "theory/strings/infer_info.h" #include "theory/strings/sequences_stats.h" #include "theory/strings/skolem_cache.h" +#include "theory/strings/solver_state.h" #include "theory/uf/equality_engine.h" namespace CVC4 { @@ -46,12 +49,34 @@ class TermRegistry typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap; public: - TermRegistry(context::Context* c, - context::UserContext* u, + TermRegistry(SolverState& s, eq::EqualityEngine& ee, OutputChannel& out, - SequencesStatistics& statistics); + SequencesStatistics& statistics, + ProofNodeManager* pnm); ~TermRegistry(); + /** The eager reduce routine + * + * Constructs a lemma for t that is incomplete, but communicates pertinent + * information about t. This is analogous to StringsPreprocess::reduce. + * + * In practice, we send this lemma eagerly, as soon as t is registered. + * + * @param t The node to reduce, + * @param sc The Skolem cache to use for new variables, + * @return The eager reduction for t. + */ + static Node eagerReduce(Node t, SkolemCache* sc); + /** + * Returns a lemma indicating that the length of a term t whose type is + * string-like has positive length. The exact form of this lemma depends + * on what works best in practice, currently: + * (or (and (= (str.len t) 0) (= t "")) (> (str.len t) 0)) + * + * @param t The node to reduce, + * @return The positive length lemma for t. + */ + static Node lengthPositive(Node t); /** * Preregister term, called when TheoryStrings::preRegisterTerm(n) is called. * This does the following: @@ -184,6 +209,8 @@ class TermRegistry Node d_negOne; /** the cardinality of the alphabet */ uint32_t d_cardSize; + /** Reference to the solver state of the theory of strings. */ + SolverState& d_state; /** Reference to equality engine of the theory of strings. */ eq::EqualityEngine& d_ee; /** Reference to the output channel of the theory of strings. */ @@ -224,6 +251,8 @@ class TermRegistry NodeNodeMap d_proxyVarToLength; /** List of terms that we have register length for */ NodeSet d_lengthLemmaTermsCache; + /** Proof generator, manages proofs for lemmas generated by this class */ + std::unique_ptr<EagerProofGenerator> d_epg; /** Register type * * Ensures the theory solver is setup to handle string-like type tn. In diff --git a/src/theory/strings/theory_strings.cpp b/src/theory/strings/theory_strings.cpp index 5107fa3f9..d1b18df13 100644 --- a/src/theory/strings/theory_strings.cpp +++ b/src/theory/strings/theory_strings.cpp @@ -2,28 +2,22 @@ /*! \file theory_strings.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tianyi Liang, Morgan Deters + ** Andrew Reynolds, Tianyi Liang, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 theory of strings. - ** - ** Implementation of the theory of strings. **/ #include "theory/strings/theory_strings.h" -#include <cmath> - #include "expr/kind.h" #include "options/strings_options.h" #include "options/theory_options.h" -#include "smt/command.h" #include "smt/logic_exception.h" -#include "smt/smt_statistics_registry.h" #include "theory/ext_theory.h" #include "theory/rewriter.h" #include "theory/strings/theory_strings_utils.h" @@ -40,28 +34,6 @@ namespace CVC4 { namespace theory { namespace strings { -std::ostream& operator<<(std::ostream& out, InferStep s) -{ - switch (s) - { - case BREAK: out << "break"; break; - case CHECK_INIT: out << "check_init"; break; - case CHECK_CONST_EQC: out << "check_const_eqc"; break; - case CHECK_EXTF_EVAL: out << "check_extf_eval"; break; - case CHECK_CYCLES: out << "check_cycles"; break; - case CHECK_FLAT_FORMS: out << "check_flat_forms"; break; - case CHECK_NORMAL_FORMS_EQ: out << "check_normal_forms_eq"; break; - case CHECK_NORMAL_FORMS_DEQ: out << "check_normal_forms_deq"; break; - case CHECK_CODES: out << "check_codes"; break; - case CHECK_LENGTH_EQC: out << "check_length_eqc"; break; - case CHECK_EXTF_REDUCTION: out << "check_extf_reduction"; break; - case CHECK_MEMBERSHIP: out << "check_membership"; break; - case CHECK_CARDINALITY: out << "check_cardinality"; break; - default: out << "?"; break; - } - return out; -} - TheoryStrings::TheoryStrings(context::Context* c, context::UserContext* u, OutputChannel& out, @@ -72,15 +44,14 @@ TheoryStrings::TheoryStrings(context::Context* c, d_statistics(), d_equalityEngine(d_notify, c, "theory::strings::ee", true), d_state(c, u, d_equalityEngine, d_valuation), - d_termReg(c, u, d_equalityEngine, out, d_statistics), + d_termReg(d_state, d_equalityEngine, out, d_statistics, nullptr), d_im(nullptr), d_rewriter(&d_statistics.d_rewrites), d_bsolver(nullptr), d_csolver(nullptr), d_esolver(nullptr), d_rsolver(nullptr), - d_stringsFmf(c, u, valuation, d_termReg), - d_strategy_init(false) + d_stringsFmf(c, u, valuation, d_termReg) { setupExtTheory(); ExtTheory* extt = getExtTheory(); @@ -88,7 +59,7 @@ TheoryStrings::TheoryStrings(context::Context* c, d_im.reset( new InferenceManager(c, u, d_state, d_termReg, *extt, out, d_statistics)); // initialize the solvers - d_bsolver.reset(new BaseSolver(c, u, d_state, *d_im)); + d_bsolver.reset(new BaseSolver(d_state, *d_im)); d_csolver.reset(new CoreSolver(c, u, d_state, *d_im, d_termReg, *d_bsolver)); d_esolver.reset(new ExtfSolver(c, u, @@ -108,6 +79,7 @@ TheoryStrings::TheoryStrings(context::Context* c, d_equalityEngine.addFunctionKind(kind::STRING_CONCAT); d_equalityEngine.addFunctionKind(kind::STRING_IN_REGEXP); d_equalityEngine.addFunctionKind(kind::STRING_TO_CODE); + d_equalityEngine.addFunctionKind(kind::SEQ_UNIT); // extended functions d_equalityEngine.addFunctionKind(kind::STRING_STRCTN); @@ -118,6 +90,9 @@ TheoryStrings::TheoryStrings(context::Context* c, d_equalityEngine.addFunctionKind(kind::STRING_STRIDOF); d_equalityEngine.addFunctionKind(kind::STRING_STRREPL); d_equalityEngine.addFunctionKind(kind::STRING_STRREPLALL); + d_equalityEngine.addFunctionKind(kind::STRING_REPLACE_RE); + d_equalityEngine.addFunctionKind(kind::STRING_REPLACE_RE_ALL); + d_equalityEngine.addFunctionKind(kind::STRING_STRREPLALL); d_equalityEngine.addFunctionKind(kind::STRING_TOLOWER); d_equalityEngine.addFunctionKind(kind::STRING_TOUPPER); d_equalityEngine.addFunctionKind(kind::STRING_REV); @@ -135,6 +110,15 @@ TheoryStrings::~TheoryStrings() { } +TheoryRewriter* TheoryStrings::getTheoryRewriter() { return &d_rewriter; } +std::string TheoryStrings::identify() const +{ + return std::string("TheoryStrings"); +} +eq::EqualityEngine* TheoryStrings::getEqualityEngine() +{ + return &d_equalityEngine; +} void TheoryStrings::finishInit() { TheoryModel* tm = d_valuation.getModel(); @@ -231,14 +215,9 @@ bool TheoryStrings::getCurrentSubstitution( int effort, std::vector< Node >& var return true; } -///////////////////////////////////////////////////////////////////////////// -// NOTIFICATIONS -///////////////////////////////////////////////////////////////////////////// - - void TheoryStrings::presolve() { Debug("strings-presolve") << "TheoryStrings::Presolving : get fmf options " << (options::stringFMF() ? "true" : "false") << std::endl; - initializeStrategy(); + d_strat.initializeStrategy(); // if strings fmf is enabled, register the strategy if (options::stringFMF()) @@ -293,7 +272,14 @@ bool TheoryStrings::collectModelInfo(TheoryModel* m) std::unordered_set<Node, NodeHashFunction> >& rst : repSet) { - if (!collectModelInfoType(rst.first, rst.second, m)) + // get partition of strings of equal lengths, per type + std::map<TypeNode, std::vector<std::vector<Node> > > colT; + std::map<TypeNode, std::vector<Node> > ltsT; + std::vector<Node> repVec(rst.second.begin(), rst.second.end()); + d_state.separateByLength(repVec, colT, ltsT); + // now collect model info for the type + TypeNode st = rst.first; + if (!collectModelInfoType(st, rst.second, colT[st], ltsT[st], m)) { return false; } @@ -304,14 +290,12 @@ bool TheoryStrings::collectModelInfo(TheoryModel* m) bool TheoryStrings::collectModelInfoType( TypeNode tn, const std::unordered_set<Node, NodeHashFunction>& repSet, + std::vector<std::vector<Node> >& col, + std::vector<Node>& lts, TheoryModel* m) { NodeManager* nm = NodeManager::currentNM(); - std::vector<Node> nodes(repSet.begin(), repSet.end()); std::map< Node, Node > processed; - std::vector< std::vector< Node > > col; - std::vector< Node > lts; - d_state.separateByLength(nodes, col, lts); //step 1 : get all values for known lengths std::vector< Node > lts_values; std::map<unsigned, Node> values_used; @@ -379,9 +363,15 @@ bool TheoryStrings::collectModelInfoType( NormalForm& nfe = d_csolver->getNormalForm(eqc); if (nfe.d_nf.size() == 1) { + // is it an equivalence class with a seq.unit term? + if (nfe.d_nf[0].getKind() == SEQ_UNIT) + { + pure_eq_assign[eqc] = nfe.d_nf[0]; + Trace("strings-model") << "(unit: " << nfe.d_nf[0] << ") "; + } // does it have a code and the length of these equivalence classes are // one? - if (d_termReg.hasStringCode() && lts_values[i] == d_one) + else if (d_termReg.hasStringCode() && lts_values[i] == d_one) { EqcInfo* eip = d_state.getOrMakeEqcInfo(eqc, false); if (eip && !eip->d_codeTerm.get().isNull()) @@ -435,14 +425,14 @@ bool TheoryStrings::collectModelInfoType( std::unique_ptr<SEnumLen> sel; Trace("strings-model") << "Cardinality of alphabet is " << utils::getAlphabetCardinality() << std::endl; - if (tn.isString()) + if (tn.isString()) // string-only { sel.reset(new StringEnumLen( currLen, currLen, utils::getAlphabetCardinality())); } else { - Unimplemented() << "Collect model info not implemented for type " << tn; + sel.reset(new SeqEnumLen(tn, nullptr, currLen, currLen)); } for (const Node& eqc : pure_eq) { @@ -518,13 +508,15 @@ bool TheoryStrings::collectModelInfoType( } Trace("strings-model") << "String Model : Pure Assigned." << std::endl; //step 4 : assign constants to all other equivalence classes - for( unsigned i=0; i<nodes.size(); i++ ){ - if( processed.find( nodes[i] )==processed.end() ){ - NormalForm& nf = d_csolver->getNormalForm(nodes[i]); + for (const Node& rn : repSet) + { + if (processed.find(rn) == processed.end()) + { + NormalForm& nf = d_csolver->getNormalForm(rn); if (Trace.isOn("strings-model")) { Trace("strings-model") - << "Construct model for " << nodes[i] << " based on normal form "; + << "Construct model for " << rn << " based on normal form "; for (unsigned j = 0, size = nf.d_nf.size(); j < size; j++) { Node n = nf.d_nf[j]; @@ -549,19 +541,24 @@ bool TheoryStrings::collectModelInfoType( nc.push_back(r.isConst() ? r : processed[r]); } Node cc = utils::mkNConcat(nc, tn); - Assert(cc.isConst()); - Trace("strings-model") << "*** Determined constant " << cc << " for " << nodes[i] << std::endl; - processed[nodes[i]] = cc; - if (!m->assertEquality(nodes[i], cc, true)) + Trace("strings-model") + << "*** Determined constant " << cc << " for " << rn << std::endl; + processed[rn] = cc; + if (!m->assertEquality(rn, cc, true)) { // this should never happen due to the model soundness argument // for strings - Unreachable() << "TheoryStrings::collectModelInfoType: " "Inconsistent equality (unprocessed eqc)" << std::endl; return false; } + else if (!cc.isConst()) + { + // the value may be specified by seq.unit components, ensure this + // is marked as the skeleton for constructing values in this class. + m->assertSkeleton(cc); + } } } //Trace("strings-model") << "String Model : Assigned." << std::endl; @@ -627,11 +624,9 @@ void TheoryStrings::check(Effort e) { } d_im->doPendingFacts(); - Assert(d_strategy_init); - std::map<Effort, std::pair<unsigned, unsigned> >::iterator itsr = - d_strat_steps.find(e); + Assert(d_strat.isStrategyInit()); if (!d_state.isInConflict() && !d_valuation.needCheck() - && itsr != d_strat_steps.end()) + && d_strat.hasStrategyEffort(e)) { Trace("strings-check-debug") << "Theory of strings " << e << " effort check " << std::endl; @@ -672,15 +667,13 @@ void TheoryStrings::check(Effort e) { Trace("strings-eqc") << std::endl; } ++(d_statistics.d_checkRuns); - unsigned sbegin = itsr->second.first; - unsigned send = itsr->second.second; bool addedLemma = false; bool addedFact; Trace("strings-check") << "Full effort check..." << std::endl; do{ ++(d_statistics.d_strategyRuns); Trace("strings-check") << " * Run strategy..." << std::endl; - runStrategy(sbegin, send); + runStrategy(e); // flush the facts addedFact = d_im->hasPendingFact(); addedLemma = d_im->hasPendingLemma(); @@ -1033,107 +1026,16 @@ void TheoryStrings::runInferStep(InferStep s, int effort) << std::endl; } -bool TheoryStrings::hasStrategyEffort(Effort e) const -{ - return d_strat_steps.find(e) != d_strat_steps.end(); -} - -void TheoryStrings::addStrategyStep(InferStep s, int effort, bool addBreak) +void TheoryStrings::runStrategy(Theory::Effort e) { - // must run check init first - Assert((s == CHECK_INIT) == d_infer_steps.empty()); - // must use check cycles when using flat forms - Assert(s != CHECK_FLAT_FORMS - || std::find(d_infer_steps.begin(), d_infer_steps.end(), CHECK_CYCLES) - != d_infer_steps.end()); - d_infer_steps.push_back(s); - d_infer_step_effort.push_back(effort); - if (addBreak) - { - d_infer_steps.push_back(BREAK); - d_infer_step_effort.push_back(0); - } -} + std::vector<std::pair<InferStep, int> >::iterator it = d_strat.stepBegin(e); + std::vector<std::pair<InferStep, int> >::iterator stepEnd = + d_strat.stepEnd(e); -void TheoryStrings::initializeStrategy() -{ - // initialize the strategy if not already done so - if (!d_strategy_init) - { - std::map<Effort, unsigned> step_begin; - std::map<Effort, unsigned> step_end; - d_strategy_init = true; - // beginning indices - step_begin[EFFORT_FULL] = 0; - if (options::stringEager()) - { - step_begin[EFFORT_STANDARD] = 0; - } - // add the inference steps - addStrategyStep(CHECK_INIT); - addStrategyStep(CHECK_CONST_EQC); - addStrategyStep(CHECK_EXTF_EVAL, 0); - addStrategyStep(CHECK_CYCLES); - if (options::stringFlatForms()) - { - addStrategyStep(CHECK_FLAT_FORMS); - } - addStrategyStep(CHECK_EXTF_REDUCTION, 1); - if (options::stringEager()) - { - // do only the above inferences at standard effort, if applicable - step_end[EFFORT_STANDARD] = d_infer_steps.size() - 1; - } - if (!options::stringEagerLen()) - { - addStrategyStep(CHECK_REGISTER_TERMS_PRE_NF); - } - addStrategyStep(CHECK_NORMAL_FORMS_EQ); - addStrategyStep(CHECK_EXTF_EVAL, 1); - if (!options::stringEagerLen() && options::stringLenNorm()) - { - addStrategyStep(CHECK_LENGTH_EQC, 0, false); - addStrategyStep(CHECK_REGISTER_TERMS_NF); - } - addStrategyStep(CHECK_NORMAL_FORMS_DEQ); - addStrategyStep(CHECK_CODES); - if (options::stringEagerLen() && options::stringLenNorm()) - { - addStrategyStep(CHECK_LENGTH_EQC); - } - if (options::stringExp() && !options::stringGuessModel()) - { - addStrategyStep(CHECK_EXTF_REDUCTION, 2); - } - addStrategyStep(CHECK_MEMBERSHIP); - addStrategyStep(CHECK_CARDINALITY); - step_end[EFFORT_FULL] = d_infer_steps.size() - 1; - if (options::stringExp() && options::stringGuessModel()) - { - step_begin[EFFORT_LAST_CALL] = d_infer_steps.size(); - // these two steps are run in parallel - addStrategyStep(CHECK_EXTF_REDUCTION, 2, false); - addStrategyStep(CHECK_EXTF_EVAL, 3); - step_end[EFFORT_LAST_CALL] = d_infer_steps.size() - 1; - } - // set the beginning/ending ranges - for (const std::pair<const Effort, unsigned>& it_begin : step_begin) - { - Effort e = it_begin.first; - std::map<Effort, unsigned>::iterator it_end = step_end.find(e); - Assert(it_end != step_end.end()); - d_strat_steps[e] = - std::pair<unsigned, unsigned>(it_begin.second, it_end->second); - } - } -} - -void TheoryStrings::runStrategy(unsigned sbegin, unsigned send) -{ Trace("strings-process") << "----check, next round---" << std::endl; - for (unsigned i = sbegin; i <= send; i++) + while (it != stepEnd) { - InferStep curr = d_infer_steps[i]; + InferStep curr = it->first; if (curr == BREAK) { if (d_im->hasProcessed()) @@ -1143,12 +1045,13 @@ void TheoryStrings::runStrategy(unsigned sbegin, unsigned send) } else { - runInferStep(curr, d_infer_step_effort[i]); + runInferStep(curr, it->second); if (d_state.isInConflict()) { break; } } + ++it; } Trace("strings-process") << "----finished round---" << std::endl; } diff --git a/src/theory/strings/theory_strings.h b/src/theory/strings/theory_strings.h index 7c99b6968..368c13a2d 100644 --- a/src/theory/strings/theory_strings.h +++ b/src/theory/strings/theory_strings.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tianyi Liang, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -35,8 +35,8 @@ #include "theory/strings/regexp_operation.h" #include "theory/strings/regexp_solver.h" #include "theory/strings/sequences_stats.h" -#include "theory/strings/skolem_cache.h" #include "theory/strings/solver_state.h" +#include "theory/strings/strategy.h" #include "theory/strings/strings_fmf.h" #include "theory/strings/strings_rewriter.h" #include "theory/strings/term_registry.h" @@ -48,91 +48,72 @@ namespace theory { namespace strings { /** - * Decision procedure for strings. - * + * A theory solver for strings. At a high level, the solver implements + * techniques described in: + * - Liang et al, CAV 2014, + * - Reynolds et al, CAV 2017, + * - Reynolds et al, IJCAR 2020. + * Its rewriter is described in: + * - Reynolds et al, CAV 2019. */ - -/** inference steps - * - * Corresponds to a step in the overall strategy of the strings solver. For - * details on the individual steps, see documentation on the inference schemas - * within TheoryStrings. - */ -enum InferStep -{ - // indicates that the strategy should break if lemmas or facts are added - BREAK, - // check initial - CHECK_INIT, - // check constant equivalence classes - CHECK_CONST_EQC, - // check extended function evaluation - CHECK_EXTF_EVAL, - // check cycles - CHECK_CYCLES, - // check flat forms - CHECK_FLAT_FORMS, - // check register terms pre-normal forms - CHECK_REGISTER_TERMS_PRE_NF, - // check normal forms equalities - CHECK_NORMAL_FORMS_EQ, - // check normal forms disequalities - CHECK_NORMAL_FORMS_DEQ, - // check codes - CHECK_CODES, - // check lengths for equivalence classes - CHECK_LENGTH_EQC, - // check register terms for normal forms - CHECK_REGISTER_TERMS_NF, - // check extended function reductions - CHECK_EXTF_REDUCTION, - // check regular expression memberships - CHECK_MEMBERSHIP, - // check cardinality - CHECK_CARDINALITY, -}; -std::ostream& operator<<(std::ostream& out, Inference i); - class TheoryStrings : public Theory { friend class InferenceManager; - typedef context::CDList<Node> NodeList; - typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap; - typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap; - typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap; typedef context::CDHashSet<Node, NodeHashFunction> NodeSet; typedef context::CDHashSet<TypeNode, TypeNodeHashFunction> TypeNodeSet; - public: TheoryStrings(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo); ~TheoryStrings(); - /** finish initialization */ void finishInit() override; - - TheoryRewriter* getTheoryRewriter() override { return &d_rewriter; } - + /** Get the theory rewriter of this class */ + TheoryRewriter* getTheoryRewriter() override; + /** Set the master equality engine */ void setMasterEqualityEngine(eq::EqualityEngine* eq) override; - - std::string identify() const override { return std::string("TheoryStrings"); } - - public: + /** Identify this theory */ + std::string identify() const override; + /** Propagate */ void propagate(Effort e) override; - bool propagate(TNode literal); + /** Explain */ Node explain(TNode literal) override; - eq::EqualityEngine* getEqualityEngine() override { return &d_equalityEngine; } + /** Get the equality engine */ + eq::EqualityEngine* getEqualityEngine() override; + /** Get current substitution */ bool getCurrentSubstitution(int effort, std::vector<Node>& vars, std::vector<Node>& subs, std::map<Node, std::vector<Node> >& exp) override; + /** presolve */ + void presolve() override; + /** shutdown */ + void shutdown() override {} + /** add shared term */ + void addSharedTerm(TNode n) override; + /** get equality status */ + EqualityStatus getEqualityStatus(TNode a, TNode b) override; + /** preregister term */ + void preRegisterTerm(TNode n) override; + /** Expand definition */ + Node expandDefinition(Node n) override; + /** Check at effort e */ + void check(Effort e) override; + /** needs check last effort */ + bool needsCheckLastEffort() override; + /** Conflict when merging two constants */ + void conflict(TNode a, TNode b); + /** called when a new equivalence class is created */ + void eqNotifyNewClass(TNode t); + /** preprocess rewrite */ + Node ppRewrite(TNode atom) override; /** * Get all relevant information in this theory regarding the current * model. Return false if a contradiction is discovered. */ bool collectModelInfo(TheoryModel* m) override; - // NotifyClass for equality engine + private: + /** NotifyClass for equality engine */ class NotifyClass : public eq::EqualityEngineNotify { public: NotifyClass(TheoryStrings& ts) : d_str(ts), d_state(ts.d_state) {} @@ -202,74 +183,8 @@ class TheoryStrings : public Theory { /** The solver state of the theory of strings */ SolverState& d_state; };/* class TheoryStrings::NotifyClass */ - - private: - // Constants - Node d_emptyString; - Node d_true; - Node d_false; - Node d_zero; - Node d_one; - Node d_neg_one; - /** the cardinality of the alphabet */ - uint32_t d_cardSize; - /** The notify class */ - NotifyClass d_notify; - - /** - * Statistics for the theory of strings/sequences. All statistics for these - * theories is collected in this object. - */ - SequencesStatistics d_statistics; - - /** Equaltity engine */ - eq::EqualityEngine d_equalityEngine; - /** The solver state object */ - SolverState d_state; - /** The term registry for this theory */ - TermRegistry d_termReg; - /** The (custom) output channel of the theory of strings */ - std::unique_ptr<InferenceManager> d_im; - - private: - std::map< Node, Node > d_eqc_to_len_term; - - - ///////////////////////////////////////////////////////////////////////////// - // NOTIFICATIONS - ///////////////////////////////////////////////////////////////////////////// - public: - void presolve() override; - void shutdown() override {} - - ///////////////////////////////////////////////////////////////////////////// - // MAIN SOLVER - ///////////////////////////////////////////////////////////////////////////// - private: - void addSharedTerm(TNode n) override; - EqualityStatus getEqualityStatus(TNode a, TNode b) override; - - private: - void addCarePairs(TNodeTrie* t1, - TNodeTrie* t2, - unsigned arity, - unsigned depth); - - public: - /** preregister term */ - void preRegisterTerm(TNode n) override; - /** Expand definition */ - Node expandDefinition(Node n) override; - /** Check at effort e */ - void check(Effort e) override; - /** needs check last effort */ - bool needsCheckLastEffort() override; - /** Conflict when merging two constants */ - void conflict(TNode a, TNode b); - /** called when a new equivalence class is created */ - void eqNotifyNewClass(TNode t); - - protected: + /** propagate method */ + bool propagate(TNode literal); /** compute care graph */ void computeCareGraph() override; /** @@ -277,17 +192,25 @@ class TheoryStrings : public Theory { * the care graph in the above function. */ bool areCareDisequal(TNode x, TNode y); - + /** Add care pairs */ + void addCarePairs(TNodeTrie* t1, + TNodeTrie* t2, + unsigned arity, + unsigned depth); /** Collect model info for type tn * * Assigns model values (in m) to all relevant terms of the string-like type - * tn in the current context, which are stored in repSet. + * tn in the current context, which are stored in repSet. Furthermore, + * col is a partition of repSet where equivalence classes are grouped into + * sets having equal length, where these lengths are stored in lts. * * Returns false if a conflict is discovered while doing this assignment. */ bool collectModelInfoType( TypeNode tn, const std::unordered_set<Node, NodeHashFunction>& repSet, + std::vector<std::vector<Node> >& col, + std::vector<Node>& lts, TheoryModel* m); /** assert pending fact @@ -299,38 +222,6 @@ class TheoryStrings : public Theory { * of atom, including calls to registerTerm. */ void assertPendingFact(Node atom, bool polarity, Node exp); - - // Symbolic Regular Expression - private: - /** The theory rewriter for this theory. */ - StringsRewriter d_rewriter; - /** - * The base solver, responsible for reasoning about congruent terms and - * inferring constants for equivalence classes. - */ - std::unique_ptr<BaseSolver> d_bsolver; - /** - * The core solver, responsible for reasoning about string concatenation - * with length constraints. - */ - std::unique_ptr<CoreSolver> d_csolver; - /** - * Extended function solver, responsible for reductions and simplifications - * involving extended string functions. - */ - std::unique_ptr<ExtfSolver> d_esolver; - /** regular expression solver module */ - std::unique_ptr<RegExpSolver> d_rsolver; - /** regular expression elimination module */ - RegExpElimination d_regexp_elim; - /** Strings finite model finding decision strategy */ - StringsFmf d_stringsFmf; - - public: - // ppRewrite - Node ppRewrite(TNode atom) override; - - private: //-----------------------inference steps /** check register terms pre-normal forms * @@ -356,42 +247,58 @@ class TheoryStrings : public Theory { */ void checkRegisterTermsNormalForms(); //-----------------------end inference steps - - //-----------------------representation of the strategy - /** is strategy initialized */ - bool d_strategy_init; /** run the given inference step */ void runInferStep(InferStep s, int effort); - /** the strategy */ - std::vector<InferStep> d_infer_steps; - /** the effort levels */ - std::vector<int> d_infer_step_effort; - /** the range (begin, end) of steps to run at given efforts */ - std::map<Effort, std::pair<unsigned, unsigned> > d_strat_steps; - /** do we have a strategy for effort e? */ - bool hasStrategyEffort(Effort e) const; - /** initialize the strategy - * - * This adds (s,effort) as a strategy step to the vectors d_infer_steps and - * d_infer_step_effort. This indicates that a call to runInferStep should - * be run as the next step in the strategy. If addBreak is true, we add - * a BREAK to the strategy following this step. + /** run strategy for effort e */ + void runStrategy(Theory::Effort e); + /** Commonly used constants */ + Node d_true; + Node d_false; + Node d_zero; + Node d_one; + Node d_neg_one; + /** the cardinality of the alphabet */ + uint32_t d_cardSize; + /** The notify class */ + NotifyClass d_notify; + /** + * Statistics for the theory of strings/sequences. All statistics for these + * theories is collected in this object. */ - void addStrategyStep(InferStep s, int effort = 0, bool addBreak = true); - /** initialize the strategy - * - * This initializes the above information based on the options. This makes - * a series of calls to addStrategyStep above. + SequencesStatistics d_statistics; + /** Equaltity engine */ + eq::EqualityEngine d_equalityEngine; + /** The solver state object */ + SolverState d_state; + /** The term registry for this theory */ + TermRegistry d_termReg; + /** The (custom) output channel of the theory of strings */ + std::unique_ptr<InferenceManager> d_im; + /** The theory rewriter for this theory. */ + StringsRewriter d_rewriter; + /** + * The base solver, responsible for reasoning about congruent terms and + * inferring constants for equivalence classes. */ - void initializeStrategy(); - /** run strategy - * - * This executes the inference steps starting at index sbegin and ending at - * index send. We exit if any step in this sequence adds a lemma or infers a - * fact. + std::unique_ptr<BaseSolver> d_bsolver; + /** + * The core solver, responsible for reasoning about string concatenation + * with length constraints. */ - void runStrategy(unsigned sbegin, unsigned send); - //-----------------------end representation of the strategy + std::unique_ptr<CoreSolver> d_csolver; + /** + * Extended function solver, responsible for reductions and simplifications + * involving extended string functions. + */ + std::unique_ptr<ExtfSolver> d_esolver; + /** regular expression solver module */ + std::unique_ptr<RegExpSolver> d_rsolver; + /** regular expression elimination module */ + RegExpElimination d_regexp_elim; + /** Strings finite model finding decision strategy */ + StringsFmf d_stringsFmf; + /** The representation of the strategy */ + Strategy d_strat; };/* class TheoryStrings */ }/* CVC4::theory::strings namespace */ diff --git a/src/theory/strings/theory_strings_preprocess.cpp b/src/theory/strings/theory_strings_preprocess.cpp index 939146a3d..af946567b 100644 --- a/src/theory/strings/theory_strings_preprocess.cpp +++ b/src/theory/strings/theory_strings_preprocess.cpp @@ -2,9 +2,9 @@ /*! \file theory_strings_preprocess.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tianyi Liang + ** Andrew Reynolds, Andres Noetzli, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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,27 +483,194 @@ 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; } + else if (t.getKind() == STRING_REPLACE_RE) + { + Node x = t[0]; + Node y = t[1]; + Node z = t[2]; + Node k = sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "k"); + + std::vector<Node> emptyVec; + Node sigmaStar = + nm->mkNode(REGEXP_STAR, nm->mkNode(REGEXP_SIGMA, emptyVec)); + Node re = nm->mkNode(REGEXP_CONCAT, sigmaStar, y, sigmaStar); + // in_re(x, re.++(_*, y, _*)) + Node hasMatch = nm->mkNode(STRING_IN_REGEXP, x, re); + + // in_re("", y) + Node matchesEmpty = + nm->mkNode(STRING_IN_REGEXP, nm->mkConst(String("")), y); + // k = z ++ x + Node res1 = k.eqNode(nm->mkNode(STRING_CONCAT, z, x)); + + Node k1 = + sc->mkSkolemCached(x, y, SkolemCache::SK_FIRST_MATCH_PRE, "rre_pre"); + Node k2 = + sc->mkSkolemCached(x, y, SkolemCache::SK_FIRST_MATCH, "rre_match"); + Node k3 = + sc->mkSkolemCached(x, y, SkolemCache::SK_FIRST_MATCH_POST, "rre_post"); + // x = k1 ++ k2 ++ k3 + Node splitX = x.eqNode(nm->mkNode(STRING_CONCAT, k1, k2, k3)); + // ~in_re(k1 ++ str.substr(k2, 0, str.len(k2) - 1), re.++(_*, y, _*)) + Node k2len = nm->mkNode(STRING_LENGTH, k2); + Node firstMatch = + nm->mkNode( + STRING_IN_REGEXP, + nm->mkNode( + STRING_CONCAT, + k1, + nm->mkNode( + STRING_SUBSTR, k2, zero, nm->mkNode(MINUS, k2len, one))), + re) + .negate(); + // in_re(k2, y) + Node k2Match = nm->mkNode(STRING_IN_REGEXP, k2, y); + // k = k1 ++ z ++ k3 + Node res2 = k.eqNode(nm->mkNode(STRING_CONCAT, k1, z, k3)); + + // IF in_re(x, re.++(_*, y, _*)) + // THEN: + // IF in_re("", y) + // THEN: k = z ++ x + // ELSE: + // x = k1 ++ k2 ++ k3 ^ + // ~in_re(k1 ++ substr(k2, 0, str.len(k2) - 1), re.++(_*, y, _*)) ^ + // in_re(k2, y) ^ k = k1 ++ z ++ k3 + // ELSE: k = x + asserts.push_back(nm->mkNode( + ITE, + hasMatch, + nm->mkNode(ITE, + matchesEmpty, + res1, + nm->mkNode(AND, splitX, firstMatch, k2Match, res2)), + k.eqNode(x))); + retNode = k; + } + else if (t.getKind() == STRING_REPLACE_RE_ALL) + { + Node x = t[0]; + Node y = t[1]; + Node z = t[2]; + Node k = sc->mkSkolemCached(t, SkolemCache::SK_PURIFY, "k"); + + 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, t.getType())); + TypeNode ufType = nm->mkFunctionType(argTypes, nm->integerType()); + Node uf = sc->mkTypedSkolemCached( + ufType, x, y, SkolemCache::SK_OCCUR_INDEX, "Uf"); + Node ul = + sc->mkTypedSkolemCached(ufType, x, y, SkolemCache::SK_OCCUR_LEN, "Ul"); + + Node emp = Word::mkEmptyWord(t.getType()); + + std::vector<Node> emptyVec; + Node sigmaStar = + nm->mkNode(REGEXP_STAR, nm->mkNode(REGEXP_SIGMA, emptyVec)); + Node yp = nm->mkNode(REGEXP_DIFF, y, nm->mkNode(STRING_TO_REGEXP, emp)); + Node re = nm->mkNode(REGEXP_CONCAT, sigmaStar, yp, sigmaStar); + // in_re(x, _* ++ y' ++ _*) + Node hasMatch = nm->mkNode(STRING_IN_REGEXP, x, re); + + Node ufno = nm->mkNode(APPLY_UF, uf, numOcc); + Node usno = nm->mkNode(APPLY_UF, us, numOcc); + Node rem = nm->mkNode(STRING_SUBSTR, x, ufno, nm->mkNode(STRING_LENGTH, x)); + + std::vector<Node> lemmas; + // numOcc > 0 + lemmas.push_back(nm->mkNode(GT, numOcc, zero)); + // k = Us(0) + lemmas.push_back(k.eqNode(nm->mkNode(APPLY_UF, us, zero))); + // Us(numOcc) = substr(x, Uf(numOcc)) + lemmas.push_back(usno.eqNode(rem)); + // Uf(0) = 0 + lemmas.push_back(nm->mkNode(APPLY_UF, uf, zero).eqNode(zero)); + // not(in_re(substr(x, Uf(numOcc)), re.++(_*, y', _*))) + lemmas.push_back(nm->mkNode(STRING_IN_REGEXP, rem, re).negate()); + + Node i = SkolemCache::mkIndexVar(t); + Node bvli = nm->mkNode(BOUND_VAR_LIST, i); + Node bound = + nm->mkNode(AND, nm->mkNode(GEQ, i, zero), nm->mkNode(LT, i, numOcc)); + Node ip1 = nm->mkNode(PLUS, i, one); + Node ufi = nm->mkNode(APPLY_UF, uf, i); + Node uli = nm->mkNode(APPLY_UF, ul, i); + Node ufip1 = nm->mkNode(APPLY_UF, uf, ip1); + Node ii = nm->mkNode(MINUS, ufip1, uli); + Node match = nm->mkNode(STRING_SUBSTR, x, ii, uli); + Node pfxMatch = + nm->mkNode(STRING_SUBSTR, x, ufi, nm->mkNode(MINUS, ii, ufi)); + Node nonMatch = + nm->mkNode(STRING_SUBSTR, + x, + ufi, + nm->mkNode(MINUS, nm->mkNode(MINUS, ufip1, one), ufi)); + + std::vector<Node> flem; + // Ul(i) > 0 + flem.push_back(nm->mkNode(GT, uli, zero)); + // Uf(i + 1) >= Uf(i) + Ul(i) + flem.push_back(nm->mkNode(GEQ, ufip1, nm->mkNode(PLUS, ufi, uli))); + // in_re(substr(x, ii, Ul(i)), y') + flem.push_back(nm->mkNode(STRING_IN_REGEXP, match, yp)); + // ~in_re(substr(x, Uf(i), Uf(i + 1) - 1 - Uf(i)), re.++(_*, y', _*)) + flem.push_back(nm->mkNode(STRING_IN_REGEXP, nonMatch, re).negate()); + // Us(i) = substr(x, Uf(i), ii - Uf(i)) ++ z ++ Us(i + 1) + flem.push_back( + nm->mkNode(APPLY_UF, us, i) + .eqNode(nm->mkNode( + STRING_CONCAT, pfxMatch, z, nm->mkNode(APPLY_UF, us, ip1)))); + + Node forall = nm->mkNode( + FORALL, bvli, nm->mkNode(OR, bound.negate(), nm->mkNode(AND, flem))); + lemmas.push_back(forall); + + // IF in_re(x, re.++(_*, y', _*)) + // THEN: + // numOcc > 0 ^ + // k = Us(0) ^ Us(numOcc) = substr(x, Uf(numOcc)) ^ + // Uf(0) = 0 ^ not(in_re(substr(x, Uf(numOcc)), re.++(_*, y', _*))) + // forall i. 0 <= i < nummOcc => + // Ul(i) > 0 ^ + // Uf(i + 1) >= Uf(i) + Ul(i) ^ + // in_re(substr(x, ii, Ul(i)), y') ^ + // ~in_re(substr(x, Uf(i), Uf(i + 1) - 1 - Uf(i)), re.++(_*, y', _*)) ^ + // Us(i) = substr(x, Uf(i), ii - Uf(i)) ++ z ++ Us(i + 1) + // where ii = Uf(i + 1) - Ul(i) + // ELSE: k = x + // where y' = re.diff(y, "") + // + // Conceptually, y' is the regex y but excluding the empty string (because + // we do not want to match empty strings), numOcc is the number of shortest + // matches of y' in x, Uf(i) is the end position of the i-th match, Ul(i) + // is the length of the i^th match, and Us(i) is the result of processing + // the remainder after processing the i^th occurrence of y in x. + asserts.push_back( + nm->mkNode(ITE, hasMatch, nm->mkNode(AND, lemmas), k.eqNode(x))); + retNode = k; + } 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 +684,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 +696,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 +704,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 +727,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 +739,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 +802,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 +837,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 +855,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 +865,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 +895,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..113d909a8 100644 --- a/src/theory/strings/theory_strings_preprocess.h +++ b/src/theory/strings/theory_strings_preprocess.h @@ -2,9 +2,9 @@ /*! \file theory_strings_preprocess.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tianyi Liang + ** Andrew Reynolds, Tianyi Liang, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..9f66c5f82 100644 --- a/src/theory/strings/theory_strings_type_rules.h +++ b/src/theory/strings/theory_strings_type_rules.h @@ -2,9 +2,9 @@ /*! \file theory_strings_type_rules.h ** \verbatim ** Top contributors (to current version): - ** Tianyi Liang, Morgan Deters, Tim King + ** Andrew Reynolds, Tianyi Liang, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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/theory_strings_utils.cpp b/src/theory/strings/theory_strings_utils.cpp index e80607acf..3cf14fead 100644 --- a/src/theory/strings/theory_strings_utils.cpp +++ b/src/theory/strings/theory_strings_utils.cpp @@ -2,9 +2,9 @@ /*! \file theory_strings_utils.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -274,6 +274,8 @@ std::pair<bool, std::vector<Node> > collectEmptyEqs(Node x) allEmptyEqs, std::vector<Node>(emptyNodes.begin(), emptyNodes.end())); } +bool isConstantLike(Node n) { return n.isConst() || n.getKind() == SEQ_UNIT; } + bool isUnboundedWildcard(const std::vector<Node>& rs, size_t start) { size_t i = start; diff --git a/src/theory/strings/theory_strings_utils.h b/src/theory/strings/theory_strings_utils.h index fd6e5122b..803a5ffea 100644 --- a/src/theory/strings/theory_strings_utils.h +++ b/src/theory/strings/theory_strings_utils.h @@ -2,9 +2,9 @@ /*! \file theory_strings_utils.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -148,6 +148,15 @@ Node mkSubstrChain(Node base, std::pair<bool, std::vector<Node> > collectEmptyEqs(Node x); /** + * Return if a string-like term n is "constant-like", that is, either a + * constant string/sequence, or an application of seq.unit. + * + * @param n The string-like term + * @return true if n is constant-like. + */ +bool isConstantLike(Node n); + +/** * Given a vector of regular expression nodes and a start index that points to * a wildcard, returns true if the wildcard is unbounded (i.e. it is followed * by an arbitrary number of `re.allchar`s and then an `re.*(re.allchar)`. If diff --git a/src/theory/strings/type_enumerator.cpp b/src/theory/strings/type_enumerator.cpp index d24206860..6d3949514 100644 --- a/src/theory/strings/type_enumerator.cpp +++ b/src/theory/strings/type_enumerator.cpp @@ -2,9 +2,9 @@ /*! \file type_enumerator.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..602d73059 100644 --- a/src/theory/strings/type_enumerator.h +++ b/src/theory/strings/type_enumerator.h @@ -2,9 +2,9 @@ /*! \file type_enumerator.h ** \verbatim ** Top contributors (to current version): - ** Tianyi Liang, Tim King, Andrew Reynolds + ** Andrew Reynolds, Tianyi Liang, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -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..35b315e35 100644 --- a/src/theory/strings/word.cpp +++ b/src/theory/strings/word.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 @@ -14,6 +14,7 @@ #include "theory/strings/word.h" +#include "expr/sequence.h" #include "util/string.h" using namespace CVC4::kind; @@ -26,25 +27,20 @@ Node Word::mkEmptyWord(TypeNode tn) { if (tn.isString()) { - return mkEmptyWord(CONST_STRING); + std::vector<unsigned> vec; + return NodeManager::currentNM()->mkConst(String(vec)); } - Unimplemented(); - return Node::null(); -} - -Node Word::mkEmptyWord(Kind k) -{ - NodeManager* nm = NodeManager::currentNM(); - if (k == CONST_STRING) + else if (tn.isSequence()) { - std::vector<unsigned> vec; - return nm->mkConst(String(vec)); + std::vector<Expr> seq; + return NodeManager::currentNM()->mkConst( + ExprSequence(tn.getSequenceElementType().toType(), seq)); } 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 +57,23 @@ 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.getSequenceElementType().toType(), seq)); + } Unimplemented(); return Node::null(); } @@ -72,17 +85,21 @@ size_t Word::getLength(TNode x) { return x.getConst<String>().size(); } - Unimplemented(); + else if (k == CONST_SEQUENCE) + { + return x.getConst<ExprSequence>().getSequence().size(); + } + Unimplemented() << "Word::getLength on " << x; return 0; } std::vector<Node> Word::getChars(TNode x) { Kind k = x.getKind(); + std::vector<Node> ret; + NodeManager* nm = NodeManager::currentNM(); if (k == CONST_STRING) { - std::vector<Node> ret; - NodeManager* nm = NodeManager::currentNM(); std::vector<unsigned> ccVec; const std::vector<unsigned>& cvec = x.getConst<String>().getVec(); for (unsigned chVal : cvec) @@ -94,8 +111,18 @@ std::vector<Node> Word::getChars(TNode x) } return ret; } + else if (k == CONST_SEQUENCE) + { + Type t = x.getConst<ExprSequence>().getType(); + const Sequence& sx = x.getConst<ExprSequence>().getSequence(); + const std::vector<Node>& vec = sx.getVec(); + for (const Node& v : vec) + { + ret.push_back(nm->mkConst(ExprSequence(t, {v.toExpr()}))); + } + return ret; + } Unimplemented(); - std::vector<Node> ret; return ret; } @@ -111,6 +138,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 +159,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 +180,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 +201,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 +222,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 +243,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 +267,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 +289,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 +307,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 +328,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 +348,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 +369,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 +390,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..3b15b763a 100644 --- a/src/theory/strings/word.h +++ b/src/theory/strings/word.h @@ -2,9 +2,9 @@ /*! \file word.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -33,11 +33,8 @@ class Word /** make empty constant of type tn */ static Node mkEmptyWord(TypeNode tn); - /** make empty constant of kind k */ - 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 +136,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/subs_minimize.cpp b/src/theory/subs_minimize.cpp index e5e6e392e..fdf3c3cc8 100644 --- a/src/theory/subs_minimize.cpp +++ b/src/theory/subs_minimize.cpp @@ -2,9 +2,9 @@ /*! \file subs_minimize.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/subs_minimize.h b/src/theory/subs_minimize.h index 3ffd588f1..c2b847f15 100644 --- a/src/theory/subs_minimize.h +++ b/src/theory/subs_minimize.h @@ -2,9 +2,9 @@ /*! \file subs_minimize.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/substitutions.cpp b/src/theory/substitutions.cpp index 7728456a7..671cf9b99 100644 --- a/src/theory/substitutions.cpp +++ b/src/theory/substitutions.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Clark Barrett, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/substitutions.h b/src/theory/substitutions.h index c19fb12f6..bb59069dd 100644 --- a/src/theory/substitutions.h +++ b/src/theory/substitutions.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Dejan Jovanovic, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/term_registration_visitor.cpp b/src/theory/term_registration_visitor.cpp index 2b6a847dc..bf7cab4e3 100644 --- a/src/theory/term_registration_visitor.cpp +++ b/src/theory/term_registration_visitor.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/term_registration_visitor.h b/src/theory/term_registration_visitor.h index cdb411c16..6c6696f64 100644 --- a/src/theory/term_registration_visitor.h +++ b/src/theory/term_registration_visitor.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/theory.cpp b/src/theory/theory.cpp index 3069461fa..9e72371d0 100644 --- a/src/theory/theory.cpp +++ b/src/theory/theory.cpp @@ -2,9 +2,9 @@ /*! \file theory.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Dejan Jovanovic, Andrew Reynolds + ** Tim King, Mathias Preiner, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -271,6 +271,11 @@ void Theory::debugPrintFacts() const{ bool Theory::isLegalElimination(TNode x, TNode val) { Assert(x.isVar()); + if (x.getKind() == kind::BOOLEAN_TERM_VARIABLE + || val.getKind() == kind::BOOLEAN_TERM_VARIABLE) + { + return false; + } if (expr::hasSubterm(val, x)) { return false; diff --git a/src/theory/theory.h b/src/theory/theory.h index 366a943ef..a5234cf25 100644 --- a/src/theory/theory.h +++ b/src/theory/theory.h @@ -2,9 +2,9 @@ /*! \file theory.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic, Tim King + ** Dejan Jovanovic, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp index 2c27c6054..2472ae023 100644 --- a/src/theory/theory_engine.cpp +++ b/src/theory/theory_engine.cpp @@ -2,9 +2,9 @@ /*! \file theory_engine.cpp ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Morgan Deters, Andrew Reynolds + ** Dejan Jovanovic, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -127,144 +127,6 @@ std::string getTheoryString(theory::TheoryId id) } } -theory::LemmaStatus TheoryEngine::EngineOutputChannel::lemma(TNode lemma, - ProofRule rule, - bool removable, - bool preprocess, - bool sendAtoms) { - Debug("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" - << lemma << ")" - << ", preprocess = " << preprocess << std::endl; - ++d_statistics.lemmas; - d_engine->d_outputChannelUsed = true; - - PROOF({ registerLemmaRecipe(lemma, lemma, preprocess, d_theory); }); - - theory::LemmaStatus result = - d_engine->lemma(lemma, rule, false, removable, preprocess, - sendAtoms ? d_theory : theory::THEORY_LAST); - return result; -} - -void TheoryEngine::EngineOutputChannel::registerLemmaRecipe(Node lemma, Node originalLemma, bool preprocess, theory::TheoryId theoryId) { - // During CNF conversion, conjunctions will be broken down into - // multiple lemmas. In order for the recipes to match, we have to do - // the same here. - NodeManager* nm = NodeManager::currentNM(); - - if (preprocess) - lemma = d_engine->preprocess(lemma); - - bool negated = (lemma.getKind() == kind::NOT); - Node nnLemma = negated ? lemma[0] : lemma; - - switch (nnLemma.getKind()) { - - case kind::AND: - if (!negated) { - for (unsigned i = 0; i < nnLemma.getNumChildren(); ++i) - registerLemmaRecipe(nnLemma[i], originalLemma, false, theoryId); - } else { - NodeBuilder<> builder(kind::OR); - for (unsigned i = 0; i < nnLemma.getNumChildren(); ++i) - builder << nnLemma[i].negate(); - - Node disjunction = (builder.getNumChildren() == 1) ? builder[0] : builder; - registerLemmaRecipe(disjunction, originalLemma, false, theoryId); - } - break; - - case kind::EQUAL: - if( nnLemma[0].getType().isBoolean() ){ - if (!negated) { - registerLemmaRecipe(nm->mkNode(kind::OR, nnLemma[0], nnLemma[1].negate()), originalLemma, false, theoryId); - registerLemmaRecipe(nm->mkNode(kind::OR, nnLemma[0].negate(), nnLemma[1]), originalLemma, false, theoryId); - } else { - registerLemmaRecipe(nm->mkNode(kind::OR, nnLemma[0], nnLemma[1]), originalLemma, false, theoryId); - registerLemmaRecipe(nm->mkNode(kind::OR, nnLemma[0].negate(), nnLemma[1].negate()), originalLemma, false, theoryId); - } - } - break; - - case kind::ITE: - if (!negated) { - registerLemmaRecipe(nm->mkNode(kind::OR, nnLemma[0].negate(), nnLemma[1]), originalLemma, false, theoryId); - registerLemmaRecipe(nm->mkNode(kind::OR, nnLemma[0], nnLemma[2]), originalLemma, false, theoryId); - } else { - registerLemmaRecipe(nm->mkNode(kind::OR, nnLemma[0].negate(), nnLemma[1].negate()), originalLemma, false, theoryId); - registerLemmaRecipe(nm->mkNode(kind::OR, nnLemma[0], nnLemma[2].negate()), originalLemma, false, theoryId); - } - break; - - default: - break; - } - - // Theory lemmas have one step that proves the empty clause - LemmaProofRecipe proofRecipe; - Node emptyNode; - LemmaProofRecipe::ProofStep proofStep(theoryId, emptyNode); - - // Remember the original lemma, so we can report this later when asked to - proofRecipe.setOriginalLemma(originalLemma); - - // Record the assertions and rewrites - Node rewritten; - if (lemma.getKind() == kind::OR) { - for (unsigned i = 0; i < lemma.getNumChildren(); ++i) { - rewritten = theory::Rewriter::rewrite(lemma[i]); - if (rewritten != lemma[i]) { - proofRecipe.addRewriteRule(lemma[i].negate(), rewritten.negate()); - } - proofStep.addAssertion(lemma[i]); - proofRecipe.addBaseAssertion(rewritten); - } - } else { - rewritten = theory::Rewriter::rewrite(lemma); - if (rewritten != lemma) { - proofRecipe.addRewriteRule(lemma.negate(), rewritten.negate()); - } - proofStep.addAssertion(lemma); - proofRecipe.addBaseAssertion(rewritten); - } - proofRecipe.addStep(proofStep); - ProofManager::getCnfProof()->setProofRecipe(&proofRecipe); -} - -theory::LemmaStatus TheoryEngine::EngineOutputChannel::splitLemma( - TNode lemma, bool removable) { - Debug("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" - << lemma << ")" << std::endl; - ++d_statistics.lemmas; - d_engine->d_outputChannelUsed = true; - - Debug("pf::explain") << "TheoryEngine::EngineOutputChannel::splitLemma( " - << lemma << " )" << std::endl; - theory::LemmaStatus result = - d_engine->lemma(lemma, RULE_SPLIT, false, removable, false, d_theory); - return result; -} - -bool TheoryEngine::EngineOutputChannel::propagate(TNode literal) { - Debug("theory::propagate") << "EngineOutputChannel<" << d_theory - << ">::propagate(" << literal << ")" << std::endl; - ++d_statistics.propagations; - d_engine->d_outputChannelUsed = true; - return d_engine->propagate(literal, d_theory); -} - -void TheoryEngine::EngineOutputChannel::conflict(TNode conflictNode, - std::unique_ptr<Proof> proof) -{ - Trace("theory::conflict") - << "EngineOutputChannel<" << d_theory << ">::conflict(" << conflictNode - << ")" << std::endl; - Assert(!proof); // Theory shouldn't be producing proofs yet - ++d_statistics.conflicts; - d_engine->d_outputChannelUsed = true; - d_engine->conflict(conflictNode, d_theory); -} - void TheoryEngine::finishInit() { //initialize the quantifiers engine, master equality engine, model, model builder if( d_logicInfo.isQuantified() ) { @@ -327,7 +189,6 @@ TheoryEngine::TheoryEngine(context::Context* context, d_curr_model_builder(nullptr), d_aloc_curr_model_builder(false), d_eager_model_building(false), - d_ppCache(), d_possiblePropagations(context), d_hasPropagated(context), d_inConflict(context, false), @@ -339,7 +200,7 @@ TheoryEngine::TheoryEngine(context::Context* context, d_propagatedLiterals(context), d_propagatedLiteralsIndex(context, 0), d_atomRequests(context), - d_tform_remover(iteRemover), + d_tpp(*this, iteRemover), d_combineTheoriesTime("TheoryEngine::combineTheoriesTime"), d_true(), d_false(), @@ -1073,7 +934,7 @@ void TheoryEngine::shutdown() { } } - d_ppCache.clear(); + d_tpp.clearCache(); } theory::Theory::PPAssertStatus TheoryEngine::solve(TNode literal, SubstitutionMap& substitutionOut) { @@ -1099,144 +960,10 @@ theory::Theory::PPAssertStatus TheoryEngine::solve(TNode literal, SubstitutionMa return solveStatus; } -// Recursively traverse a term and call the theory rewriter on its sub-terms -Node TheoryEngine::ppTheoryRewrite(TNode term) { - NodeMap::iterator find = d_ppCache.find(term); - if (find != d_ppCache.end()) { - return (*find).second; - } - unsigned nc = term.getNumChildren(); - if (nc == 0) { - return theoryOf(term)->ppRewrite(term); - } - Trace("theory-pp") << "ppTheoryRewrite { " << term << endl; - - Node newTerm; - // do not rewrite inside quantifiers - if (term.isClosure()) - { - newTerm = Rewriter::rewrite(term); - } - else - { - NodeBuilder<> newNode(term.getKind()); - if (term.getMetaKind() == kind::metakind::PARAMETERIZED) { - newNode << term.getOperator(); - } - unsigned i; - for (i = 0; i < nc; ++i) { - newNode << ppTheoryRewrite(term[i]); - } - newTerm = Rewriter::rewrite(Node(newNode)); - } - Node newTerm2 = theoryOf(newTerm)->ppRewrite(newTerm); - if (newTerm != newTerm2) { - newTerm = ppTheoryRewrite(Rewriter::rewrite(newTerm2)); - } - d_ppCache[term] = newTerm; - Trace("theory-pp")<< "ppTheoryRewrite returning " << newTerm << "}" << endl; - return newTerm; -} - - -void TheoryEngine::preprocessStart() -{ - d_ppCache.clear(); -} - - -struct preprocess_stack_element { - TNode node; - bool children_added; - preprocess_stack_element(TNode n) : node(n), children_added(false) {} -};/* struct preprocess_stack_element */ - +void TheoryEngine::preprocessStart() { d_tpp.clearCache(); } Node TheoryEngine::preprocess(TNode assertion) { - - Trace("theory::preprocess") << "TheoryEngine::preprocess(" << assertion << ")" << endl; - // spendResource(); - - // Do a topological sort of the subexpressions and substitute them - vector<preprocess_stack_element> toVisit; - toVisit.push_back(assertion); - - while (!toVisit.empty()) - { - // The current node we are processing - preprocess_stack_element& stackHead = toVisit.back(); - TNode current = stackHead.node; - - Debug("theory::internal") << "TheoryEngine::preprocess(" << assertion << "): processing " << current << endl; - - // If node already in the cache we're done, pop from the stack - NodeMap::iterator find = d_ppCache.find(current); - if (find != d_ppCache.end()) { - toVisit.pop_back(); - continue; - } - - if(! d_logicInfo.isTheoryEnabled(Theory::theoryOf(current)) && - Theory::theoryOf(current) != THEORY_SAT_SOLVER) { - stringstream ss; - ss << "The logic was specified as " << d_logicInfo.getLogicString() - << ", which doesn't include " << Theory::theoryOf(current) - << ", but got a preprocessing-time fact for that theory." << endl - << "The fact:" << endl - << current; - throw LogicException(ss.str()); - } - - // If this is an atom, we preprocess its terms with the theory ppRewriter - if (Theory::theoryOf(current) != THEORY_BOOL) { - Node ppRewritten = ppTheoryRewrite(current); - d_ppCache[current] = ppRewritten; - Assert(Rewriter::rewrite(d_ppCache[current]) == d_ppCache[current]); - continue; - } - - // Not yet substituted, so process - if (stackHead.children_added) { - // Children have been processed, so substitute - NodeBuilder<> builder(current.getKind()); - if (current.getMetaKind() == kind::metakind::PARAMETERIZED) { - builder << current.getOperator(); - } - for (unsigned i = 0; i < current.getNumChildren(); ++ i) { - Assert(d_ppCache.find(current[i]) != d_ppCache.end()); - builder << d_ppCache[current[i]]; - } - // Mark the substitution and continue - Node result = builder; - if (result != current) { - result = Rewriter::rewrite(result); - } - Debug("theory::internal") << "TheoryEngine::preprocess(" << assertion << "): setting " << current << " -> " << result << endl; - d_ppCache[current] = result; - toVisit.pop_back(); - } else { - // Mark that we have added the children if any - if (current.getNumChildren() > 0) { - stackHead.children_added = true; - // We need to add the children - for(TNode::iterator child_it = current.begin(); child_it != current.end(); ++ child_it) { - TNode childNode = *child_it; - NodeMap::iterator childFind = d_ppCache.find(childNode); - if (childFind == d_ppCache.end()) { - toVisit.push_back(childNode); - } - } - } else { - // No children, so we're done - Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << assertion << "): setting " << current << " -> " << current << endl; - d_ppCache[current] = current; - toVisit.pop_back(); - } - } - } - - // Return the substituted version - return d_ppCache[assertion]; + return d_tpp.theoryPreprocess(assertion); } void TheoryEngine::notifyPreprocessedAssertions( @@ -1881,49 +1608,27 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node, << CheckSatCommand(n.toExpr()); } - AssertionPipeline additionalLemmas; - - // Run theory preprocessing, maybe - Node ppNode = preprocess ? this->preprocess(node) : Node(node); - - // Remove the ITEs - Debug("ite") << "Remove ITE from " << ppNode << std::endl; - additionalLemmas.push_back(ppNode); - additionalLemmas.updateRealAssertionsEnd(); - d_tform_remover.run(additionalLemmas.ref(), - additionalLemmas.getIteSkolemMap()); - Debug("ite") << "..done " << additionalLemmas[0] << std::endl; - additionalLemmas.replace(0, theory::Rewriter::rewrite(additionalLemmas[0])); - - if(Debug.isOn("lemma-ites")) { - Debug("lemma-ites") << "removed ITEs from lemma: " << ppNode << endl; - Debug("lemma-ites") << " + now have the following " - << additionalLemmas.size() << " lemma(s):" << endl; - for(std::vector<Node>::const_iterator i = additionalLemmas.begin(); - i != additionalLemmas.end(); - ++i) { - Debug("lemma-ites") << " + " << *i << endl; - } - Debug("lemma-ites") << endl; - } - - // assert to prop engine - d_propEngine->assertLemma(additionalLemmas[0], negated, removable, rule, node); - for (unsigned i = 1; i < additionalLemmas.size(); ++ i) { - additionalLemmas.replace(i, theory::Rewriter::rewrite(additionalLemmas[i])); - d_propEngine->assertLemma(additionalLemmas[i], false, removable, rule, node); + // the assertion pipeline storing the lemmas + AssertionPipeline lemmas; + // call preprocessor + d_tpp.preprocess(node, lemmas, preprocess); + // assert lemmas to prop engine + for (size_t i = 0, lsize = lemmas.size(); i < lsize; ++i) + { + d_propEngine->assertLemma( + lemmas[i], i == 0 && negated, removable, rule, node); } - // WARNING: Below this point don't assume additionalLemmas[0] to be not negated. + // WARNING: Below this point don't assume lemmas[0] to be not negated. if(negated) { - additionalLemmas.replace(0, additionalLemmas[0].notNode()); + lemmas.replace(0, lemmas[0].notNode()); negated = false; } // assert to decision engine if (!removable) { - d_propEngine->addAssertionsToDecisionEngine(additionalLemmas); + d_propEngine->addAssertionsToDecisionEngine(lemmas); } // Mark that we added some lemmas @@ -1931,7 +1636,13 @@ 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 = lemmas[0]; + if (lemmas.size() > 1) + { + // the returned lemma is the conjunction of all additional lemmas. + retLemma = NodeManager::currentNM()->mkNode(kind::AND, lemmas.ref()); + } + return theory::LemmaStatus(retLemma, d_userContext->getLevel()); } void TheoryEngine::conflict(TNode conflict, TheoryId theoryId) { @@ -2372,26 +2083,4 @@ void TheoryEngine::spendResource(ResourceManager::Resource r) d_resourceManager->spendResource(r); } -TheoryEngine::Statistics::Statistics(theory::TheoryId theory): - conflicts(getStatsPrefix(theory) + "::conflicts", 0), - propagations(getStatsPrefix(theory) + "::propagations", 0), - lemmas(getStatsPrefix(theory) + "::lemmas", 0), - requirePhase(getStatsPrefix(theory) + "::requirePhase", 0), - restartDemands(getStatsPrefix(theory) + "::restartDemands", 0) -{ - smtStatisticsRegistry()->registerStat(&conflicts); - smtStatisticsRegistry()->registerStat(&propagations); - smtStatisticsRegistry()->registerStat(&lemmas); - smtStatisticsRegistry()->registerStat(&requirePhase); - smtStatisticsRegistry()->registerStat(&restartDemands); -} - -TheoryEngine::Statistics::~Statistics() { - smtStatisticsRegistry()->unregisterStat(&conflicts); - smtStatisticsRegistry()->unregisterStat(&propagations); - smtStatisticsRegistry()->unregisterStat(&lemmas); - smtStatisticsRegistry()->unregisterStat(&requirePhase); - smtStatisticsRegistry()->unregisterStat(&restartDemands); -} - }/* CVC4 namespace */ diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h index 9c631ca60..f2274b3da 100644 --- a/src/theory/theory_engine.h +++ b/src/theory/theory_engine.h @@ -2,9 +2,9 @@ /*! \file theory_engine.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Morgan Deters, Andrew Reynolds + ** Dejan Jovanovic, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -36,6 +36,7 @@ #include "smt/command.h" #include "theory/atom_requests.h" #include "theory/decision_manager.h" +#include "theory/engine_output_channel.h" #include "theory/interrupted.h" #include "theory/rewriter.h" #include "theory/shared_terms_database.h" @@ -43,6 +44,7 @@ #include "theory/substitutions.h" #include "theory/term_registration_visitor.h" #include "theory/theory.h" +#include "theory/theory_preprocessor.h" #include "theory/uf/equality_engine.h" #include "theory/valuation.h" #include "util/hash.h" @@ -114,6 +116,7 @@ class TheoryEngine { /** Shared terms database can use the internals notify the theories */ friend class SharedTermsDatabase; friend class theory::quantifiers::TermDb; + friend class theory::EngineOutputChannel; /** Associated PropEngine engine */ prop::PropEngine* d_propEngine; @@ -217,11 +220,6 @@ class TheoryEngine { typedef std::unordered_map<TNode, Node, TNodeHashFunction> TNodeMap; /** - * Cache for theory-preprocessing of assertions - */ - NodeMap d_ppCache; - - /** * Used for "missed-t-propagations" dumping mode only. A set of all * theory-propagable literals. */ @@ -234,115 +232,10 @@ class TheoryEngine { */ context::CDHashSet<Node, NodeHashFunction> d_hasPropagated; - - /** - * Statistics for a particular theory. - */ - class Statistics { - - static std::string mkName(std::string prefix, - theory::TheoryId theory, - std::string suffix) { - std::stringstream ss; - ss << prefix << theory << suffix; - return ss.str(); - } - - public: - IntStat conflicts, propagations, lemmas, requirePhase, restartDemands; - - Statistics(theory::TheoryId theory); - ~Statistics(); - };/* class TheoryEngine::Statistics */ - - /** - * An output channel for Theory that passes messages - * back to a TheoryEngine. - */ - class EngineOutputChannel : public theory::OutputChannel { - friend class TheoryEngine; - - /** - * The theory engine we're communicating with. - */ - TheoryEngine* d_engine; - - /** - * The statistics of the theory interractions. - */ - Statistics d_statistics; - - /** The theory owning this channel. */ - theory::TheoryId d_theory; - - public: - EngineOutputChannel(TheoryEngine* engine, theory::TheoryId theory) - : d_engine(engine), d_statistics(theory), d_theory(theory) {} - - void safePoint(ResourceManager::Resource r) override - { - spendResource(r); - if (d_engine->d_interrupted) { - throw theory::Interrupted(); - } - } - - void conflict(TNode conflictNode, - std::unique_ptr<Proof> pf = nullptr) override; - bool propagate(TNode literal) override; - - theory::LemmaStatus lemma(TNode lemma, ProofRule rule, - bool removable = false, bool preprocess = false, - bool sendAtoms = false) override; - - theory::LemmaStatus splitLemma(TNode lemma, - bool removable = false) override; - - void demandRestart() override { - NodeManager* curr = NodeManager::currentNM(); - Node restartVar = curr->mkSkolem( - "restartVar", curr->booleanType(), - "A boolean variable asserted to be true to force a restart"); - Trace("theory::restart") - << "EngineOutputChannel<" << d_theory << ">::restart(" << restartVar - << ")" << std::endl; - ++d_statistics.restartDemands; - lemma(restartVar, RULE_INVALID, true); - } - - void requirePhase(TNode n, bool phase) override { - Debug("theory") << "EngineOutputChannel::requirePhase(" << n << ", " - << phase << ")" << std::endl; - ++d_statistics.requirePhase; - d_engine->d_propEngine->requirePhase(n, phase); - } - - void setIncomplete() override { - Trace("theory") << "TheoryEngine::setIncomplete()" << std::endl; - d_engine->setIncomplete(d_theory); - } - - void spendResource(ResourceManager::Resource r) override - { - d_engine->spendResource(r); - } - - void handleUserAttribute(const char* attr, theory::Theory* t) override { - d_engine->handleUserAttribute(attr, t); - } - - private: - /** - * A helper function for registering lemma recipes with the proof engine - */ - void registerLemmaRecipe(Node lemma, Node originalLemma, bool preprocess, - theory::TheoryId theoryId); - }; /* class TheoryEngine::EngineOutputChannel */ - /** * Output channels for individual theories. */ - EngineOutputChannel* d_theoryOut[theory::THEORY_LAST]; + theory::EngineOutputChannel* d_theoryOut[theory::THEORY_LAST]; /** * Are we in conflict. @@ -450,11 +343,12 @@ class TheoryEngine { /** Enusre that the given atoms are send to the given theory */ void ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::TheoryId theory); - RemoveTermFormulas& d_tform_remover; - /** sort inference module */ SortInference d_sortInfer; + /** The theory preprocessor */ + theory::TheoryPreprocessor d_tpp; + /** Time spent in theory combination */ TimerStat d_combineTheoriesTime; @@ -488,7 +382,7 @@ class TheoryEngine { inline void addTheory(theory::TheoryId theoryId) { Assert(d_theoryTable[theoryId] == NULL && d_theoryOut[theoryId] == NULL); - d_theoryOut[theoryId] = new EngineOutputChannel(this, theoryId); + d_theoryOut[theoryId] = new theory::EngineOutputChannel(this, theoryId); d_theoryTable[theoryId] = new TheoryClass(d_context, d_userContext, *d_theoryOut[theoryId], @@ -543,11 +437,6 @@ class TheoryEngine { private: /** - * Helper for preprocess - */ - Node ppTheoryRewrite(TNode term); - - /** * Queue of nodes for pre-registration. */ std::queue<TNode> d_preregisterQueue; @@ -890,8 +779,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/theory_id.cpp b/src/theory/theory_id.cpp index 2a061b017..2c87458ef 100644 --- a/src/theory/theory_id.cpp +++ b/src/theory/theory_id.cpp @@ -1,3 +1,20 @@ +/********************* */ +/*! \file theory_id.cpp + ** \verbatim + ** Top contributors (to current version): + ** Aina Niemetz, Tim King, Dejan Jovanovic + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 [[ Add one-line brief description here ]] + ** + ** [[ Add lengthier description here ]] + ** \todo document this file + **/ + #include "theory/theory_id.h" namespace CVC4 { diff --git a/src/theory/theory_id.h b/src/theory/theory_id.h index 7ca5916fa..005380352 100644 --- a/src/theory/theory_id.h +++ b/src/theory/theory_id.h @@ -1,3 +1,20 @@ +/********************* */ +/*! \file theory_id.h + ** \verbatim + ** Top contributors (to current version): + ** Aina Niemetz, Dejan Jovanovic, Mathias Preiner + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 [[ Add one-line brief description here ]] + ** + ** [[ Add lengthier description here ]] + ** \todo document this file + **/ + #include "cvc4_public.h" #ifndef CVC4__THEORY__THEORY_ID_H diff --git a/src/theory/theory_model.cpp b/src/theory/theory_model.cpp index 567b5c4e4..70f46d6e5 100644 --- a/src/theory/theory_model.cpp +++ b/src/theory/theory_model.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Clark Barrett, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -681,7 +681,7 @@ void TheoryModel::assignFunctionDefinition( Node f, Node f_def ) { f_def = Rewriter::rewrite( f_def ); Trace("model-builder-debug") << "Model value (post-rewrite) : " << f_def << std::endl; - Assert(f_def.isConst()); + Assert(f_def.isConst()) << "Non-constant f_def: " << f_def; } // d_uf_models only stores models for variables diff --git a/src/theory/theory_model.h b/src/theory/theory_model.h index 1deec82d9..2d6bdd2af 100644 --- a/src/theory/theory_model.h +++ b/src/theory/theory_model.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/theory_model_builder.cpp b/src/theory/theory_model_builder.cpp index e829c1db4..c82486bdd 100644 --- a/src/theory/theory_model_builder.cpp +++ b/src/theory/theory_model_builder.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Clark Barrett, Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/theory_model_builder.h b/src/theory/theory_model_builder.h index 226ac573d..caf8bd6b8 100644 --- a/src/theory/theory_model_builder.h +++ b/src/theory/theory_model_builder.h @@ -2,9 +2,9 @@ /*! \file theory_model_builder.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Tim King, Morgan Deters + ** Andrew Reynolds, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/theory_preprocessor.cpp b/src/theory/theory_preprocessor.cpp new file mode 100644 index 000000000..d5a66ef9b --- /dev/null +++ b/src/theory/theory_preprocessor.cpp @@ -0,0 +1,239 @@ +/********************* */ +/*! \file theory_preprocessor.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds, Morgan Deters + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 theory preprocessor + **/ + +#include "theory/theory_preprocessor.h" + +#include "theory/logic_info.h" +#include "theory/rewriter.h" +#include "theory/theory_engine.h" + +using namespace std; + +namespace CVC4 { +namespace theory { + +TheoryPreprocessor::TheoryPreprocessor(TheoryEngine& engine, + RemoveTermFormulas& tfr) + : d_engine(engine), + d_logicInfo(engine.getLogicInfo()), + d_ppCache(), + d_tfr(tfr) +{ +} + +TheoryPreprocessor::~TheoryPreprocessor() {} + +void TheoryPreprocessor::clearCache() { d_ppCache.clear(); } + +void TheoryPreprocessor::preprocess(TNode node, + preprocessing::AssertionPipeline& lemmas, + bool doTheoryPreprocess) +{ + // Run theory preprocessing, maybe + Node ppNode = doTheoryPreprocess ? theoryPreprocess(node) : Node(node); + + // Remove the ITEs + Trace("te-tform-rm") << "Remove term formulas from " << ppNode << std::endl; + lemmas.push_back(ppNode); + lemmas.updateRealAssertionsEnd(); + d_tfr.run(lemmas.ref(), lemmas.getIteSkolemMap()); + Trace("te-tform-rm") << "..done " << lemmas[0] << std::endl; + + if (Debug.isOn("lemma-ites")) + { + Debug("lemma-ites") << "removed ITEs from lemma: " << ppNode << endl; + Debug("lemma-ites") << " + now have the following " << lemmas.size() + << " lemma(s):" << endl; + for (std::vector<Node>::const_iterator i = lemmas.begin(); + i != lemmas.end(); + ++i) + { + Debug("lemma-ites") << " + " << *i << endl; + } + Debug("lemma-ites") << endl; + } + + // now, rewrite the lemmas + Node retLemma; + for (size_t i = 0, lsize = lemmas.size(); i < lsize; ++i) + { + Node rewritten = Rewriter::rewrite(lemmas[i]); + lemmas.replace(i, rewritten); + } +} + +struct preprocess_stack_element +{ + TNode node; + bool children_added; + preprocess_stack_element(TNode n) : node(n), children_added(false) {} +}; + +Node TheoryPreprocessor::theoryPreprocess(TNode assertion) +{ + Trace("theory::preprocess") + << "TheoryPreprocessor::theoryPreprocess(" << assertion << ")" << endl; + // spendResource(); + + // Do a topological sort of the subexpressions and substitute them + vector<preprocess_stack_element> toVisit; + toVisit.push_back(assertion); + + while (!toVisit.empty()) + { + // The current node we are processing + preprocess_stack_element& stackHead = toVisit.back(); + TNode current = stackHead.node; + + Debug("theory::internal") + << "TheoryPreprocessor::theoryPreprocess(" << assertion + << "): processing " << current << endl; + + // If node already in the cache we're done, pop from the stack + NodeMap::iterator find = d_ppCache.find(current); + if (find != d_ppCache.end()) + { + toVisit.pop_back(); + continue; + } + + if (!d_logicInfo.isTheoryEnabled(Theory::theoryOf(current)) + && Theory::theoryOf(current) != THEORY_SAT_SOLVER) + { + stringstream ss; + ss << "The logic was specified as " << d_logicInfo.getLogicString() + << ", which doesn't include " << Theory::theoryOf(current) + << ", but got a preprocessing-time fact for that theory." << endl + << "The fact:" << endl + << current; + throw LogicException(ss.str()); + } + + // If this is an atom, we preprocess its terms with the theory ppRewriter + if (Theory::theoryOf(current) != THEORY_BOOL) + { + Node ppRewritten = ppTheoryRewrite(current); + d_ppCache[current] = ppRewritten; + Assert(Rewriter::rewrite(d_ppCache[current]) == d_ppCache[current]); + continue; + } + + // Not yet substituted, so process + if (stackHead.children_added) + { + // Children have been processed, so substitute + NodeBuilder<> builder(current.getKind()); + if (current.getMetaKind() == kind::metakind::PARAMETERIZED) + { + builder << current.getOperator(); + } + for (unsigned i = 0; i < current.getNumChildren(); ++i) + { + Assert(d_ppCache.find(current[i]) != d_ppCache.end()); + builder << d_ppCache[current[i]]; + } + // Mark the substitution and continue + Node result = builder; + if (result != current) + { + result = Rewriter::rewrite(result); + } + Debug("theory::internal") + << "TheoryPreprocessor::theoryPreprocess(" << assertion + << "): setting " << current << " -> " << result << endl; + d_ppCache[current] = result; + toVisit.pop_back(); + } + else + { + // Mark that we have added the children if any + if (current.getNumChildren() > 0) + { + stackHead.children_added = true; + // We need to add the children + for (TNode::iterator child_it = current.begin(); + child_it != current.end(); + ++child_it) + { + TNode childNode = *child_it; + NodeMap::iterator childFind = d_ppCache.find(childNode); + if (childFind == d_ppCache.end()) + { + toVisit.push_back(childNode); + } + } + } + else + { + // No children, so we're done + Debug("substitution::internal") + << "SubstitutionMap::internalSubstitute(" << assertion + << "): setting " << current << " -> " << current << endl; + d_ppCache[current] = current; + toVisit.pop_back(); + } + } + } + + // Return the substituted version + return d_ppCache[assertion]; +} + +// Recursively traverse a term and call the theory rewriter on its sub-terms +Node TheoryPreprocessor::ppTheoryRewrite(TNode term) +{ + NodeMap::iterator find = d_ppCache.find(term); + if (find != d_ppCache.end()) + { + return (*find).second; + } + unsigned nc = term.getNumChildren(); + if (nc == 0) + { + return d_engine.theoryOf(term)->ppRewrite(term); + } + Trace("theory-pp") << "ppTheoryRewrite { " << term << endl; + + Node newTerm; + // do not rewrite inside quantifiers + if (term.isClosure()) + { + newTerm = Rewriter::rewrite(term); + } + else + { + NodeBuilder<> newNode(term.getKind()); + if (term.getMetaKind() == kind::metakind::PARAMETERIZED) + { + newNode << term.getOperator(); + } + unsigned i; + for (i = 0; i < nc; ++i) + { + newNode << ppTheoryRewrite(term[i]); + } + newTerm = Rewriter::rewrite(Node(newNode)); + } + Node newTerm2 = d_engine.theoryOf(newTerm)->ppRewrite(newTerm); + if (newTerm != newTerm2) + { + newTerm = ppTheoryRewrite(Rewriter::rewrite(newTerm2)); + } + d_ppCache[term] = newTerm; + Trace("theory-pp") << "ppTheoryRewrite returning " << newTerm << "}" << endl; + return newTerm; +} + +} // namespace theory +} // namespace CVC4 diff --git a/src/theory/theory_preprocessor.h b/src/theory/theory_preprocessor.h new file mode 100644 index 000000000..2488cf162 --- /dev/null +++ b/src/theory/theory_preprocessor.h @@ -0,0 +1,81 @@ +/********************* */ +/*! \file theory_preprocessor.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds, Morgan Deters, Dejan Jovanovic + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 theory preprocessor. + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__THEORY__THEORY_PREPROCESSOR_H +#define CVC4__THEORY__THEORY_PREPROCESSOR_H + +#include <unordered_map> + +#include "expr/node.h" +#include "preprocessing/assertion_pipeline.h" + +namespace CVC4 { + +class LogicInfo; +class TheoryEngine; +class RemoveTermFormulas; +class LazyCDProof; + +namespace theory { + +/** + * The preprocessor used in TheoryEngine. + */ +class TheoryPreprocessor +{ + typedef std::unordered_map<Node, Node, NodeHashFunction> NodeMap; + + public: + /** Constructs a theory preprocessor */ + TheoryPreprocessor(TheoryEngine& engine, RemoveTermFormulas& tfr); + /** Destroys a theory preprocessor */ + ~TheoryPreprocessor(); + /** Clear the cache of this class */ + void clearCache(); + /** + * Preprocesses node and stores it along with lemmas generated by + * preprocessing into the assertion pipeline lemmas. The (optional) argument + * lcp is the proof that stores a proof of all top-level formulas in lemmas, + * assuming that lcp initially contains a proof of node. The flag + * doTheoryPreprocess is whether we should run theory-specific preprocessing. + */ + void preprocess(TNode node, + preprocessing::AssertionPipeline& lemmas, + bool doTheoryPreprocess); + /** + * Runs theory specific preprocessing on the non-Boolean parts of + * the formula. This is only called on input assertions, after ITEs + * have been removed. + */ + Node theoryPreprocess(TNode node); + + private: + /** Reference to owning theory engine */ + TheoryEngine& d_engine; + /** Logic info of theory engine */ + const LogicInfo& d_logicInfo; + /** Cache for theory-preprocessing of assertions */ + NodeMap d_ppCache; + /** The term formula remover */ + RemoveTermFormulas& d_tfr; + /** Helper for theoryPreprocess */ + Node ppTheoryRewrite(TNode term); +}; + +} // namespace theory +} // namespace CVC4 + +#endif /* CVC4__THEORY__THEORY_PREPROCESSOR_H */ diff --git a/src/theory/theory_proof_step_buffer.cpp b/src/theory/theory_proof_step_buffer.cpp new file mode 100644 index 000000000..8a518b49a --- /dev/null +++ b/src/theory/theory_proof_step_buffer.cpp @@ -0,0 +1,94 @@ +/********************* */ +/*! \file theory_proof_step_buffer.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 theory proof step buffer utility + **/ + +#include "theory/theory_proof_step_buffer.h" + +#include "expr/proof.h" + +using namespace CVC4::kind; + +namespace CVC4 { +namespace theory { + +TheoryProofStepBuffer::TheoryProofStepBuffer(ProofChecker* pc) + : ProofStepBuffer(pc) +{ +} + +bool TheoryProofStepBuffer::applyPredTransform(Node src, + Node tgt, + const std::vector<Node>& exp, + MethodId ids, + MethodId idr) +{ + // symmetric equalities + if (CDProof::isSame(src, tgt)) + { + return true; + } + std::vector<Node> children; + children.push_back(src); + std::vector<Node> args; + // try to prove that tgt rewrites to src + children.insert(children.end(), exp.begin(), exp.end()); + args.push_back(tgt); + builtin::BuiltinProofRuleChecker::addMethodIds(args, ids, idr); + Node res = tryStep(PfRule::MACRO_SR_PRED_TRANSFORM, children, args); + if (res.isNull()) + { + // failed to apply + return false; + } + // should definitely have concluded tgt + Assert(res == tgt); + return true; +} + +bool TheoryProofStepBuffer::applyPredIntro(Node tgt, + const std::vector<Node>& exp, + MethodId ids, + MethodId idr) +{ + std::vector<Node> args; + args.push_back(tgt); + builtin::BuiltinProofRuleChecker::addMethodIds(args, ids, idr); + Node res = tryStep(PfRule::MACRO_SR_PRED_INTRO, exp, args); + if (res.isNull()) + { + return false; + } + Assert(res == tgt); + return true; +} + +Node TheoryProofStepBuffer::applyPredElim(Node src, + const std::vector<Node>& exp, + MethodId ids, + MethodId idr) +{ + std::vector<Node> children; + children.push_back(src); + children.insert(children.end(), exp.begin(), exp.end()); + std::vector<Node> args; + builtin::BuiltinProofRuleChecker::addMethodIds(args, ids, idr); + Node srcRew = tryStep(PfRule::MACRO_SR_PRED_ELIM, children, args); + if (CDProof::isSame(src, srcRew)) + { + popStep(); + } + return srcRew; +} + +} // namespace theory +} // namespace CVC4 diff --git a/src/theory/theory_proof_step_buffer.h b/src/theory/theory_proof_step_buffer.h new file mode 100644 index 000000000..55b4ee1c0 --- /dev/null +++ b/src/theory/theory_proof_step_buffer.h @@ -0,0 +1,81 @@ +/********************* */ +/*! \file theory_proof_step_buffer.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 Theory proof step buffer utility. + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__THEORY__THEORY_PROOF_STEP_BUFFER_H +#define CVC4__THEORY__THEORY_PROOF_STEP_BUFFER_H + +#include <vector> + +#include "expr/node.h" +#include "expr/proof_step_buffer.h" +#include "theory/builtin/proof_checker.h" + +namespace CVC4 { +namespace theory { +/** + * Class used to speculatively try and buffer a set of proof steps before + * sending them to a proof object, extended with theory-specfic proof rule + * utilities. + */ +class TheoryProofStepBuffer : public ProofStepBuffer +{ + public: + TheoryProofStepBuffer(ProofChecker* pc = nullptr); + ~TheoryProofStepBuffer() {} + //---------------------------- utilities builtin proof rules + /** + * Apply predicate transform. If this method returns true, it adds (at most + * one) proof step to the buffer that conclude tgt from premises src, exp. In + * particular, it may attempt to apply MACRO_SR_PRED_TRANSFORM. This method + * should be applied when src and tgt are equivalent formulas assuming exp. + */ + bool applyPredTransform(Node src, + Node tgt, + const std::vector<Node>& exp, + MethodId ids = MethodId::SB_DEFAULT, + MethodId idr = MethodId::RW_REWRITE); + /** + * Apply predicate introduction. If this method returns true, it adds proof + * step(s) to the buffer that conclude tgt from premises exp. In particular, + * it may attempt to apply the rule MACRO_SR_PRED_INTRO. This method should be + * applied when tgt is equivalent to true assuming exp. + */ + bool applyPredIntro(Node tgt, + const std::vector<Node>& exp, + MethodId ids = MethodId::SB_DEFAULT, + MethodId idr = MethodId::RW_REWRITE); + /** + * Apply predicate elimination. This method returns the result of applying + * the rule MACRO_SR_PRED_ELIM on src, exp. The returned formula is equivalent + * to src assuming exp. If the return value is equivalent to src, then no + * proof step is added to this buffer, since this step is a no-op in this + * case. + * + * Notice that in contrast to the other rules above, predicate elimination + * never fails and proves a formula that is not explicitly given as an + * argument tgt. Thus, the return value of this method is Node not bool. + */ + Node applyPredElim(Node src, + const std::vector<Node>& exp, + MethodId ids = MethodId::SB_DEFAULT, + MethodId idr = MethodId::RW_REWRITE); + //---------------------------- end utilities builtin proof rules +}; + +} // namespace theory +} // namespace CVC4 + +#endif /* CVC4__THEORY__THEORY_PROOF_STEP_BUFFER_H */ diff --git a/src/theory/theory_registrar.h b/src/theory/theory_registrar.h index 822ae086c..f2217f619 100644 --- a/src/theory/theory_registrar.h +++ b/src/theory/theory_registrar.h @@ -2,9 +2,9 @@ /*! \file theory_registrar.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Tim King, Mathias Preiner + ** Mathias Preiner, Tim King, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/theory_rewriter.h b/src/theory/theory_rewriter.h index 311ab9020..4a9c8d14f 100644 --- a/src/theory/theory_rewriter.h +++ b/src/theory/theory_rewriter.h @@ -2,9 +2,9 @@ /*! \file theory_rewriter.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andres Noetzli, Morgan Deters, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/theory_test_utils.h b/src/theory/theory_test_utils.h index 17b47d2d3..61caca82a 100644 --- a/src/theory/theory_test_utils.h +++ b/src/theory/theory_test_utils.h @@ -2,9 +2,9 @@ /*! \file theory_test_utils.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Dejan Jovanovic + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/theory_traits_template.h b/src/theory/theory_traits_template.h index 9bd67dba6..775f42a46 100644 --- a/src/theory/theory_traits_template.h +++ b/src/theory/theory_traits_template.h @@ -2,9 +2,9 @@ /*! \file theory_traits_template.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Dejan Jovanovic + ** Morgan Deters, Dejan Jovanovic, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/trust_node.cpp b/src/theory/trust_node.cpp new file mode 100644 index 000000000..af2d60241 --- /dev/null +++ b/src/theory/trust_node.cpp @@ -0,0 +1,121 @@ +/********************* */ +/*! \file trust_node.cpp + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 trust node utility + **/ + +#include "theory/trust_node.h" + +#include "expr/proof_generator.h" + +namespace CVC4 { +namespace theory { + +const char* toString(TrustNodeKind tnk) +{ + switch (tnk) + { + case TrustNodeKind::CONFLICT: return "CONFLICT"; + case TrustNodeKind::LEMMA: return "LEMMA"; + case TrustNodeKind::PROP_EXP: return "PROP_EXP"; + case TrustNodeKind::REWRITE: return "REWRITE"; + default: return "?"; + } +} + +std::ostream& operator<<(std::ostream& out, TrustNodeKind tnk) +{ + out << toString(tnk); + return out; +} + +TrustNode TrustNode::mkTrustConflict(Node conf, ProofGenerator* g) +{ + Node ckey = getConflictProven(conf); + // if a generator is provided, should confirm that it can prove it + Assert(g == nullptr || g->hasProofFor(ckey)); + return TrustNode(TrustNodeKind::CONFLICT, ckey, g); +} + +TrustNode TrustNode::mkTrustLemma(Node lem, ProofGenerator* g) +{ + Node lkey = getLemmaProven(lem); + // if a generator is provided, should confirm that it can prove it + Assert(g == nullptr || g->hasProofFor(lkey)); + return TrustNode(TrustNodeKind::LEMMA, lkey, g); +} + +TrustNode TrustNode::mkTrustPropExp(TNode lit, Node exp, ProofGenerator* g) +{ + Node pekey = getPropExpProven(lit, exp); + Assert(g == nullptr || g->hasProofFor(pekey)); + return TrustNode(TrustNodeKind::PROP_EXP, pekey, g); +} + +TrustNode TrustNode::mkTrustRewrite(TNode n, Node nr, ProofGenerator* g) +{ + Node rkey = getRewriteProven(n, nr); + Assert(g == nullptr || g->hasProofFor(rkey)); + return TrustNode(TrustNodeKind::REWRITE, rkey, g); +} + +TrustNode TrustNode::null() +{ + return TrustNode(TrustNodeKind::INVALID, Node::null()); +} + +TrustNode::TrustNode(TrustNodeKind tnk, Node p, ProofGenerator* g) + : d_tnk(tnk), d_proven(p), d_gen(g) +{ + // does not make sense to provide null node with generator + Assert(!d_proven.isNull() || d_gen == nullptr); +} + +TrustNodeKind TrustNode::getKind() const { return d_tnk; } + +Node TrustNode::getNode() const +{ + switch (d_tnk) + { + // the node of lemma is the node itself + case TrustNodeKind::LEMMA: return d_proven; + // the node of the rewrite is the right hand side of EQUAL + case TrustNodeKind::REWRITE: return d_proven[1]; + // the node of an explained propagation is the antecendant of an IMPLIES + // the node of a conflict is underneath a NOT + default: return d_proven[0]; + } +} + +Node TrustNode::getProven() const { return d_proven; } +ProofGenerator* TrustNode::getGenerator() const { return d_gen; } + +bool TrustNode::isNull() const { return d_proven.isNull(); } + +Node TrustNode::getConflictProven(Node conf) { return conf.notNode(); } + +Node TrustNode::getLemmaProven(Node lem) { return lem; } + +Node TrustNode::getPropExpProven(TNode lit, Node exp) +{ + return NodeManager::currentNM()->mkNode(kind::IMPLIES, exp, lit); +} + +Node TrustNode::getRewriteProven(TNode n, Node nr) { return n.eqNode(nr); } + +std::ostream& operator<<(std::ostream& out, TrustNode n) +{ + out << "(trust " << n.getNode() << ")"; + return out; +} + +} // namespace theory +} // namespace CVC4 diff --git a/src/theory/trust_node.h b/src/theory/trust_node.h new file mode 100644 index 000000000..a3c0fbec5 --- /dev/null +++ b/src/theory/trust_node.h @@ -0,0 +1,162 @@ +/********************* */ +/*! \file trust_node.h + ** \verbatim + ** Top contributors (to current version): + ** Andrew Reynolds + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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 trust node utility + **/ + +#include "cvc4_private.h" + +#ifndef CVC4__THEORY__TRUST_NODE_H +#define CVC4__THEORY__TRUST_NODE_H + +#include "expr/node.h" + +namespace CVC4 { + +class ProofGenerator; + +namespace theory { + +/** A kind for trust nodes */ +enum class TrustNodeKind : uint32_t +{ + CONFLICT, + LEMMA, + PROP_EXP, + REWRITE, + INVALID +}; +/** + * Converts a proof rule to a string. Note: This function is also used in + * `safe_print()`. Changing this function name or signature will result in + * `safe_print()` printing "<unsupported>" instead of the proper strings for + * the enum values. + * + * Returns a string with static lifetime: it should not be freed. + * + * @param tnk The trust node kind + * @return The name of the trust node kind + */ +const char* toString(TrustNodeKind tnk); + +/** + * Writes a trust node kind name to a stream. + * + * @param out The stream to write to + * @param tnk The trust node kind to write to the stream + * @return The stream + */ +std::ostream& operator<<(std::ostream& out, TrustNodeKind tnk); + +/** + * A trust node is a pair (F, G) where F is a formula and G is a proof + * generator that can construct a proof for F if asked. + * + * More generally, a trust node is any node that can be used for a specific + * purpose that requires justification, such as being passed to + * OutputChannel::lemma. That justification is intended to be given by the + * generator that is required to construct this object. + * + * They are intended to be constructed by ProofGenerator objects themselves (a + * proof generator wraps itself in TrustNode it returns) and passed + * to ProofOutputChannel by theory solvers. + * + * The static functions for constructing them check that the generator, if + * provided, is capable of proving the given conflict or lemma, or an assertion + * failure occurs. Otherwise an assertion error is given. + * + * While this is not enforced, a `TrustNode` generally encapsulates a **closed** proof + * of the formula: one without free assumptions. + */ +class TrustNode +{ + public: + TrustNode() : d_tnk(TrustNodeKind::INVALID), d_gen(nullptr) {} + /** Make a proven node for conflict */ + static TrustNode mkTrustConflict(Node conf, ProofGenerator* g = nullptr); + /** Make a proven node for lemma */ + static TrustNode mkTrustLemma(Node lem, ProofGenerator* g = nullptr); + /** Make a proven node for explanation of propagated literal */ + static TrustNode mkTrustPropExp(TNode lit, + Node exp, + ProofGenerator* g = nullptr); + /** Make a proven node for rewrite */ + static TrustNode mkTrustRewrite(TNode n, + Node nr, + ProofGenerator* g = nullptr); + /** The null proven node */ + static TrustNode null(); + ~TrustNode() {} + /** get kind */ + TrustNodeKind getKind() const; + /** get node + * + * This is the node that is used in a common interface, either: + * (1) A T-unsat conjunction conf to pass to OutputChannel::conflict, + * (2) A valid T-formula lem to pass to OutputChannel::lemma, + * (3) A conjunction of literals exp to return in Theory::explain(lit), or + * (4) A result of rewriting a term n into an equivalent one nr. + * + * Notice that this node does not necessarily correspond to a valid formula. + * The call getProven() below retrieves a valid formula corresponding to + * the above calls. + */ + Node getNode() const; + /** get proven + * + * This is the corresponding formula that is proven by the proof generator + * for the above cases: + * (1) (not conf), for conflicts, + * (2) lem, for lemmas, + * (3) (=> exp lit), for propagations from explanations, + * (4) (= n nr), for results of rewriting. + * + * When constructing this trust node, the proof generator should be able to + * provide a proof for this fact. + */ + Node getProven() const; + /** get generator */ + ProofGenerator* getGenerator() const; + /** is null? */ + bool isNull() const; + + /** Get the proven formula corresponding to a conflict call */ + static Node getConflictProven(Node conf); + /** Get the proven formula corresponding to a lemma call */ + static Node getLemmaProven(Node lem); + /** Get the proven formula corresponding to explanations for propagation */ + static Node getPropExpProven(TNode lit, Node exp); + /** Get the proven formula corresponding to a rewrite */ + static Node getRewriteProven(TNode n, Node nr); + + private: + TrustNode(TrustNodeKind tnk, Node p, ProofGenerator* g = nullptr); + /** The kind */ + TrustNodeKind d_tnk; + /** The proven node */ + Node d_proven; + /** The generator */ + ProofGenerator* d_gen; +}; + +/** + * Writes a trust node to a stream. + * + * @param out The stream to write to + * @param n The trust node to write to the stream + * @return The stream + */ +std::ostream& operator<<(std::ostream& out, TrustNode n); + +} // namespace theory +} // namespace CVC4 + +#endif /* CVC4__THEORY__TRUST_NODE_H */ diff --git a/src/theory/type_enumerator.h b/src/theory/type_enumerator.h index 81c0c38c8..bb223a950 100644 --- a/src/theory/type_enumerator.h +++ b/src/theory/type_enumerator.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/type_enumerator_template.cpp b/src/theory/type_enumerator_template.cpp index 01d25860c..e9fdc6a86 100644 --- a/src/theory/type_enumerator_template.cpp +++ b/src/theory/type_enumerator_template.cpp @@ -2,9 +2,9 @@ /*! \file type_enumerator_template.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Andres Noetzli + ** Morgan Deters, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/type_set.cpp b/src/theory/type_set.cpp index 0e14f9102..85364fb33 100644 --- a/src/theory/type_set.cpp +++ b/src/theory/type_set.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Clark Barrett ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/type_set.h b/src/theory/type_set.h index aed7ad80c..3914d6a3c 100644 --- a/src/theory/type_set.h +++ b/src/theory/type_set.h @@ -2,9 +2,9 @@ /*! \file type_set.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/cardinality_extension.cpp b/src/theory/uf/cardinality_extension.cpp index 908e788f8..1f83c94d6 100644 --- a/src/theory/uf/cardinality_extension.cpp +++ b/src/theory/uf/cardinality_extension.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/cardinality_extension.h b/src/theory/uf/cardinality_extension.h index 37d442968..e1ca46bfb 100644 --- a/src/theory/uf/cardinality_extension.h +++ b/src/theory/uf/cardinality_extension.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/equality_engine.cpp b/src/theory/uf/equality_engine.cpp index 60883e4ef..1dd9ba8b6 100644 --- a/src/theory/uf/equality_engine.cpp +++ b/src/theory/uf/equality_engine.cpp @@ -2,9 +2,9 @@ /*! \file equality_engine.cpp ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Guy Katz, Andrew Reynolds + ** Dejan Jovanovic, Andrew Reynolds, Guy Katz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/equality_engine.h b/src/theory/uf/equality_engine.h index 0ae95b34a..cf6eabfb7 100644 --- a/src/theory/uf/equality_engine.h +++ b/src/theory/uf/equality_engine.h @@ -2,9 +2,9 @@ /*! \file equality_engine.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Morgan Deters, Guy Katz + ** Dejan Jovanovic, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/equality_engine_types.h b/src/theory/uf/equality_engine_types.h index 0e6d283fe..14cd80436 100644 --- a/src/theory/uf/equality_engine_types.h +++ b/src/theory/uf/equality_engine_types.h @@ -2,9 +2,9 @@ /*! \file equality_engine_types.h ** \verbatim ** Top contributors (to current version): - ** Dejan Jovanovic, Andrew Reynolds, Andres Noetzli + ** Dejan Jovanovic, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/ho_extension.cpp b/src/theory/uf/ho_extension.cpp index 23b7b9217..d90a02486 100644 --- a/src/theory/uf/ho_extension.cpp +++ b/src/theory/uf/ho_extension.cpp @@ -2,9 +2,9 @@ /*! \file ho_extension.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds + ** Andrew Reynolds, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/ho_extension.h b/src/theory/uf/ho_extension.h index 47336e085..d00372c98 100644 --- a/src/theory/uf/ho_extension.h +++ b/src/theory/uf/ho_extension.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/proof_checker.cpp b/src/theory/uf/proof_checker.cpp new file mode 100644 index 000000000..f866e77dd --- /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 + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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..92d853f3a --- /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 + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2020 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/theory/uf/symmetry_breaker.cpp b/src/theory/uf/symmetry_breaker.cpp index 27d045120..513c58783 100644 --- a/src/theory/uf/symmetry_breaker.cpp +++ b/src/theory/uf/symmetry_breaker.cpp @@ -2,9 +2,9 @@ /*! \file symmetry_breaker.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Liana Hadarean, Tim King + ** Morgan Deters, Mathias Preiner, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/symmetry_breaker.h b/src/theory/uf/symmetry_breaker.h index d528e948f..c7fc51465 100644 --- a/src/theory/uf/symmetry_breaker.h +++ b/src/theory/uf/symmetry_breaker.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Liana Hadarean, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/theory_uf.cpp b/src/theory/uf/theory_uf.cpp index 1098d42ce..8334f29d1 100644 --- a/src/theory/uf/theory_uf.cpp +++ b/src/theory/uf/theory_uf.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Morgan Deters, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/theory_uf.h b/src/theory/uf/theory_uf.h index 8627eb3f0..a3e908b1f 100644 --- a/src/theory/uf/theory_uf.h +++ b/src/theory/uf/theory_uf.h @@ -2,9 +2,9 @@ /*! \file theory_uf.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Dejan Jovanovic, Morgan Deters + ** Dejan Jovanovic, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/theory_uf_model.cpp b/src/theory/uf/theory_uf_model.cpp index d667aea7e..56d44b769 100644 --- a/src/theory/uf/theory_uf_model.cpp +++ b/src/theory/uf/theory_uf_model.cpp @@ -2,9 +2,9 @@ /*! \file theory_uf_model.cpp ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters, Clark Barrett + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/theory_uf_model.h b/src/theory/uf/theory_uf_model.h index 4454b7e8c..138ad1238 100644 --- a/src/theory/uf/theory_uf_model.h +++ b/src/theory/uf/theory_uf_model.h @@ -2,9 +2,9 @@ /*! \file theory_uf_model.h ** \verbatim ** Top contributors (to current version): - ** Andrew Reynolds, Morgan Deters + ** Andrew Reynolds, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/theory_uf_rewriter.h b/src/theory/uf/theory_uf_rewriter.h index 1cc8ab876..e651edb51 100644 --- a/src/theory/uf/theory_uf_rewriter.h +++ b/src/theory/uf/theory_uf_rewriter.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Haniel Barbosa, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/uf/theory_uf_type_rules.h b/src/theory/uf/theory_uf_type_rules.h index f782cd618..372ca9ad0 100644 --- a/src/theory/uf/theory_uf_type_rules.h +++ b/src/theory/uf/theory_uf_type_rules.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/valuation.cpp b/src/theory/valuation.cpp index 4ad8c8785..c4529992a 100644 --- a/src/theory/valuation.cpp +++ b/src/theory/valuation.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Dejan Jovanovic, Andrew Reynolds, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/theory/valuation.h b/src/theory/valuation.h index 4667db0e9..01ae61fcb 100644 --- a/src/theory/valuation.h +++ b/src/theory/valuation.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Dejan Jovanovic, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index eba5fb8c9..028288dbc 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -17,6 +17,7 @@ libcvc4_add_sources( floatingpoint.cpp gmp_util.h hash.h + iand.h index.cpp index.h maybe.h diff --git a/src/util/abstract_value.cpp b/src/util/abstract_value.cpp index 49247ee38..e004a22a7 100644 --- a/src/util/abstract_value.cpp +++ b/src/util/abstract_value.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/abstract_value.h b/src/util/abstract_value.h index 8091a7ee5..f1fe9f575 100644 --- a/src/util/abstract_value.h +++ b/src/util/abstract_value.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/bin_heap.h b/src/util/bin_heap.h index 7ada9a655..d7d3a8e18 100644 --- a/src/util/bin_heap.h +++ b/src/util/bin_heap.h @@ -2,9 +2,9 @@ /*! \file bin_heap.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andres Noetzli + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/bitvector.cpp b/src/util/bitvector.cpp index a561fe088..3f3327c93 100644 --- a/src/util/bitvector.cpp +++ b/src/util/bitvector.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Aina Niemetz, Liana Hadarean, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/bitvector.h b/src/util/bitvector.h index a75339112..8e11d2465 100644 --- a/src/util/bitvector.h +++ b/src/util/bitvector.h @@ -2,9 +2,9 @@ /*! \file bitvector.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Dejan Jovanovic, Morgan Deters + ** Aina Niemetz, Andres Noetzli, Dejan Jovanovic ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/bool.h b/src/util/bool.h index 32f3741f8..5779f073b 100644 --- a/src/util/bool.h +++ b/src/util/bool.h @@ -2,9 +2,9 @@ /*! \file bool.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/cardinality.cpp b/src/util/cardinality.cpp index 6615f8378..e7c0ac01c 100644 --- a/src/util/cardinality.cpp +++ b/src/util/cardinality.cpp @@ -2,9 +2,9 @@ /*! \file cardinality.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/cardinality.h b/src/util/cardinality.h index b06d72286..d1b003300 100644 --- a/src/util/cardinality.h +++ b/src/util/cardinality.h @@ -2,9 +2,9 @@ /*! \file cardinality.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Andrew Reynolds + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/dense_map.h b/src/util/dense_map.h index 08da8faaa..8e5f5f9cf 100644 --- a/src/util/dense_map.h +++ b/src/util/dense_map.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Dejan Jovanovic, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/divisible.cpp b/src/util/divisible.cpp index c89886fa8..a218642d7 100644 --- a/src/util/divisible.cpp +++ b/src/util/divisible.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/divisible.h b/src/util/divisible.h index a0c730436..bb2370f0b 100644 --- a/src/util/divisible.h +++ b/src/util/divisible.h @@ -2,9 +2,9 @@ /*! \file divisible.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters + ** Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/floatingpoint.cpp b/src/util/floatingpoint.cpp index f5545f73c..7403c340b 100644 --- a/src/util/floatingpoint.cpp +++ b/src/util/floatingpoint.cpp @@ -2,10 +2,10 @@ /*! \file floatingpoint.cpp ** \verbatim ** Top contributors (to current version): - ** Martin Brain, Martin Brain, Tim King + ** Martin Brain, Haniel Barbosa, Mathias Preiner ** Copyright (c) 2013 University of Oxford ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -959,6 +959,41 @@ static FloatingPointLiteral constructorHelperBitVector( return bv; } - +std::string FloatingPoint::toString(bool printAsIndexed) const +{ + std::string str; + // retrive BV value + BitVector bv(pack()); + unsigned largestSignificandBit = + t.significand() - 2; // -1 for -inclusive, -1 for hidden + unsigned largestExponentBit = + (t.exponent() - 1) + (largestSignificandBit + 1); + BitVector v[3]; + v[0] = bv.extract(largestExponentBit + 1, largestExponentBit + 1); + v[1] = bv.extract(largestExponentBit, largestSignificandBit + 1); + v[2] = bv.extract(largestSignificandBit, 0); + str.append("(fp "); + for (unsigned i = 0; i < 3; ++i) + { + if (printAsIndexed) + { + str.append("(_ bv"); + str.append(v[i].getValue().toString()); + str.append(" "); + str.append(std::to_string(v[i].getSize())); + str.append(")"); + } + else + { + str.append("#b"); + str.append(v[i].toString()); + } + if (i < 2) + { + str.append(" "); + } + } + return str; +} }/* CVC4 namespace */ diff --git a/src/util/floatingpoint.h.in b/src/util/floatingpoint.h.in index bac0fbd59..d38cae5fa 100644 --- a/src/util/floatingpoint.h.in +++ b/src/util/floatingpoint.h.in @@ -2,10 +2,10 @@ /*! \file floatingpoint.h.in ** \verbatim ** Top contributors (to current version): - ** Martin Brain, Martin Brain, Tim King + ** Martin Brain, Haniel Barbosa, Tim King ** Copyright (c) 2013 University of Oxford ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -333,6 +333,13 @@ namespace CVC4 { return this->fpl; } + /* Return string representation. + * + * If printAsIndexed is true then it prints + * the bit-vector components of the FP value as indexed symbols, otherwise + * in binary notation. */ + std::string toString(bool printAsIndexed = false) const; + // Gives the corresponding IEEE-754 transfer format BitVector pack (void) const; @@ -526,17 +533,10 @@ namespace CVC4 { */ inline std::ostream& operator <<(std::ostream& os, const FloatingPoint& fp) CVC4_PUBLIC; - inline std::ostream& operator <<(std::ostream& os, const FloatingPoint& fp) { - BitVector bv(fp.pack()); - - unsigned largestSignificandBit = fp.t.significand() - 2; // -1 for -inclusive, -1 for hidden - unsigned largestExponentBit = (fp.t.exponent() - 1) + (largestSignificandBit + 1); - - return os - << "(fp #b" << bv.extract(largestExponentBit + 1, largestExponentBit + 1) - << " #b" << bv.extract(largestExponentBit, largestSignificandBit + 1) - << " #b" << bv.extract(largestSignificandBit, 0) - << ")"; + inline std::ostream& operator<<(std::ostream& os, const FloatingPoint& fp) + { + // print in binary notation + return os << fp.toString(); } inline std::ostream& operator <<(std::ostream& os, const FloatingPointSize& fps) CVC4_PUBLIC; diff --git a/src/util/gmp_util.h b/src/util/gmp_util.h index 3ba388564..bde7b50a8 100644 --- a/src/util/gmp_util.h +++ b/src/util/gmp_util.h @@ -2,9 +2,9 @@ /*! \file gmp_util.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Andres Noetzli, Morgan Deters + ** Tim King, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/hash.h b/src/util/hash.h index 14167bc82..548fb3afc 100644 --- a/src/util/hash.h +++ b/src/util/hash.h @@ -2,9 +2,9 @@ /*! \file hash.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli + ** Morgan Deters, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/iand.h b/src/util/iand.h new file mode 100644 index 000000000..b5bc92960 --- /dev/null +++ b/src/util/iand.h @@ -0,0 +1,47 @@ +/********************* */ +/*! \file iand.h + ** \verbatim + ** Top contributors (to current version): + ** Anrew 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 integer AND operator. + **/ + +#include "cvc4_public.h" + +#ifndef CVC4__IAND_H +#define CVC4__IAND_H + +#include <cstdint> +#include <iosfwd> + +#include "base/exception.h" +#include "util/integer.h" + +namespace CVC4 { + +struct CVC4_PUBLIC IntAnd +{ + unsigned d_size; + IntAnd(unsigned size) : d_size(size) {} + operator unsigned() const { return d_size; } +}; /* struct IntAnd */ + +/* ----------------------------------------------------------------------- + ** Output stream + * ----------------------------------------------------------------------- */ + +inline std::ostream& operator<<(std::ostream& os, const IntAnd& ia) CVC4_PUBLIC; +inline std::ostream& operator<<(std::ostream& os, const IntAnd& ia) +{ + return os << "[" << ia.d_size << "]"; +} + +} // namespace CVC4 + +#endif /* CVC4__IAND_H */ diff --git a/src/util/iand.i b/src/util/iand.i new file mode 100644 index 000000000..92c5a1223 --- /dev/null +++ b/src/util/iand.i @@ -0,0 +1,9 @@ +%{ +#include "util/iand.h" +%} + +%rename(toUnsigned) CVC4::IntAnd::operator unsigned() const; + +%ignore CVC4::operator<<(std::ostream&, const IntAnd&); + +%include "util/iand.h" diff --git a/src/util/index.cpp b/src/util/index.cpp index 6f036d537..3d9877135 100644 --- a/src/util/index.cpp +++ b/src/util/index.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/index.h b/src/util/index.h index 2ee6ff19e..05227f0d3 100644 --- a/src/util/index.h +++ b/src/util/index.h @@ -2,9 +2,9 @@ /*! \file index.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/integer.h.in b/src/util/integer.h.in index 87a5e35d3..f13f68a82 100644 --- a/src/util/integer.h.in +++ b/src/util/integer.h.in @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/integer_cln_imp.cpp b/src/util/integer_cln_imp.cpp index 5cca2fcba..ca59822a7 100644 --- a/src/util/integer_cln_imp.cpp +++ b/src/util/integer_cln_imp.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Aina Niemetz, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/integer_cln_imp.h b/src/util/integer_cln_imp.h index aba5b6a3a..ff4bcdf69 100644 --- a/src/util/integer_cln_imp.h +++ b/src/util/integer_cln_imp.h @@ -2,9 +2,9 @@ /*! \file integer_cln_imp.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Liana Hadarean + ** Tim King, Gereon Kremer, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -24,6 +24,7 @@ #include <cln/integer.h> #include <cln/integer_io.h> #include <cln/modinteger.h> + #include <iostream> #include <limits> #include <sstream> @@ -35,53 +36,22 @@ namespace CVC4 { class Rational; -class CVC4_PUBLIC Integer { -private: - /** - * Stores the value of the rational is stored in a C++ CLN integer class. - */ - cln::cl_I d_value; - - /** - * Gets a reference to the cln data that backs up the integer. - * Only accessible to friend classes. - */ - const cln::cl_I& get_cl_I() const { return d_value; } +class CVC4_PUBLIC Integer +{ + friend class CVC4::Rational; + public: /** * Constructs an Integer by copying a CLN C++ primitive. */ Integer(const cln::cl_I& val) : d_value(val) {} - // Throws a std::invalid_argument on invalid input `s` for the given base. - void readInt(const cln::cl_read_flags& flags, - const std::string& s, - unsigned base); - - // Throws a std::invalid_argument on invalid inputs. - void parseInt(const std::string& s, unsigned base); - - // These constants are to help with CLN conversion in 32 bit. - // See http://www.ginac.de/CLN/cln.html#Conversions - static signed int s_fastSignedIntMax; /* 2^29 - 1 */ - static signed int s_fastSignedIntMin; /* -2^29 */ - static unsigned int s_fastUnsignedIntMax; /* 2^29 - 1 */ - - static signed long s_slowSignedIntMax; /* std::numeric_limits<signed int>::max() */ - static signed long s_slowSignedIntMin; /* std::numeric_limits<signed int>::min() */ - static unsigned long s_slowUnsignedIntMax; /* std::numeric_limits<unsigned int>::max() */ - static unsigned long s_signedLongMin; - static unsigned long s_signedLongMax; - static unsigned long s_unsignedLongMax; -public: /** Constructs a rational with the value 0. */ - Integer() : d_value(0){} + Integer() : d_value(0) {} /** * Constructs a Integer from a C string. - * Throws std::invalid_argument if the string is not a valid rational. - * For more information about what is a valid rational string, - * see GMP's documentation for mpq_set_str(). + * Throws std::invalid_argument if the string is not a valid integer. */ explicit Integer(const char* sp, unsigned base = 10) { @@ -95,13 +65,13 @@ public: Integer(const Integer& q) : d_value(q.d_value) {} - Integer( signed int z) : d_value((signed long int)z) {} + Integer(signed int z) : d_value((signed long int)z) {} Integer(unsigned int z) : d_value((unsigned long int)z) {} - Integer( signed long int z) : d_value(z) {} + Integer(signed long int z) : d_value(z) {} Integer(unsigned long int z) : d_value(z) {} #ifdef CVC4_NEED_INT64_T_OVERLOADS - Integer( int64_t z) : d_value(static_cast<long>(z)) {} + Integer(int64_t z) : d_value(static_cast<long>(z)) {} Integer(uint64_t z) : d_value(static_cast<unsigned long>(z)) {} #endif /* CVC4_NEED_INT64_T_OVERLOADS */ @@ -110,103 +80,90 @@ public: /** * Returns a copy of d_value to enable public access of CLN data. */ - cln::cl_I getValue() const - { - return d_value; - } + const cln::cl_I& getValue() const { return d_value; } - Integer& operator=(const Integer& x){ - if(this == &x) return *this; + Integer& operator=(const Integer& x) + { + if (this == &x) return *this; d_value = x.d_value; return *this; } - bool operator==(const Integer& y) const { - return d_value == y.d_value; - } - - Integer operator-() const{ - return Integer(-(d_value)); - } + bool operator==(const Integer& y) const { return d_value == y.d_value; } + Integer operator-() const { return Integer(-(d_value)); } - bool operator!=(const Integer& y) const { - return d_value != y.d_value; - } + bool operator!=(const Integer& y) const { return d_value != y.d_value; } - bool operator< (const Integer& y) const { - return d_value < y.d_value; - } + bool operator<(const Integer& y) const { return d_value < y.d_value; } - bool operator<=(const Integer& y) const { - return d_value <= y.d_value; - } + bool operator<=(const Integer& y) const { return d_value <= y.d_value; } - bool operator> (const Integer& y) const { - return d_value > y.d_value; - } + bool operator>(const Integer& y) const { return d_value > y.d_value; } - bool operator>=(const Integer& y) const { - return d_value >= y.d_value; - } + bool operator>=(const Integer& y) const { return d_value >= y.d_value; } - - Integer operator+(const Integer& y) const { - return Integer( d_value + y.d_value ); + Integer operator+(const Integer& y) const + { + return Integer(d_value + y.d_value); } - Integer& operator+=(const Integer& y) { + Integer& operator+=(const Integer& y) + { d_value += y.d_value; return *this; } - Integer operator-(const Integer& y) const { - return Integer( d_value - y.d_value ); + Integer operator-(const Integer& y) const + { + return Integer(d_value - y.d_value); } - Integer& operator-=(const Integer& y) { + Integer& operator-=(const Integer& y) + { d_value -= y.d_value; return *this; } - Integer operator*(const Integer& y) const { - return Integer( d_value * y.d_value ); + Integer operator*(const Integer& y) const + { + return Integer(d_value * y.d_value); } - Integer& operator*=(const Integer& y) { + Integer& operator*=(const Integer& y) + { d_value *= y.d_value; return *this; } - - Integer bitwiseOr(const Integer& y) const { + Integer bitwiseOr(const Integer& y) const + { return Integer(cln::logior(d_value, y.d_value)); } - Integer bitwiseAnd(const Integer& y) const { + Integer bitwiseAnd(const Integer& y) const + { return Integer(cln::logand(d_value, y.d_value)); } - Integer bitwiseXor(const Integer& y) const { + Integer bitwiseXor(const Integer& y) const + { return Integer(cln::logxor(d_value, y.d_value)); } - Integer bitwiseNot() const { - return Integer(cln::lognot(d_value)); - } - + Integer bitwiseNot() const { return Integer(cln::lognot(d_value)); } /** * Return this*(2^pow). */ - Integer multiplyByPow2(uint32_t pow) const { + Integer multiplyByPow2(uint32_t pow) const + { cln::cl_I ipow(pow); - return Integer( d_value << ipow); + return Integer(d_value << ipow); } - bool isBitSet(uint32_t i) const { - return !extractBitRange(1, i).isZero(); - } + bool isBitSet(uint32_t i) const { return !extractBitRange(1, i).isZero(); } - Integer setBit(uint32_t i) const { + Integer setBit(uint32_t i) const + { cln::cl_I mask(1); mask = mask << i; return Integer(cln::logior(d_value, mask)); @@ -214,13 +171,11 @@ public: Integer oneExtend(uint32_t size, uint32_t amount) const; - uint32_t toUnsignedInt() const { - return cln::cl_I_to_uint(d_value); - } - + uint32_t toUnsignedInt() const { return cln::cl_I_to_uint(d_value); } /** See CLN Documentation. */ - Integer extractBitRange(uint32_t bitCount, uint32_t low) const { + Integer extractBitRange(uint32_t bitCount, uint32_t low) const + { cln::cl_byte range(bitCount, low); return Integer(cln::ldb(d_value, range)); } @@ -228,20 +183,26 @@ public: /** * Returns the floor(this / y) */ - Integer floorDivideQuotient(const Integer& y) const { - return Integer( cln::floor1(d_value, y.d_value) ); + Integer floorDivideQuotient(const Integer& y) const + { + return Integer(cln::floor1(d_value, y.d_value)); } /** * Returns r == this - floor(this/y)*y */ - Integer floorDivideRemainder(const Integer& y) const { - return Integer( cln::floor2(d_value, y.d_value).remainder ); + Integer floorDivideRemainder(const Integer& y) const + { + return Integer(cln::floor2(d_value, y.d_value).remainder); } - /** + /** * Computes a floor quoient and remainder for x divided by y. */ - static void floorQR(Integer& q, Integer& r, const Integer& x, const Integer& y) { + static void floorQR(Integer& q, + Integer& r, + const Integer& x, + const Integer& y) + { cln::cl_I_div_t res = cln::floor2(x.d_value, y.d_value); q.d_value = res.quotient; r.d_value = res.remainder; @@ -250,43 +211,53 @@ public: /** * Returns the ceil(this / y) */ - Integer ceilingDivideQuotient(const Integer& y) const { - return Integer( cln::ceiling1(d_value, y.d_value) ); + Integer ceilingDivideQuotient(const Integer& y) const + { + return Integer(cln::ceiling1(d_value, y.d_value)); } /** * Returns the ceil(this / y) */ - Integer ceilingDivideRemainder(const Integer& y) const { - return Integer( cln::ceiling2(d_value, y.d_value).remainder ); + Integer ceilingDivideRemainder(const Integer& y) const + { + return Integer(cln::ceiling2(d_value, y.d_value).remainder); } /** - * Computes a quoitent and remainder according to Boute's Euclidean definition. - * euclidianDivideQuotient, euclidianDivideRemainder. + * Computes a quoitent and remainder according to Boute's Euclidean + * definition. euclidianDivideQuotient, euclidianDivideRemainder. * * Boute, Raymond T. (April 1992). * The Euclidean definition of the functions div and mod. * ACM Transactions on Programming Languages and Systems (TOPLAS) * ACM Press. 14 (2): 127 - 144. doi:10.1145/128861.128862. */ - static void euclidianQR(Integer& q, Integer& r, const Integer& x, const Integer& y) { + static void euclidianQR(Integer& q, + Integer& r, + const Integer& x, + const Integer& y) + { // compute the floor and then fix the value up if needed. - floorQR(q,r,x,y); + floorQR(q, r, x, y); - if(r.strictlyNegative()){ + if (r.strictlyNegative()) + { // if r < 0 // abs(r) < abs(y) // - abs(y) < r < 0, then 0 < r + abs(y) < abs(y) // n = y * q + r // n = y * q - abs(y) + r + abs(y) - if(r.sgn() >= 0){ + if (r.sgn() >= 0) + { // y = abs(y) // n = y * q - y + r + y // n = y * (q-1) + (r+y) q -= 1; r += y; - }else{ + } + else + { // y = -abs(y) // n = y * q + y + r - y // n = y * (q+1) + (r-y) @@ -300,9 +271,10 @@ public: * Returns the quoitent according to Boute's Euclidean definition. * See the documentation for euclidianQR. */ - Integer euclidianDivideQuotient(const Integer& y) const { - Integer q,r; - euclidianQR(q,r, *this, y); + Integer euclidianDivideQuotient(const Integer& y) const + { + Integer q, r; + euclidianQR(q, r, *this, y); return q; } @@ -310,9 +282,10 @@ public: * Returns the remainfing according to Boute's Euclidean definition. * See the documentation for euclidianQR. */ - Integer euclidianDivideRemainder(const Integer& y) const { - Integer q,r; - euclidianQR(q,r, *this, y); + Integer euclidianDivideRemainder(const Integer& y) const + { + Integer q, r; + euclidianQR(q, r, *this, y); return r; } @@ -321,14 +294,13 @@ public: */ Integer exactQuotient(const Integer& y) const; - Integer modByPow2(uint32_t exp) const { + Integer modByPow2(uint32_t exp) const + { cln::cl_byte range(exp, 0); return Integer(cln::ldb(d_value, range)); } - Integer divByPow2(uint32_t exp) const { - return d_value >> exp; - } + Integer divByPow2(uint32_t exp) const { return d_value >> exp; } /** * Raise this Integer to the power <code>exp</code>. @@ -340,7 +312,8 @@ public: /** * Return the greatest common divisor of this integer with another. */ - Integer gcd(const Integer& y) const { + Integer gcd(const Integer& y) const + { cln::cl_I result = cln::gcd(d_value, y.d_value); return Integer(result); } @@ -348,7 +321,8 @@ public: /** * Return the least common multiple of this integer with another. */ - Integer lcm(const Integer& y) const { + Integer lcm(const Integer& y) const + { cln::cl_I result = cln::lcm(d_value, y.d_value); return Integer(result); } @@ -380,7 +354,8 @@ public: /** * Return true if *this exactly divides y. */ - bool divides(const Integer& y) const { + bool divides(const Integer& y) const + { cln::cl_I result = cln::rem(y.d_value, d_value); return cln::zerop(result); } @@ -388,31 +363,24 @@ public: /** * Return the absolute value of this integer. */ - Integer abs() const { - return d_value >= 0 ? *this : -*this; - } + Integer abs() const { return d_value >= 0 ? *this : -*this; } - std::string toString(int base = 10) const{ + std::string toString(int base = 10) const + { std::stringstream ss; - switch(base){ - case 2: - fprintbinary(ss,d_value); - break; - case 8: - fprintoctal(ss,d_value); - break; - case 10: - fprintdecimal(ss,d_value); - break; - case 16: - fprinthexadecimal(ss,d_value); - break; - default: - throw Exception("Unhandled base in Integer::toString()"); + switch (base) + { + case 2: fprintbinary(ss, d_value); break; + case 8: fprintoctal(ss, d_value); break; + case 10: fprintdecimal(ss, d_value); break; + case 16: fprinthexadecimal(ss, d_value); break; + default: throw Exception("Unhandled base in Integer::toString()"); } std::string output = ss.str(); - for( unsigned i = 0; i <= output.length(); ++i){ - if(isalpha(output[i])){ + for (unsigned i = 0; i <= output.length(); ++i) + { + if (isalpha(output[i])) + { output.replace(i, 1, 1, tolower(output[i])); } } @@ -420,31 +388,21 @@ public: return output; } - int sgn() const { + int sgn() const + { cln::cl_I sgn = cln::signum(d_value); return cln::cl_I_to_int(sgn); } + inline bool strictlyPositive() const { return sgn() > 0; } - inline bool strictlyPositive() const { - return sgn() > 0; - } - - inline bool strictlyNegative() const { - return sgn() < 0; - } + inline bool strictlyNegative() const { return sgn() < 0; } - inline bool isZero() const { - return sgn() == 0; - } + inline bool isZero() const { return sgn() == 0; } - inline bool isOne() const { - return d_value == 1; - } + inline bool isOne() const { return d_value == 1; } - inline bool isNegativeOne() const { - return d_value == -1; - } + inline bool isNegativeOne() const { return d_value == -1; } /** fits the C "signed int" primitive */ bool fitsSignedInt() const; @@ -460,20 +418,26 @@ public: bool fitsUnsignedLong() const; - long getLong() const { + long getLong() const + { // ensure there isn't overflow - CheckArgument(d_value <= std::numeric_limits<long>::max(), this, + CheckArgument(d_value <= std::numeric_limits<long>::max(), + this, "Overflow detected in Integer::getLong()"); - CheckArgument(d_value >= std::numeric_limits<long>::min(), this, + CheckArgument(d_value >= std::numeric_limits<long>::min(), + this, "Overflow detected in Integer::getLong()"); return cln::cl_I_to_long(d_value); } - unsigned long getUnsignedLong() const { + unsigned long getUnsignedLong() const + { // ensure there isn't overflow - CheckArgument(d_value <= std::numeric_limits<unsigned long>::max(), this, + CheckArgument(d_value <= std::numeric_limits<unsigned long>::max(), + this, "Overflow detected in Integer::getUnsignedLong()"); - CheckArgument(d_value >= std::numeric_limits<unsigned long>::min(), this, + CheckArgument(d_value >= std::numeric_limits<unsigned long>::min(), + this, "Overflow detected in Integer::getUnsignedLong()"); return cln::cl_I_to_ulong(d_value); } @@ -482,9 +446,7 @@ public: * Computes the hash of the node from the first word of the * numerator, the denominator. */ - size_t hash() const { - return equal_hashcode(d_value); - } + size_t hash() const { return equal_hashcode(d_value); } /** * Returns true iff bit n is set. @@ -492,15 +454,14 @@ public: * @param n the bit to test (0 == least significant bit) * @return true if bit n is set in this integer; false otherwise */ - bool testBit(unsigned n) const { - return cln::logbitp(n, d_value); - } + bool testBit(unsigned n) const { return cln::logbitp(n, d_value); } /** * Returns k if the integer is equal to 2^(k-1) * @return k if the integer is equal to 2^(k-1) and 0 otherwise */ - unsigned isPow2() const { + unsigned isPow2() const + { if (d_value <= 0) return 0; // power2p returns n such that d_value = 2^(n-1) return cln::power2p(d_value); @@ -510,53 +471,101 @@ public: * If x != 0, returns the unique n s.t. 2^{n-1} <= abs(x) < 2^{n}. * If x == 0, returns 1. */ - size_t length() const { + size_t length() const + { int s = sgn(); - if(s == 0){ + if (s == 0) + { return 1; - }else if(s < 0){ + } + else if (s < 0) + { size_t len = cln::integer_length(d_value); - /*If this is -2^n, return len+1 not len to stay consistent with the definition above! - * From CLN's documentation of integer_length: - * This is the smallest n >= 0 such that -2^n <= x < 2^n. - * If x > 0, this is the unique n > 0 such that 2^(n-1) <= x < 2^n. + /*If this is -2^n, return len+1 not len to stay consistent with the + * definition above! From CLN's documentation of integer_length: This is + * the smallest n >= 0 such that -2^n <= x < 2^n. If x > 0, this is the + * unique n > 0 such that 2^(n-1) <= x < 2^n. */ size_t ord2 = cln::ord2(d_value); return (len == ord2) ? (len + 1) : len; - }else{ + } + else + { return cln::integer_length(d_value); } } -/* cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v) */ -/* This function ("extended gcd") returns the greatest common divisor g of a and b and at the same time the representation of g as an integral linear combination of a and b: u and v with u*a+v*b = g, g >= 0. u and v will be normalized to be of smallest possible absolute value, in the following sense: If a and b are non-zero, and abs(a) != abs(b), u and v will satisfy the inequalities abs(u) <= abs(b)/(2*g), abs(v) <= abs(a)/(2*g). */ - static void extendedGcd(Integer& g, Integer& s, Integer& t, const Integer& a, const Integer& b){ + /* cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v) */ + /* This function ("extended gcd") returns the greatest common divisor g of a + * and b and at the same time the representation of g as an integral linear + * combination of a and b: u and v with u*a+v*b = g, g >= 0. u and v will be + * normalized to be of smallest possible absolute value, in the following + * sense: If a and b are non-zero, and abs(a) != abs(b), u and v will satisfy + * the inequalities abs(u) <= abs(b)/(2*g), abs(v) <= abs(a)/(2*g). */ + static void extendedGcd( + Integer& g, Integer& s, Integer& t, const Integer& a, const Integer& b) + { g.d_value = cln::xgcd(a.d_value, b.d_value, &s.d_value, &t.d_value); } /** Returns a reference to the minimum of two integers. */ - static const Integer& min(const Integer& a, const Integer& b){ - return (a <=b ) ? a : b; + static const Integer& min(const Integer& a, const Integer& b) + { + return (a <= b) ? a : b; } /** Returns a reference to the maximum of two integers. */ - static const Integer& max(const Integer& a, const Integer& b){ - return (a >= b ) ? a : b; + static const Integer& max(const Integer& a, const Integer& b) + { + return (a >= b) ? a : b; } - friend class CVC4::Rational; -};/* class Integer */ + private: + /** + * Gets a reference to the cln data that backs up the integer. + * Only accessible to friend classes. + */ + const cln::cl_I& get_cl_I() const { return d_value; } + // Throws a std::invalid_argument on invalid input `s` for the given base. + void readInt(const cln::cl_read_flags& flags, + const std::string& s, + unsigned base); -struct IntegerHashFunction { - inline size_t operator()(const CVC4::Integer& i) const { - return i.hash(); - } -};/* struct IntegerHashFunction */ + // Throws a std::invalid_argument on invalid inputs. + void parseInt(const std::string& s, unsigned base); + + // These constants are to help with CLN conversion in 32 bit. + // See http://www.ginac.de/CLN/cln.html#Conversions + static signed int s_fastSignedIntMax; /* 2^29 - 1 */ + static signed int s_fastSignedIntMin; /* -2^29 */ + static unsigned int s_fastUnsignedIntMax; /* 2^29 - 1 */ + + static signed long + s_slowSignedIntMax; /* std::numeric_limits<signed int>::max() */ + static signed long + s_slowSignedIntMin; /* std::numeric_limits<signed int>::min() */ + static unsigned long + s_slowUnsignedIntMax; /* std::numeric_limits<unsigned int>::max() */ + static unsigned long s_signedLongMin; + static unsigned long s_signedLongMax; + static unsigned long s_unsignedLongMax; + + /** + * Stores the value of the rational is stored in a C++ CLN integer class. + */ + cln::cl_I d_value; +}; /* class Integer */ + +struct IntegerHashFunction +{ + inline size_t operator()(const CVC4::Integer& i) const { return i.hash(); } +}; /* struct IntegerHashFunction */ -inline std::ostream& operator<<(std::ostream& os, const Integer& n) { +inline std::ostream& operator<<(std::ostream& os, const Integer& n) +{ return os << n.toString(); } -}/* CVC4 namespace */ +} // namespace CVC4 #endif /* CVC4__INTEGER_H */ diff --git a/src/util/integer_gmp_imp.cpp b/src/util/integer_gmp_imp.cpp index 2bc11f0a7..8c59d74b8 100644 --- a/src/util/integer_gmp_imp.cpp +++ b/src/util/integer_gmp_imp.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Aina Niemetz, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/integer_gmp_imp.h b/src/util/integer_gmp_imp.h index 144e88536..5277923f4 100644 --- a/src/util/integer_gmp_imp.h +++ b/src/util/integer_gmp_imp.h @@ -2,9 +2,9 @@ /*! \file integer_gmp_imp.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Liana Hadarean, Morgan Deters + ** Tim King, Gereon Kremer, Liana Hadarean ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -20,9 +20,9 @@ #ifndef CVC4__INTEGER_H #define CVC4__INTEGER_H -#include <string> #include <iosfwd> #include <limits> +#include <string> #include "base/exception.h" #include "util/gmp_util.h" @@ -31,29 +31,18 @@ namespace CVC4 { class Rational; -class CVC4_PUBLIC Integer { -private: - /** - * Stores the value of the rational is stored in a C++ GMP integer class. - * Using this instead of mpz_t allows for easier destruction. - */ - mpz_class d_value; - - /** - * Gets a reference to the gmp data that backs up the integer. - * Only accessible to friend classes. - */ - const mpz_class& get_mpz() const { return d_value; } +class CVC4_PUBLIC Integer +{ + friend class CVC4::Rational; + public: /** * Constructs an Integer by copying a GMP C++ primitive. */ Integer(const mpz_class& val) : d_value(val) {} -public: - /** Constructs a rational with the value 0. */ - Integer() : d_value(0){} + Integer() : d_value(0) {} /** * Constructs a Integer from a C string. @@ -66,13 +55,13 @@ public: Integer(const Integer& q) : d_value(q.d_value) {} - Integer( signed int z) : d_value(z) {} + Integer(signed int z) : d_value(z) {} Integer(unsigned int z) : d_value(z) {} - Integer( signed long int z) : d_value(z) {} + Integer(signed long int z) : d_value(z) {} Integer(unsigned long int z) : d_value(z) {} #ifdef CVC4_NEED_INT64_T_OVERLOADS - Integer( int64_t z) : d_value(static_cast<long>(z)) {} + Integer(int64_t z) : d_value(static_cast<long>(z)) {} Integer(uint64_t z) : d_value(static_cast<unsigned long>(z)) {} #endif /* CVC4_NEED_INT64_T_OVERLOADS */ @@ -81,91 +70,82 @@ public: /** * Returns a copy of d_value to enable public access of GMP data. */ - mpz_class getValue() const - { - return d_value; - } + const mpz_class& getValue() const { return d_value; } - Integer& operator=(const Integer& x){ - if(this == &x) return *this; + Integer& operator=(const Integer& x) + { + if (this == &x) return *this; d_value = x.d_value; return *this; } - bool operator==(const Integer& y) const { - return d_value == y.d_value; - } - - Integer operator-() const { - return Integer(-(d_value)); - } + bool operator==(const Integer& y) const { return d_value == y.d_value; } + Integer operator-() const { return Integer(-(d_value)); } - bool operator!=(const Integer& y) const { - return d_value != y.d_value; - } - - bool operator< (const Integer& y) const { - return d_value < y.d_value; - } + bool operator!=(const Integer& y) const { return d_value != y.d_value; } - bool operator<=(const Integer& y) const { - return d_value <= y.d_value; - } + bool operator<(const Integer& y) const { return d_value < y.d_value; } - bool operator> (const Integer& y) const { - return d_value > y.d_value; - } + bool operator<=(const Integer& y) const { return d_value <= y.d_value; } - bool operator>=(const Integer& y) const { - return d_value >= y.d_value; - } + bool operator>(const Integer& y) const { return d_value > y.d_value; } + bool operator>=(const Integer& y) const { return d_value >= y.d_value; } - Integer operator+(const Integer& y) const { - return Integer( d_value + y.d_value ); + Integer operator+(const Integer& y) const + { + return Integer(d_value + y.d_value); } - Integer& operator+=(const Integer& y) { + Integer& operator+=(const Integer& y) + { d_value += y.d_value; return *this; } - Integer operator-(const Integer& y) const { - return Integer( d_value - y.d_value ); + Integer operator-(const Integer& y) const + { + return Integer(d_value - y.d_value); } - Integer& operator-=(const Integer& y) { + Integer& operator-=(const Integer& y) + { d_value -= y.d_value; return *this; } - Integer operator*(const Integer& y) const { - return Integer( d_value * y.d_value ); + Integer operator*(const Integer& y) const + { + return Integer(d_value * y.d_value); } - Integer& operator*=(const Integer& y) { + Integer& operator*=(const Integer& y) + { d_value *= y.d_value; return *this; } - - Integer bitwiseOr(const Integer& y) const { + Integer bitwiseOr(const Integer& y) const + { mpz_class result; mpz_ior(result.get_mpz_t(), d_value.get_mpz_t(), y.d_value.get_mpz_t()); return Integer(result); } - Integer bitwiseAnd(const Integer& y) const { + Integer bitwiseAnd(const Integer& y) const + { mpz_class result; mpz_and(result.get_mpz_t(), d_value.get_mpz_t(), y.d_value.get_mpz_t()); return Integer(result); } - Integer bitwiseXor(const Integer& y) const { + Integer bitwiseXor(const Integer& y) const + { mpz_class result; mpz_xor(result.get_mpz_t(), d_value.get_mpz_t(), y.d_value.get_mpz_t()); return Integer(result); } - Integer bitwiseNot() const { + Integer bitwiseNot() const + { mpz_class result; mpz_com(result.get_mpz_t(), d_value.get_mpz_t()); return Integer(result); @@ -174,25 +154,25 @@ public: /** * Return this*(2^pow). */ - Integer multiplyByPow2(uint32_t pow) const{ + Integer multiplyByPow2(uint32_t pow) const + { mpz_class result; mpz_mul_2exp(result.get_mpz_t(), d_value.get_mpz_t(), pow); - return Integer( result ); + return Integer(result); } /** * Returns the Integer obtained by setting the ith bit of the * current Integer to 1. */ - Integer setBit(uint32_t i) const { + Integer setBit(uint32_t i) const + { mpz_class res = d_value; mpz_setbit(res.get_mpz_t(), i); return Integer(res); } - bool isBitSet(uint32_t i) const { - return !extractBitRange(1, i).isZero(); - } + bool isBitSet(uint32_t i) const { return !extractBitRange(1, i).isZero(); } /** * Returns the integer with the binary representation of size bits @@ -200,17 +180,16 @@ public: */ Integer oneExtend(uint32_t size, uint32_t amount) const; - uint32_t toUnsignedInt() const { - return mpz_get_ui(d_value.get_mpz_t()); - } + uint32_t toUnsignedInt() const { return mpz_get_ui(d_value.get_mpz_t()); } /** See GMP Documentation. */ - Integer extractBitRange(uint32_t bitCount, uint32_t low) const { + Integer extractBitRange(uint32_t bitCount, uint32_t low) const + { // bitCount = high-low+1 - uint32_t high = low + bitCount-1; + uint32_t high = low + bitCount - 1; //— Function: void mpz_fdiv_r_2exp (mpz_t r, mpz_t n, mp_bitcnt_t b) mpz_class rem, div; - mpz_fdiv_r_2exp(rem.get_mpz_t(), d_value.get_mpz_t(), high+1); + mpz_fdiv_r_2exp(rem.get_mpz_t(), d_value.get_mpz_t(), high + 1); mpz_fdiv_q_2exp(div.get_mpz_t(), rem.get_mpz_t(), low); return Integer(div); @@ -219,72 +198,91 @@ public: /** * Returns the floor(this / y) */ - Integer floorDivideQuotient(const Integer& y) const { + Integer floorDivideQuotient(const Integer& y) const + { mpz_class q; mpz_fdiv_q(q.get_mpz_t(), d_value.get_mpz_t(), y.d_value.get_mpz_t()); - return Integer( q ); + return Integer(q); } /** * Returns r == this - floor(this/y)*y */ - Integer floorDivideRemainder(const Integer& y) const { + Integer floorDivideRemainder(const Integer& y) const + { mpz_class r; mpz_fdiv_r(r.get_mpz_t(), d_value.get_mpz_t(), y.d_value.get_mpz_t()); - return Integer( r ); + return Integer(r); } /** * Computes a floor quotient and remainder for x divided by y. */ - static void floorQR(Integer& q, Integer& r, const Integer& x, const Integer& y) { - mpz_fdiv_qr(q.d_value.get_mpz_t(), r.d_value.get_mpz_t(), x.d_value.get_mpz_t(), y.d_value.get_mpz_t()); + static void floorQR(Integer& q, + Integer& r, + const Integer& x, + const Integer& y) + { + mpz_fdiv_qr(q.d_value.get_mpz_t(), + r.d_value.get_mpz_t(), + x.d_value.get_mpz_t(), + y.d_value.get_mpz_t()); } /** * Returns the ceil(this / y) */ - Integer ceilingDivideQuotient(const Integer& y) const { + Integer ceilingDivideQuotient(const Integer& y) const + { mpz_class q; mpz_cdiv_q(q.get_mpz_t(), d_value.get_mpz_t(), y.d_value.get_mpz_t()); - return Integer( q ); + return Integer(q); } /** * Returns the ceil(this / y) */ - Integer ceilingDivideRemainder(const Integer& y) const { + Integer ceilingDivideRemainder(const Integer& y) const + { mpz_class r; mpz_cdiv_r(r.get_mpz_t(), d_value.get_mpz_t(), y.d_value.get_mpz_t()); - return Integer( r ); + return Integer(r); } /** - * Computes a quotient and remainder according to Boute's Euclidean definition. - * euclidianDivideQuotient, euclidianDivideRemainder. + * Computes a quotient and remainder according to Boute's Euclidean + * definition. euclidianDivideQuotient, euclidianDivideRemainder. * * Boute, Raymond T. (April 1992). * The Euclidean definition of the functions div and mod. * ACM Transactions on Programming Languages and Systems (TOPLAS) * ACM Press. 14 (2): 127 - 144. doi:10.1145/128861.128862. */ - static void euclidianQR(Integer& q, Integer& r, const Integer& x, const Integer& y) { + static void euclidianQR(Integer& q, + Integer& r, + const Integer& x, + const Integer& y) + { // compute the floor and then fix the value up if needed. - floorQR(q,r,x,y); + floorQR(q, r, x, y); - if(r.strictlyNegative()){ + if (r.strictlyNegative()) + { // if r < 0 // abs(r) < abs(y) // - abs(y) < r < 0, then 0 < r + abs(y) < abs(y) // n = y * q + r // n = y * q - abs(y) + r + abs(y) - if(r.sgn() >= 0){ + if (r.sgn() >= 0) + { // y = abs(y) // n = y * q - y + r + y // n = y * (q-1) + (r+y) q -= 1; r += y; - }else{ + } + else + { // y = -abs(y) // n = y * q + y + r - y // n = y * (q+1) + (r-y) @@ -298,9 +296,10 @@ public: * Returns the quotient according to Boute's Euclidean definition. * See the documentation for euclidianQR. */ - Integer euclidianDivideQuotient(const Integer& y) const { - Integer q,r; - euclidianQR(q,r, *this, y); + Integer euclidianDivideQuotient(const Integer& y) const + { + Integer q, r; + euclidianQR(q, r, *this, y); return q; } @@ -308,13 +307,13 @@ public: * Returns the remainder according to Boute's Euclidean definition. * See the documentation for euclidianQR. */ - Integer euclidianDivideRemainder(const Integer& y) const { - Integer q,r; - euclidianQR(q,r, *this, y); + Integer euclidianDivideRemainder(const Integer& y) const + { + Integer q, r; + euclidianQR(q, r, *this, y); return r; } - /** * If y divides *this, then exactQuotient returns (this/y) */ @@ -323,7 +322,8 @@ public: /** * Returns y mod 2^exp */ - Integer modByPow2(uint32_t exp) const { + Integer modByPow2(uint32_t exp) const + { mpz_class res; mpz_fdiv_r_2exp(res.get_mpz_t(), d_value.get_mpz_t(), exp); return Integer(res); @@ -332,34 +332,25 @@ public: /** * Returns y / 2^exp */ - Integer divByPow2(uint32_t exp) const { + Integer divByPow2(uint32_t exp) const + { mpz_class res; mpz_fdiv_q_2exp(res.get_mpz_t(), d_value.get_mpz_t(), exp); return Integer(res); } + int sgn() const { return mpz_sgn(d_value.get_mpz_t()); } - int sgn() const { - return mpz_sgn(d_value.get_mpz_t()); - } + inline bool strictlyPositive() const { return sgn() > 0; } - inline bool strictlyPositive() const { - return sgn() > 0; - } + inline bool strictlyNegative() const { return sgn() < 0; } - inline bool strictlyNegative() const { - return sgn() < 0; - } - - inline bool isZero() const { - return sgn() == 0; - } + inline bool isZero() const { return sgn() == 0; } - bool isOne() const { - return mpz_cmp_si(d_value.get_mpz_t(), 1) == 0; - } + bool isOne() const { return mpz_cmp_si(d_value.get_mpz_t(), 1) == 0; } - bool isNegativeOne() const { + bool isNegativeOne() const + { return mpz_cmp_si(d_value.get_mpz_t(), -1) == 0; } @@ -368,7 +359,8 @@ public: * * @param exp the exponent */ - Integer pow(unsigned long int exp) const { + Integer pow(unsigned long int exp) const + { mpz_class result; mpz_pow_ui(result.get_mpz_t(), d_value.get_mpz_t(), exp); return Integer(result); @@ -377,7 +369,8 @@ public: /** * Return the greatest common divisor of this integer with another. */ - Integer gcd(const Integer& y) const { + Integer gcd(const Integer& y) const + { mpz_class result; mpz_gcd(result.get_mpz_t(), d_value.get_mpz_t(), y.d_value.get_mpz_t()); return Integer(result); @@ -386,7 +379,8 @@ public: /** * Return the least common multiple of this integer with another. */ - Integer lcm(const Integer& y) const { + Integer lcm(const Integer& y) const + { mpz_class result; mpz_lcm(result.get_mpz_t(), d_value.get_mpz_t(), y.d_value.get_mpz_t()); return Integer(result); @@ -420,7 +414,8 @@ public: * All non-zero integers z, z.divide(0) * ! zero.divides(zero) */ - bool divides(const Integer& y) const { + bool divides(const Integer& y) const + { int res = mpz_divisible_p(y.d_value.get_mpz_t(), d_value.get_mpz_t()); return res != 0; } @@ -428,13 +423,9 @@ public: /** * Return the absolute value of this integer. */ - Integer abs() const { - return d_value >= 0 ? *this : -*this; - } + Integer abs() const { return d_value >= 0 ? *this : -*this; } - std::string toString(int base = 10) const{ - return d_value.get_str(base); - } + std::string toString(int base = 10) const { return d_value.get_str(base); } bool fitsSignedInt() const; @@ -448,18 +439,22 @@ public: bool fitsUnsignedLong() const; - long getLong() const { + long getLong() const + { long si = d_value.get_si(); // ensure there wasn't overflow - CheckArgument(mpz_cmp_si(d_value.get_mpz_t(), si) == 0, this, - "Overflow detected in Integer::getLong()."); + CheckArgument(mpz_cmp_si(d_value.get_mpz_t(), si) == 0, + this, + "Overflow detected in Integer::getLong()."); return si; } - unsigned long getUnsignedLong() const { + unsigned long getUnsignedLong() const + { unsigned long ui = d_value.get_ui(); // ensure there wasn't overflow - CheckArgument(mpz_cmp_ui(d_value.get_mpz_t(), ui) == 0, this, + CheckArgument(mpz_cmp_ui(d_value.get_mpz_t(), ui) == 0, + this, "Overflow detected in Integer::getUnsignedLong()."); return ui; } @@ -468,9 +463,7 @@ public: * Computes the hash of the node from the first word of the * numerator, the denominator. */ - size_t hash() const { - return gmpz_hash(d_value.get_mpz_t()); - } + size_t hash() const { return gmpz_hash(d_value.get_mpz_t()); } /** * Returns true iff bit n is set. @@ -478,66 +471,88 @@ public: * @param n the bit to test (0 == least significant bit) * @return true if bit n is set in this integer; false otherwise */ - bool testBit(unsigned n) const { - return mpz_tstbit(d_value.get_mpz_t(), n); - } + bool testBit(unsigned n) const { return mpz_tstbit(d_value.get_mpz_t(), n); } /** * Returns k if the integer is equal to 2^(k-1) * @return k if the integer is equal to 2^(k-1) and 0 otherwise */ - unsigned isPow2() const { + unsigned isPow2() const + { if (d_value <= 0) return 0; // check that the number of ones in the binary representation is 1 - if (mpz_popcount(d_value.get_mpz_t()) == 1) { + if (mpz_popcount(d_value.get_mpz_t()) == 1) + { // return the index of the first one plus 1 return mpz_scan1(d_value.get_mpz_t(), 0) + 1; } - return 0; + return 0; } - /** * If x != 0, returns the smallest n s.t. 2^{n-1} <= abs(x) < 2^{n}. * If x == 0, returns 1. */ - size_t length() const { - if(sgn() == 0){ + size_t length() const + { + if (sgn() == 0) + { return 1; - }else{ - return mpz_sizeinbase(d_value.get_mpz_t(),2); + } + else + { + return mpz_sizeinbase(d_value.get_mpz_t(), 2); } } - static void extendedGcd(Integer& g, Integer& s, Integer& t, const Integer& a, const Integer& b){ - //see the documentation for: - //mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, mpz_t a, mpz_t b); - mpz_gcdext (g.d_value.get_mpz_t(), s.d_value.get_mpz_t(), t.d_value.get_mpz_t(), a.d_value.get_mpz_t(), b.d_value.get_mpz_t()); + static void extendedGcd( + Integer& g, Integer& s, Integer& t, const Integer& a, const Integer& b) + { + // see the documentation for: + // mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, mpz_t a, mpz_t b); + mpz_gcdext(g.d_value.get_mpz_t(), + s.d_value.get_mpz_t(), + t.d_value.get_mpz_t(), + a.d_value.get_mpz_t(), + b.d_value.get_mpz_t()); } /** Returns a reference to the minimum of two integers. */ - static const Integer& min(const Integer& a, const Integer& b){ - return (a <=b ) ? a : b; + static const Integer& min(const Integer& a, const Integer& b) + { + return (a <= b) ? a : b; } /** Returns a reference to the maximum of two integers. */ - static const Integer& max(const Integer& a, const Integer& b){ - return (a >= b ) ? a : b; + static const Integer& max(const Integer& a, const Integer& b) + { + return (a >= b) ? a : b; } - friend class CVC4::Rational; -};/* class Integer */ + private: + /** + * Gets a reference to the gmp data that backs up the integer. + * Only accessible to friend classes. + */ + const mpz_class& get_mpz() const { return d_value; } -struct IntegerHashFunction { - inline size_t operator()(const CVC4::Integer& i) const { - return i.hash(); - } -};/* struct IntegerHashFunction */ + /** + * Stores the value of the rational is stored in a C++ GMP integer class. + * Using this instead of mpz_t allows for easier destruction. + */ + mpz_class d_value; +}; /* class Integer */ + +struct IntegerHashFunction +{ + inline size_t operator()(const CVC4::Integer& i) const { return i.hash(); } +}; /* struct IntegerHashFunction */ -inline std::ostream& operator<<(std::ostream& os, const Integer& n) { +inline std::ostream& operator<<(std::ostream& os, const Integer& n) +{ return os << n.toString(); } -}/* CVC4 namespace */ +} // namespace CVC4 #endif /* CVC4__INTEGER_H */ diff --git a/src/util/maybe.h b/src/util/maybe.h index 33c6c6511..ed8c999a5 100644 --- a/src/util/maybe.h +++ b/src/util/maybe.h @@ -2,9 +2,9 @@ /*! \file maybe.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/ostream_util.cpp b/src/util/ostream_util.cpp index 3ada604ca..c8d81d363 100644 --- a/src/util/ostream_util.cpp +++ b/src/util/ostream_util.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/ostream_util.h b/src/util/ostream_util.h index 45d30a01c..e58ff8443 100644 --- a/src/util/ostream_util.h +++ b/src/util/ostream_util.h @@ -2,9 +2,9 @@ /*! \file ostream_util.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/proof.h b/src/util/proof.h index ac129e3aa..c89a3b0a6 100644 --- a/src/util/proof.h +++ b/src/util/proof.h @@ -2,9 +2,9 @@ /*! \file proof.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Guy Katz + ** Tim King, Morgan Deters, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/proof.i b/src/util/proof.i index 22dff1043..59a524a0f 100644 --- a/src/util/proof.i +++ b/src/util/proof.i @@ -2,4 +2,6 @@ #include "util/proof.h" %} +%ignore CVC4::Proof::toStream(std::ostream& out, const ProofLetMap& map) const; + %include "util/proof.h" diff --git a/src/util/random.cpp b/src/util/random.cpp index 325fac325..89b8c0513 100644 --- a/src/util/random.cpp +++ b/src/util/random.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/random.h b/src/util/random.h index 0b46a1f04..04bea1b69 100644 --- a/src/util/random.h +++ b/src/util/random.h @@ -2,9 +2,9 @@ /*! \file random.h ** \verbatim ** Top contributors (to current version): - ** Aina Niemetz, Andres Noetzli + ** Aina Niemetz, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/rational.h.in b/src/util/rational.h.in index 5da7a501e..b5934cc10 100644 --- a/src/util/rational.h.in +++ b/src/util/rational.h.in @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/rational_cln_imp.cpp b/src/util/rational_cln_imp.cpp index d19f99d31..2624698bc 100644 --- a/src/util/rational_cln_imp.cpp +++ b/src/util/rational_cln_imp.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Christopher L. Conway, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/rational_cln_imp.h b/src/util/rational_cln_imp.h index 660c4b075..724698363 100644 --- a/src/util/rational_cln_imp.h +++ b/src/util/rational_cln_imp.h @@ -2,9 +2,9 @@ /*! \file rational_cln_imp.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Christopher L. Conway + ** Tim King, Gereon Kremer, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -20,19 +20,19 @@ #ifndef CVC4__RATIONAL_H #define CVC4__RATIONAL_H -#include <gmp.h> -#include <string> -#include <sstream> -#include <cassert> -#include <cln/rational.h> +#include <cln/dfloat.h> #include <cln/input.h> #include <cln/io.h> +#include <cln/number_io.h> #include <cln/output.h> +#include <cln/rational.h> #include <cln/rational_io.h> -#include <cln/number_io.h> -#include <cln/dfloat.h> #include <cln/real.h> +#include <cassert> +#include <sstream> +#include <string> + #include "base/exception.h" #include "util/integer.h" #include "util/maybe.h" @@ -54,24 +54,14 @@ namespace CVC4 { ** in danger of invoking the char* constructor, from whence you will segfault. **/ -class CVC4_PUBLIC Rational { -private: +class CVC4_PUBLIC Rational +{ + public: /** - * Stores the value of the rational is stored in a C++ GMP rational class. - * Using this instead of mpq_t allows for easier destruction. - */ - cln::cl_RA d_value; - - /** - * Constructs a Rational from a mpq_class object. + * Constructs a Rational from a cln::cl_RA object. * Does a deep copy. - * Assumes that the value is in canonical form, and thus does not - * have to call canonicalize() on the value. */ - //Rational(const mpq_class& val) : d_value(val) { } - Rational(const cln::cl_RA& val) : d_value(val) { } - -public: + Rational(const cln::cl_RA& val) : d_value(val) {} /** * Creates a rational from a decimal string (e.g., <code>"1.5"</code>). @@ -82,14 +72,13 @@ public: static Rational fromDecimal(const std::string& dec); /** Constructs a rational with the value 0/1. */ - Rational() : d_value(0){ - } + Rational() : d_value(0) {} /** * Constructs a Rational from a C string in a given base (defaults to 10). * * Throws std::invalid_argument if the string is not a valid rational. * For more information about what is a valid rational string, - * see GMP's documentation for mpq_set_str(). + * see CLN's documentation for read_rational. */ explicit Rational(const char* s, unsigned base = 10) { @@ -98,11 +87,14 @@ public: flags.syntax = cln::syntax_rational; flags.lsyntax = cln::lsyntax_standard; flags.rational_base = base; - try{ + try + { d_value = read_rational(flags, s, NULL, NULL); - }catch(...){ + } + catch (...) + { std::stringstream ss; - ss << "Rational() failed to parse value \"" <<s << "\" in base=" <<base; + ss << "Rational() failed to parse value \"" << s << "\" in base=" << base; throw std::invalid_argument(ss.str()); } } @@ -113,11 +105,14 @@ public: flags.syntax = cln::syntax_rational; flags.lsyntax = cln::lsyntax_standard; flags.rational_base = base; - try{ + try + { d_value = read_rational(flags, s.c_str(), NULL, NULL); - }catch(...){ + } + catch (...) + { std::stringstream ss; - ss << "Rational() failed to parse value \"" <<s << "\" in base=" <<base; + ss << "Rational() failed to parse value \"" << s << "\" in base=" << base; throw std::invalid_argument(ss.str()); } } @@ -125,78 +120,76 @@ public: /** * Creates a Rational from another Rational, q, by performing a deep copy. */ - Rational(const Rational& q) : d_value(q.d_value) { } + Rational(const Rational& q) : d_value(q.d_value) {} /** * Constructs a canonical Rational from a numerator. */ - Rational(signed int n) : d_value((signed long int)n) { } - Rational(unsigned int n) : d_value((unsigned long int)n) { } - Rational(signed long int n) : d_value(n) { } - Rational(unsigned long int n) : d_value(n) { } + Rational(signed int n) : d_value((signed long int)n) {} + Rational(unsigned int n) : d_value((unsigned long int)n) {} + Rational(signed long int n) : d_value(n) {} + Rational(unsigned long int n) : d_value(n) {} #ifdef CVC4_NEED_INT64_T_OVERLOADS - Rational(int64_t n) : d_value(static_cast<long>(n)) { } - Rational(uint64_t n) : d_value(static_cast<unsigned long>(n)) { } + Rational(int64_t n) : d_value(static_cast<long>(n)) {} + Rational(uint64_t n) : d_value(static_cast<unsigned long>(n)) {} #endif /* CVC4_NEED_INT64_T_OVERLOADS */ /** * Constructs a canonical Rational from a numerator and denominator. */ - Rational(signed int n, signed int d) : d_value((signed long int)n) { + Rational(signed int n, signed int d) : d_value((signed long int)n) + { d_value /= cln::cl_I(d); } - Rational(unsigned int n, unsigned int d) : d_value((unsigned long int)n) { + Rational(unsigned int n, unsigned int d) : d_value((unsigned long int)n) + { d_value /= cln::cl_I(d); } - Rational(signed long int n, signed long int d) : d_value(n) { + Rational(signed long int n, signed long int d) : d_value(n) + { d_value /= cln::cl_I(d); } - Rational(unsigned long int n, unsigned long int d) : d_value(n) { + Rational(unsigned long int n, unsigned long int d) : d_value(n) + { d_value /= cln::cl_I(d); } #ifdef CVC4_NEED_INT64_T_OVERLOADS - Rational(int64_t n, int64_t d) : d_value(static_cast<long>(n)) { + Rational(int64_t n, int64_t d) : d_value(static_cast<long>(n)) + { d_value /= cln::cl_I(d); } - Rational(uint64_t n, uint64_t d) : d_value(static_cast<unsigned long>(n)) { + Rational(uint64_t n, uint64_t d) : d_value(static_cast<unsigned long>(n)) + { d_value /= cln::cl_I(d); } #endif /* CVC4_NEED_INT64_T_OVERLOADS */ - Rational(const Integer& n, const Integer& d) : - d_value(n.get_cl_I()) + Rational(const Integer& n, const Integer& d) : d_value(n.get_cl_I()) { d_value /= d.get_cl_I(); } - Rational(const Integer& n) : d_value(n.get_cl_I()){ } + Rational(const Integer& n) : d_value(n.get_cl_I()) {} ~Rational() {} /** * Returns a copy of d_value to enable public access of CLN data. */ - cln::cl_RA getValue() const - { - return d_value; - } + const cln::cl_RA& getValue() const { return d_value; } /** * Returns the value of numerator of the Rational. * Note that this makes a deep copy of the numerator. */ - Integer getNumerator() const { - return Integer(cln::numerator(d_value)); - } + Integer getNumerator() const { return Integer(cln::numerator(d_value)); } /** * Returns the value of denominator of the Rational. * Note that this makes a deep copy of the denominator. */ - Integer getDenominator() const { - return Integer(cln::denominator(d_value)); - } + Integer getDenominator() const { return Integer(cln::denominator(d_value)); } /** Return an exact rational for a double d. */ static Maybe<Rational> fromDouble(double d); @@ -206,138 +199,126 @@ public: * approximate: truncation may occur, overflow may result in * infinity, and underflow may result in zero. */ - double getDouble() const { - return cln::double_approx(d_value); - } + double getDouble() const { return cln::double_approx(d_value); } - Rational inverse() const { - return Rational(cln::recip(d_value)); - } + Rational inverse() const { return Rational(cln::recip(d_value)); } - int cmp(const Rational& x) const { - //Don't use mpq_class's cmp() function. - //The name ends up conflicting with this function. + int cmp(const Rational& x) const + { + // Don't use mpq_class's cmp() function. + // The name ends up conflicting with this function. return cln::compare(d_value, x.d_value); } - - int sgn() const { - if(cln::zerop(d_value)){ - return 0; - }else if(cln::minusp(d_value)){ - return -1; - }else{ + int sgn() const + { + if (cln::zerop(d_value)) + { + return 0; + } + else if (cln::minusp(d_value)) + { + return -1; + } + else + { assert(cln::plusp(d_value)); return 1; } } - bool isZero() const { - return cln::zerop(d_value); - } + bool isZero() const { return cln::zerop(d_value); } - bool isOne() const { - return d_value == 1; - } + bool isOne() const { return d_value == 1; } - bool isNegativeOne() const { - return d_value == -1; - } + bool isNegativeOne() const { return d_value == -1; } - Rational abs() const { - if(sgn() < 0){ + Rational abs() const + { + if (sgn() < 0) + { return -(*this); - }else{ + } + else + { return *this; } } - bool isIntegral() const{ - return getDenominator() == 1; - } + bool isIntegral() const { return getDenominator() == 1; } - Integer floor() const { - return Integer(cln::floor1(d_value)); - } + Integer floor() const { return Integer(cln::floor1(d_value)); } - Integer ceiling() const { - return Integer(cln::ceiling1(d_value)); - } + Integer ceiling() const { return Integer(cln::ceiling1(d_value)); } - Rational floor_frac() const { - return (*this) - Rational(floor()); - } + Rational floor_frac() const { return (*this) - Rational(floor()); } - Rational& operator=(const Rational& x){ - if(this == &x) return *this; + Rational& operator=(const Rational& x) + { + if (this == &x) return *this; d_value = x.d_value; return *this; } - Rational operator-() const{ - return Rational(-(d_value)); - } + Rational operator-() const { return Rational(-(d_value)); } - bool operator==(const Rational& y) const { - return d_value == y.d_value; - } + bool operator==(const Rational& y) const { return d_value == y.d_value; } - bool operator!=(const Rational& y) const { - return d_value != y.d_value; - } + bool operator!=(const Rational& y) const { return d_value != y.d_value; } - bool operator< (const Rational& y) const { - return d_value < y.d_value; - } + bool operator<(const Rational& y) const { return d_value < y.d_value; } - bool operator<=(const Rational& y) const { - return d_value <= y.d_value; - } + bool operator<=(const Rational& y) const { return d_value <= y.d_value; } - bool operator> (const Rational& y) const { - return d_value > y.d_value; - } + bool operator>(const Rational& y) const { return d_value > y.d_value; } - bool operator>=(const Rational& y) const { - return d_value >= y.d_value; - } + bool operator>=(const Rational& y) const { return d_value >= y.d_value; } - Rational operator+(const Rational& y) const{ - return Rational( d_value + y.d_value ); + Rational operator+(const Rational& y) const + { + return Rational(d_value + y.d_value); } - Rational operator-(const Rational& y) const { - return Rational( d_value - y.d_value ); + Rational operator-(const Rational& y) const + { + return Rational(d_value - y.d_value); } - Rational operator*(const Rational& y) const { - return Rational( d_value * y.d_value ); + Rational operator*(const Rational& y) const + { + return Rational(d_value * y.d_value); } - Rational operator/(const Rational& y) const { - return Rational( d_value / y.d_value ); + Rational operator/(const Rational& y) const + { + return Rational(d_value / y.d_value); } - Rational& operator+=(const Rational& y){ + Rational& operator+=(const Rational& y) + { d_value += y.d_value; return (*this); } - Rational& operator-=(const Rational& y){ + Rational& operator-=(const Rational& y) + { d_value -= y.d_value; return (*this); } - Rational& operator*=(const Rational& y){ + Rational& operator*=(const Rational& y) + { d_value *= y.d_value; return (*this); } - Rational& operator/=(const Rational& y){ + Rational& operator/=(const Rational& y) + { d_value /= y.d_value; return (*this); } /** Returns a string representing the rational in the given base. */ - std::string toString(int base = 10) const { + std::string toString(int base = 10) const + { cln::cl_print_flags flags; flags.rational_base = base; flags.rational_readably = false; @@ -350,27 +331,31 @@ public: * Computes the hash of the rational from hashes of the numerator and the * denominator. */ - size_t hash() const { - return equal_hashcode(d_value); - } + size_t hash() const { return equal_hashcode(d_value); } - uint32_t complexity() const { + uint32_t complexity() const + { return getNumerator().length() + getDenominator().length(); } /** Equivalent to calling (this->abs()).cmp(b.abs()) */ int absCmp(const Rational& q) const; -};/* class Rational */ + private: + /** + * Stores the value of the rational in a C++ CLN rational class. + */ + cln::cl_RA d_value; + +}; /* class Rational */ -struct RationalHashFunction { - inline size_t operator()(const CVC4::Rational& r) const { - return r.hash(); - } -};/* struct RationalHashFunction */ +struct RationalHashFunction +{ + inline size_t operator()(const CVC4::Rational& r) const { return r.hash(); } +}; /* struct RationalHashFunction */ CVC4_PUBLIC std::ostream& operator<<(std::ostream& os, const Rational& n); -}/* CVC4 namespace */ +} // namespace CVC4 #endif /* CVC4__RATIONAL_H */ diff --git a/src/util/rational_gmp_imp.cpp b/src/util/rational_gmp_imp.cpp index 0127381b6..a6442ac1f 100644 --- a/src/util/rational_gmp_imp.cpp +++ b/src/util/rational_gmp_imp.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Christopher L. Conway, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/rational_gmp_imp.h b/src/util/rational_gmp_imp.h index ff8a0f776..6054cd793 100644 --- a/src/util/rational_gmp_imp.h +++ b/src/util/rational_gmp_imp.h @@ -2,9 +2,9 @@ /*! \file rational_gmp_imp.h ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Christopher L. Conway + ** Tim King, Gereon Kremer, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -25,9 +25,9 @@ * cause errors: https://gcc.gnu.org/gcc-4.9/porting_to.html * Including <cstddef> is a workaround for this issue. */ -#include <cstddef> - #include <gmp.h> + +#include <cstddef> #include <string> #include "base/exception.h" @@ -51,23 +51,16 @@ namespace CVC4 { ** in danger of invoking the char* constructor, from whence you will segfault. **/ -class CVC4_PUBLIC Rational { -private: - /** - * Stores the value of the rational is stored in a C++ GMP rational class. - * Using this instead of mpq_t allows for easier destruction. - */ - mpq_class d_value; - +class CVC4_PUBLIC Rational +{ + public: /** * Constructs a Rational from a mpq_class object. * Does a deep copy. * Assumes that the value is in canonical form, and thus does not * have to call canonicalize() on the value. */ - Rational(const mpq_class& val) : d_value(val) { } - -public: + Rational(const mpq_class& val) : d_value(val) {} /** * Creates a rational from a decimal string (e.g., <code>"1.5"</code>). @@ -78,9 +71,7 @@ public: static Rational fromDecimal(const std::string& dec); /** Constructs a rational with the value 0/1. */ - Rational() : d_value(0){ - d_value.canonicalize(); - } + Rational() : d_value(0) { d_value.canonicalize(); } /** * Constructs a Rational from a C string in a given base (defaults to 10). @@ -89,41 +80,35 @@ public: * For more information about what is a valid rational string, * see GMP's documentation for mpq_set_str(). */ - explicit Rational(const char* s, unsigned base = 10): d_value(s, base) { + explicit Rational(const char* s, unsigned base = 10) : d_value(s, base) + { d_value.canonicalize(); } - Rational(const std::string& s, unsigned base = 10) : d_value(s, base) { + Rational(const std::string& s, unsigned base = 10) : d_value(s, base) + { d_value.canonicalize(); } /** * Creates a Rational from another Rational, q, by performing a deep copy. */ - Rational(const Rational& q) : d_value(q.d_value) { - d_value.canonicalize(); - } + Rational(const Rational& q) : d_value(q.d_value) { d_value.canonicalize(); } /** * Constructs a canonical Rational from a numerator. */ - Rational(signed int n) : d_value(n,1) { - d_value.canonicalize(); - } - Rational(unsigned int n) : d_value(n,1) { - d_value.canonicalize(); - } - Rational(signed long int n) : d_value(n,1) { - d_value.canonicalize(); - } - Rational(unsigned long int n) : d_value(n,1) { - d_value.canonicalize(); - } + Rational(signed int n) : d_value(n, 1) { d_value.canonicalize(); } + Rational(unsigned int n) : d_value(n, 1) { d_value.canonicalize(); } + Rational(signed long int n) : d_value(n, 1) { d_value.canonicalize(); } + Rational(unsigned long int n) : d_value(n, 1) { d_value.canonicalize(); } #ifdef CVC4_NEED_INT64_T_OVERLOADS - Rational(int64_t n) : d_value(static_cast<long>(n), 1) { + Rational(int64_t n) : d_value(static_cast<long>(n), 1) + { d_value.canonicalize(); } - Rational(uint64_t n) : d_value(static_cast<unsigned long>(n), 1) { + Rational(uint64_t n) : d_value(static_cast<unsigned long>(n), 1) + { d_value.canonicalize(); } #endif /* CVC4_NEED_INT64_T_OVERLOADS */ @@ -131,63 +116,60 @@ public: /** * Constructs a canonical Rational from a numerator and denominator. */ - Rational(signed int n, signed int d) : d_value(n,d) { + Rational(signed int n, signed int d) : d_value(n, d) + { d_value.canonicalize(); } - Rational(unsigned int n, unsigned int d) : d_value(n,d) { + Rational(unsigned int n, unsigned int d) : d_value(n, d) + { d_value.canonicalize(); } - Rational(signed long int n, signed long int d) : d_value(n,d) { + Rational(signed long int n, signed long int d) : d_value(n, d) + { d_value.canonicalize(); } - Rational(unsigned long int n, unsigned long int d) : d_value(n,d) { + Rational(unsigned long int n, unsigned long int d) : d_value(n, d) + { d_value.canonicalize(); } #ifdef CVC4_NEED_INT64_T_OVERLOADS - Rational(int64_t n, int64_t d) : d_value(static_cast<long>(n), static_cast<long>(d)) { + Rational(int64_t n, int64_t d) + : d_value(static_cast<long>(n), static_cast<long>(d)) + { d_value.canonicalize(); } - Rational(uint64_t n, uint64_t d) : d_value(static_cast<unsigned long>(n), static_cast<unsigned long>(d)) { + Rational(uint64_t n, uint64_t d) + : d_value(static_cast<unsigned long>(n), static_cast<unsigned long>(d)) + { d_value.canonicalize(); } #endif /* CVC4_NEED_INT64_T_OVERLOADS */ - Rational(const Integer& n, const Integer& d) : - d_value(n.get_mpz(), d.get_mpz()) - { - d_value.canonicalize(); - } - Rational(const Integer& n) : - d_value(n.get_mpz()) + Rational(const Integer& n, const Integer& d) + : d_value(n.get_mpz(), d.get_mpz()) { d_value.canonicalize(); } + Rational(const Integer& n) : d_value(n.get_mpz()) { d_value.canonicalize(); } ~Rational() {} /** * Returns a copy of d_value to enable public access of GMP data. */ - mpq_class getValue() const - { - return d_value; - } + const mpq_class& getValue() const { return d_value; } /** * Returns the value of numerator of the Rational. * Note that this makes a deep copy of the numerator. */ - Integer getNumerator() const { - return Integer(d_value.get_num()); - } + Integer getNumerator() const { return Integer(d_value.get_num()); } /** * Returns the value of denominator of the Rational. * Note that this makes a deep copy of the denominator. */ - Integer getDenominator() const { - return Integer(d_value.get_den()); - } + Integer getDenominator() const { return Integer(d_value.get_den()); } static Maybe<Rational> fromDouble(double d); @@ -196,166 +178,164 @@ public: * approximate: truncation may occur, overflow may result in * infinity, and underflow may result in zero. */ - double getDouble() const { - return d_value.get_d(); - } + double getDouble() const { return d_value.get_d(); } - Rational inverse() const { + Rational inverse() const + { return Rational(getDenominator(), getNumerator()); } - int cmp(const Rational& x) const { - //Don't use mpq_class's cmp() function. - //The name ends up conflicting with this function. + int cmp(const Rational& x) const + { + // Don't use mpq_class's cmp() function. + // The name ends up conflicting with this function. return mpq_cmp(d_value.get_mpq_t(), x.d_value.get_mpq_t()); } - int sgn() const { - return mpq_sgn(d_value.get_mpq_t()); - } + int sgn() const { return mpq_sgn(d_value.get_mpq_t()); } - bool isZero() const { - return sgn() == 0; - } + bool isZero() const { return sgn() == 0; } - bool isOne() const { - return mpq_cmp_si(d_value.get_mpq_t(), 1, 1) == 0; - } + bool isOne() const { return mpq_cmp_si(d_value.get_mpq_t(), 1, 1) == 0; } - bool isNegativeOne() const { + bool isNegativeOne() const + { return mpq_cmp_si(d_value.get_mpq_t(), -1, 1) == 0; } - Rational abs() const { - if(sgn() < 0){ + Rational abs() const + { + if (sgn() < 0) + { return -(*this); - }else{ + } + else + { return *this; } } - Integer floor() const { + Integer floor() const + { mpz_class q; mpz_fdiv_q(q.get_mpz_t(), d_value.get_num_mpz_t(), d_value.get_den_mpz_t()); return Integer(q); } - Integer ceiling() const { + Integer ceiling() const + { mpz_class q; mpz_cdiv_q(q.get_mpz_t(), d_value.get_num_mpz_t(), d_value.get_den_mpz_t()); return Integer(q); } - Rational floor_frac() const { - return (*this) - Rational(floor()); - } + Rational floor_frac() const { return (*this) - Rational(floor()); } - Rational& operator=(const Rational& x){ - if(this == &x) return *this; + Rational& operator=(const Rational& x) + { + if (this == &x) return *this; d_value = x.d_value; return *this; } - Rational operator-() const{ - return Rational(-(d_value)); - } + Rational operator-() const { return Rational(-(d_value)); } - bool operator==(const Rational& y) const { - return d_value == y.d_value; - } + bool operator==(const Rational& y) const { return d_value == y.d_value; } - bool operator!=(const Rational& y) const { - return d_value != y.d_value; - } + bool operator!=(const Rational& y) const { return d_value != y.d_value; } - bool operator< (const Rational& y) const { - return d_value < y.d_value; - } + bool operator<(const Rational& y) const { return d_value < y.d_value; } - bool operator<=(const Rational& y) const { - return d_value <= y.d_value; - } + bool operator<=(const Rational& y) const { return d_value <= y.d_value; } - bool operator> (const Rational& y) const { - return d_value > y.d_value; - } + bool operator>(const Rational& y) const { return d_value > y.d_value; } - bool operator>=(const Rational& y) const { - return d_value >= y.d_value; - } + bool operator>=(const Rational& y) const { return d_value >= y.d_value; } - Rational operator+(const Rational& y) const{ - return Rational( d_value + y.d_value ); + Rational operator+(const Rational& y) const + { + return Rational(d_value + y.d_value); } - Rational operator-(const Rational& y) const { - return Rational( d_value - y.d_value ); + Rational operator-(const Rational& y) const + { + return Rational(d_value - y.d_value); } - Rational operator*(const Rational& y) const { - return Rational( d_value * y.d_value ); + Rational operator*(const Rational& y) const + { + return Rational(d_value * y.d_value); } - Rational operator/(const Rational& y) const { - return Rational( d_value / y.d_value ); + Rational operator/(const Rational& y) const + { + return Rational(d_value / y.d_value); } - Rational& operator+=(const Rational& y){ + Rational& operator+=(const Rational& y) + { d_value += y.d_value; return (*this); } - Rational& operator-=(const Rational& y){ + Rational& operator-=(const Rational& y) + { d_value -= y.d_value; return (*this); } - Rational& operator*=(const Rational& y){ + Rational& operator*=(const Rational& y) + { d_value *= y.d_value; return (*this); } - Rational& operator/=(const Rational& y){ + Rational& operator/=(const Rational& y) + { d_value /= y.d_value; return (*this); } - bool isIntegral() const{ - return getDenominator() == 1; - } + bool isIntegral() const { return getDenominator() == 1; } /** Returns a string representing the rational in the given base. */ - std::string toString(int base = 10) const { - return d_value.get_str(base); - } + std::string toString(int base = 10) const { return d_value.get_str(base); } /** * Computes the hash of the rational from hashes of the numerator and the * denominator. */ - size_t hash() const { + size_t hash() const + { size_t numeratorHash = gmpz_hash(d_value.get_num_mpz_t()); size_t denominatorHash = gmpz_hash(d_value.get_den_mpz_t()); return numeratorHash xor denominatorHash; } - uint32_t complexity() const { + uint32_t complexity() const + { uint32_t numLen = getNumerator().length(); uint32_t denLen = getDenominator().length(); - return numLen + denLen; + return numLen + denLen; } /** Equivalent to calling (this->abs()).cmp(b.abs()) */ int absCmp(const Rational& q) const; -};/* class Rational */ + private: + /** + * Stores the value of the rational is stored in a C++ GMP rational class. + * Using this instead of mpq_t allows for easier destruction. + */ + mpq_class d_value; -struct RationalHashFunction { - inline size_t operator()(const CVC4::Rational& r) const { - return r.hash(); - } -};/* struct RationalHashFunction */ +}; /* class Rational */ + +struct RationalHashFunction +{ + inline size_t operator()(const CVC4::Rational& r) const { return r.hash(); } +}; /* struct RationalHashFunction */ CVC4_PUBLIC std::ostream& operator<<(std::ostream& os, const Rational& n); -}/* CVC4 namespace */ +} // namespace CVC4 #endif /* CVC4__RATIONAL_H */ diff --git a/src/util/regexp.cpp b/src/util/regexp.cpp index 7051b251f..be1459865 100644 --- a/src/util/regexp.cpp +++ b/src/util/regexp.cpp @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/util/regexp.h b/src/util/regexp.h index aaba9e4db..180bb0c32 100644 --- a/src/util/regexp.h +++ b/src/util/regexp.h @@ -4,7 +4,7 @@ ** 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 + ** Copyright (c) 2009-2020 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 diff --git a/src/util/resource_manager.cpp b/src/util/resource_manager.cpp index 2667d8513..eddf9e5c9 100644 --- a/src/util/resource_manager.cpp +++ b/src/util/resource_manager.cpp @@ -2,9 +2,9 @@ /*! \file resource_manager.cpp ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Tim King, Morgan Deters + ** Liana Hadarean, Mathias Preiner, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/resource_manager.h b/src/util/resource_manager.h index 659d455f2..39fceb7ec 100644 --- a/src/util/resource_manager.h +++ b/src/util/resource_manager.h @@ -2,9 +2,9 @@ /*! \file resource_manager.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean, Tim King, Morgan Deters + ** Tim King, Liana Hadarean, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/result.cpp b/src/util/result.cpp index 01d5b052e..0ed063ebc 100644 --- a/src/util/result.cpp +++ b/src/util/result.cpp @@ -2,9 +2,9 @@ /*! \file result.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Andrew Reynolds + ** Tim King, Aina Niemetz, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -374,7 +374,6 @@ void Result::toStreamTptp(std::ostream& out) const { void Result::toStream(std::ostream& out, OutputLanguage language) const { switch (language) { - case language::output::LANG_SYGUS_V1: case language::output::LANG_SYGUS_V2: toStreamSmt2(out); break; case language::output::LANG_TPTP: toStreamTptp(out); diff --git a/src/util/result.h b/src/util/result.h index 10df05388..d9d024b5a 100644 --- a/src/util/result.h +++ b/src/util/result.h @@ -2,9 +2,9 @@ /*! \file result.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Tim King, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/safe_print.cpp b/src/util/safe_print.cpp index beb1a1673..7bc7fed9b 100644 --- a/src/util/safe_print.cpp +++ b/src/util/safe_print.cpp @@ -2,9 +2,9 @@ /*! \file safe_print.cpp ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli, Andres Noetzli + ** Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/safe_print.h b/src/util/safe_print.h index fa9430f2c..4afd08c1a 100644 --- a/src/util/safe_print.h +++ b/src/util/safe_print.h @@ -2,9 +2,9 @@ /*! \file safe_print.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/sampler.cpp b/src/util/sampler.cpp index 60d38bb34..47cc32fb0 100644 --- a/src/util/sampler.cpp +++ b/src/util/sampler.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/sampler.h b/src/util/sampler.h index aa473ba0c..688c83f1b 100644 --- a/src/util/sampler.h +++ b/src/util/sampler.h @@ -2,9 +2,9 @@ /*! \file sampler.h ** \verbatim ** Top contributors (to current version): - ** Andres Noetzli + ** Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/sexpr.cpp b/src/util/sexpr.cpp index 24ec700bc..6f2da480e 100644 --- a/src/util/sexpr.cpp +++ b/src/util/sexpr.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 @@ -272,7 +272,6 @@ void SExpr::toStreamRec(std::ostream& out, const SExpr& sexpr, bool SExpr::languageQuotesKeywords(OutputLanguage language) { switch (language) { - case language::output::LANG_SYGUS_V1: case language::output::LANG_TPTP: return true; case language::output::LANG_AST: diff --git a/src/util/sexpr.h b/src/util/sexpr.h index bdc85df41..73e25026a 100644 --- a/src/util/sexpr.h +++ b/src/util/sexpr.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Tim King, Morgan Deters, Christopher L. Conway ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/smt2_quote_string.cpp b/src/util/smt2_quote_string.cpp index 8d1d4b987..3dc41407a 100644 --- a/src/util/smt2_quote_string.cpp +++ b/src/util/smt2_quote_string.cpp @@ -2,9 +2,9 @@ /*! \file smt2_quote_string.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Morgan Deters, Kshitij Bansal + ** Tim King, Andres Noetzli, Morgan Deters ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/smt2_quote_string.h b/src/util/smt2_quote_string.h index f91874a2e..fb8332063 100644 --- a/src/util/smt2_quote_string.h +++ b/src/util/smt2_quote_string.h @@ -2,9 +2,9 @@ /*! \file smt2_quote_string.h ** \verbatim ** Top contributors (to current version): - ** Tim King + ** Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/statistics.cpp b/src/util/statistics.cpp index c61520df9..0344bb5b1 100644 --- a/src/util/statistics.cpp +++ b/src/util/statistics.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andres Noetzli, Tim King ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/statistics.h b/src/util/statistics.h index 68d8d6fda..e77b48090 100644 --- a/src/util/statistics.h +++ b/src/util/statistics.h @@ -2,9 +2,9 @@ /*! \file statistics.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Andres Noetzli, Tim King + ** Morgan Deters, Andres Noetzli, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/statistics.i b/src/util/statistics.i index 8d1086dcc..7dfc7ec39 100644 --- a/src/util/statistics.i +++ b/src/util/statistics.i @@ -64,12 +64,12 @@ %include <std_pair.i> %include <std_string.i> -%include <std_vector.i> -%include "bindings/java_iterator_adapter.h" %include "util/sexpr.h" %template(Statistic) std::pair<std::string, CVC4::SExpr>; + +%feature("valuewrapper") CVC4::JavaIteratorAdapter<CVC4::StatisticsBase, std::pair<std::string, CVC4::SExpr> >; %template(JavaIteratorAdapter_StatisticsBase) CVC4::JavaIteratorAdapter<CVC4::StatisticsBase, std::pair<std::string, CVC4::SExpr> >; #endif /* SWIGJAVA */ diff --git a/src/util/statistics_registry.cpp b/src/util/statistics_registry.cpp index ee7d1bb87..81eaa3559 100644 --- a/src/util/statistics_registry.cpp +++ b/src/util/statistics_registry.cpp @@ -2,9 +2,9 @@ /*! \file statistics_registry.cpp ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King, Kshitij Bansal + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/statistics_registry.h b/src/util/statistics_registry.h index 4d4cc76df..69f6105cd 100644 --- a/src/util/statistics_registry.h +++ b/src/util/statistics_registry.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/string.cpp b/src/util/string.cpp index ff522ba7b..abe3b01e7 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -2,9 +2,9 @@ /*! \file string.cpp ** \verbatim ** Top contributors (to current version): - ** Tim King, Tianyi Liang, Andrew Reynolds + ** Andrew Reynolds, Tim King, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/string.h b/src/util/string.h index 637ffe365..700291aeb 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andrew Reynolds, Tim King, Tianyi Liang ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/tuple.h b/src/util/tuple.h index 13b605794..ff5dd18b3 100644 --- a/src/util/tuple.h +++ b/src/util/tuple.h @@ -2,9 +2,9 @@ /*! \file tuple.h ** \verbatim ** Top contributors (to current version): - ** Morgan Deters, Tim King + ** Morgan Deters, Tim King, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/unsafe_interrupt_exception.h b/src/util/unsafe_interrupt_exception.h index 5c8360cdf..0cd390cdd 100644 --- a/src/util/unsafe_interrupt_exception.h +++ b/src/util/unsafe_interrupt_exception.h @@ -2,9 +2,9 @@ /*! \file unsafe_interrupt_exception.h ** \verbatim ** Top contributors (to current version): - ** Liana Hadarean + ** Liana Hadarean, Mathias Preiner ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/utility.cpp b/src/util/utility.cpp index acabd8739..b1b86a38b 100644 --- a/src/util/utility.cpp +++ b/src/util/utility.cpp @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Andres Noetzli ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 diff --git a/src/util/utility.h b/src/util/utility.h index 4477fc7b2..86dd64df9 100644 --- a/src/util/utility.h +++ b/src/util/utility.h @@ -4,7 +4,7 @@ ** Top contributors (to current version): ** Morgan Deters, Andres Noetzli, Aina Niemetz ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS + ** Copyright (c) 2009-2020 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 |