summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Noetzli <andres.noetzli@gmail.com>2019-01-14 17:02:53 -0800
committerAndres Noetzli <andres.noetzli@gmail.com>2019-01-14 17:02:53 -0800
commitc8664731adc61ab3967b74fe90ad44fb464dc556 (patch)
tree495766d37af08f4f587ed18ac224deaae5402b1b
parent2771dce1fe1933537f80d68966642ecf3bf95f77 (diff)
parent8d9c190ccf806460bfc336daee33ed56f151e563 (diff)
Merge remote-tracking branch 'fork/loopProcessOpts' into cav2019strings
-rw-r--r--CMakeLists.txt16
-rw-r--r--cmake/FindDrat2Er.cmake12
-rw-r--r--examples/api/combination-new.cpp4
-rw-r--r--examples/api/datatypes-new.cpp4
-rw-r--r--examples/api/linear_arith-new.cpp4
-rw-r--r--examples/api/sets-new.cpp6
-rw-r--r--examples/api/strings-new.cpp2
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/api/cvc4cpp.cpp1032
-rw-r--r--src/api/cvc4cpp.h429
-rw-r--r--src/api/cvc4cppkind.h43
-rw-r--r--src/options/CMakeLists.txt2
-rw-r--r--src/options/bv_bitblast_mode.cpp13
-rw-r--r--src/options/bv_bitblast_mode.h21
-rw-r--r--src/options/bv_options.toml11
-rw-r--r--src/options/options_handler.cpp97
-rw-r--r--src/options/options_handler.h9
-rw-r--r--src/options/strings_options.toml24
-rw-r--r--src/options/strings_process_loop_mode.cpp46
-rw-r--r--src/options/strings_process_loop_mode.h55
-rw-r--r--src/parser/parser.cpp2
-rw-r--r--src/parser/parser.h3
-rw-r--r--src/parser/smt2/Smt2.g228
-rw-r--r--src/printer/cvc/cvc_printer.cpp1
-rw-r--r--src/proof/arith_proof.cpp577
-rw-r--r--src/proof/arith_proof.h72
-rw-r--r--src/proof/arith_proof_recorder.cpp14
-rw-r--r--src/proof/bitvector_proof.cpp14
-rw-r--r--src/proof/bitvector_proof.h72
-rw-r--r--src/proof/clausal_bitvector_proof.cpp115
-rw-r--r--src/proof/clausal_bitvector_proof.h97
-rw-r--r--src/proof/cnf_proof.cpp24
-rw-r--r--src/proof/cnf_proof.h13
-rw-r--r--src/proof/drat/drat_proof.cpp287
-rw-r--r--src/proof/drat/drat_proof.h140
-rw-r--r--src/proof/lfsc_proof_printer.cpp41
-rw-r--r--src/proof/lfsc_proof_printer.h49
-rw-r--r--src/proof/lrat/lrat_proof.cpp385
-rw-r--r--src/proof/lrat/lrat_proof.h182
-rw-r--r--src/proof/resolution_bitvector_proof.cpp69
-rw-r--r--src/proof/resolution_bitvector_proof.h58
-rw-r--r--src/proof/theory_proof.cpp32
-rw-r--r--src/prop/bvminisat/bvminisat.cpp3
-rw-r--r--src/prop/bvminisat/bvminisat.h2
-rw-r--r--src/prop/cnf_stream.cpp21
-rw-r--r--src/prop/cryptominisat.cpp29
-rw-r--r--src/prop/cryptominisat.h3
-rw-r--r--src/prop/sat_solver.h10
-rw-r--r--src/smt/smt_engine.h12
-rw-r--r--src/theory/arith/constraint.cpp47
-rw-r--r--src/theory/arith/constraint.h424
-rw-r--r--src/theory/arith/kinds1
-rw-r--r--src/theory/arith/theory_arith_private.cpp65
-rw-r--r--src/theory/arith/theory_arith_type_rules.h12
-rw-r--r--src/theory/bv/bitblast/bitblaster.h31
-rw-r--r--src/theory/bv/bitblast/eager_bitblaster.cpp10
-rw-r--r--src/theory/bv/bitblast/eager_bitblaster.h7
-rw-r--r--src/theory/bv/bitblast/lazy_bitblaster.cpp11
-rw-r--r--src/theory/bv/bitblast/lazy_bitblaster.h7
-rw-r--r--src/theory/bv/bv_eager_solver.cpp5
-rw-r--r--src/theory/bv/bv_eager_solver.h4
-rw-r--r--src/theory/bv/bv_subtheory.h4
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.cpp2
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.h2
-rw-r--r--src/theory/bv/kinds151
-rw-r--r--src/theory/bv/theory_bv.cpp4
-rw-r--r--src/theory/bv/theory_bv.h10
-rw-r--r--src/theory/bv/theory_bv_type_rules.h531
-rw-r--r--src/theory/datatypes/datatypes_rewriter.cpp2
-rw-r--r--src/theory/datatypes/kinds2
-rw-r--r--src/theory/datatypes/theory_datatypes_type_rules.h24
-rw-r--r--src/theory/fp/theory_fp_rewriter.cpp16
-rw-r--r--src/theory/strings/theory_strings.cpp65
-rw-r--r--src/theory/strings/theory_strings.h28
-rw-r--r--test/regress/CMakeLists.txt2
-rw-r--r--test/regress/regress1/sygus/temp_input_to_synth_ic-error-121418.sy26
-rw-r--r--test/regress/regress2/sygus/min_IC_1.sy25
-rw-r--r--test/unit/CMakeLists.txt1
-rw-r--r--test/unit/api/CMakeLists.txt3
-rw-r--r--test/unit/api/datatype_api_black.h57
-rw-r--r--test/unit/api/solver_black.h813
-rw-r--r--test/unit/api/term_black.h18
-rw-r--r--test/unit/proof/CMakeLists.txt6
-rw-r--r--test/unit/proof/drat_proof_black.h187
-rw-r--r--test/unit/proof/lfsc_proof_printer_black.h118
-rw-r--r--test/unit/proof/lrat_proof_black.h113
86 files changed, 5589 insertions, 1636 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3265830cc..33e06840e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -212,15 +212,6 @@ if(NOT ENABLE_ASSERTIONS)
set(ENABLE_UNIT_TESTING OFF)
endif()
-# Never build unit tests as static binaries, otherwise we'll end up with
-# ~300MB per unit test.
-if(ENABLE_UNIT_TESTING)
- if(NOT ENABLE_SHARED)
- message(WARNING "Disabling static build since unit testing is enabled.")
- endif()
- set(ENABLE_SHARED ON)
-endif()
-
#-----------------------------------------------------------------------------#
# Shared/static libraries
#
@@ -239,6 +230,13 @@ else()
# This is required to force find_package(Boost) to use static libraries.
set(Boost_USE_STATIC_LIBS ON)
cvc4_set_option(ENABLE_STATIC_BINARY ON)
+
+ # Never build unit tests as static binaries, otherwise we'll end up with
+ # ~300MB per unit test.
+ if(ENABLE_UNIT_TESTING)
+ message(WARNING "Disabling unit tests since static build is enabled.")
+ set(ENABLE_UNIT_TESTING OFF)
+ endif()
endif()
#-----------------------------------------------------------------------------#
diff --git a/cmake/FindDrat2Er.cmake b/cmake/FindDrat2Er.cmake
index e0bc8d446..a7c2538a5 100644
--- a/cmake/FindDrat2Er.cmake
+++ b/cmake/FindDrat2Er.cmake
@@ -19,13 +19,21 @@ find_library(Drat2Er_LIBRARIES
NAMES libdrat2er.a
PATHS ${Drat2Er_HOME}/lib
NO_DEFAULT_PATH)
+find_library(DratTrim_LIBRARIES
+ NAMES libdrat-trim.a
+ PATHS ${Drat2Er_HOME}/lib
+ NO_DEFAULT_PATH)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Drat2Er
DEFAULT_MSG
- Drat2Er_INCLUDE_DIR Drat2Er_LIBRARIES)
+ Drat2Er_INCLUDE_DIR Drat2Er_LIBRARIES DratTrim_LIBRARIES)
-mark_as_advanced(Drat2Er_INCLUDE_DIR Drat2Er_LIBRARIES)
+mark_as_advanced(Drat2Er_INCLUDE_DIR Drat2Er_LIBRARIES DratTrim_LIBRARIES)
if(Drat2Er_LIBRARIES)
message(STATUS "Found Drat2Er libs: ${Drat2Er_LIBRARIES}")
endif()
+if(DratTrim_LIBRARIES)
+ message(STATUS "Found DratTrim libs: ${DratTrim_LIBRARIES}")
+ list(APPEND Drat2Er_LIBRARIES ${DratTrim_LIBRARIES})
+endif()
diff --git a/examples/api/combination-new.cpp b/examples/api/combination-new.cpp
index 2956d76e6..8c968c95e 100644
--- a/examples/api/combination-new.cpp
+++ b/examples/api/combination-new.cpp
@@ -59,8 +59,8 @@ int main()
Term p = slv.mkVar("p", intPred);
// Constants
- Term zero = slv.mkInteger(0);
- Term one = slv.mkInteger(1);
+ Term zero = slv.mkReal(0);
+ Term one = slv.mkReal(1);
// Terms
Term f_x = slv.mkTerm(APPLY_UF, f, x);
diff --git a/examples/api/datatypes-new.cpp b/examples/api/datatypes-new.cpp
index b6a816db4..48560e894 100644
--- a/examples/api/datatypes-new.cpp
+++ b/examples/api/datatypes-new.cpp
@@ -39,7 +39,7 @@ void test(Solver& slv, Sort& consListSort)
Term t = slv.mkTerm(
APPLY_CONSTRUCTOR,
consList.getConstructorTerm("cons"),
- slv.mkInteger(0),
+ slv.mkReal(0),
slv.mkTerm(APPLY_CONSTRUCTOR, consList.getConstructorTerm("nil")));
std::cout << "t is " << t << std::endl
@@ -127,7 +127,7 @@ void test(Solver& slv, Sort& consListSort)
<< "sort of cons is "
<< paramConsList.getConstructorTerm("cons").getSort() << std::endl
<< std::endl;
- Term assertion = slv.mkTerm(GT, head_a, slv.mkInteger(50));
+ Term assertion = slv.mkTerm(GT, head_a, slv.mkReal(50));
std::cout << "Assert " << assertion << std::endl;
slv.assertFormula(assertion);
std::cout << "Expect sat." << std::endl;
diff --git a/examples/api/linear_arith-new.cpp b/examples/api/linear_arith-new.cpp
index ef8faade9..d643b85bc 100644
--- a/examples/api/linear_arith-new.cpp
+++ b/examples/api/linear_arith-new.cpp
@@ -40,8 +40,8 @@ int main()
Term y = slv.mkVar("y", real);
// Constants
- Term three = slv.mkInteger(3);
- Term neg2 = slv.mkInteger(-2);
+ Term three = slv.mkReal(3);
+ Term neg2 = slv.mkReal(-2);
Term two_thirds = slv.mkReal(2, 3);
// Terms
diff --git a/examples/api/sets-new.cpp b/examples/api/sets-new.cpp
index be35bcc21..2dcfbbc02 100644
--- a/examples/api/sets-new.cpp
+++ b/examples/api/sets-new.cpp
@@ -70,9 +70,9 @@ int main()
// Find me an element in {1, 2} intersection {2, 3}, if there is one.
{
- Term one = slv.mkInteger(1);
- Term two = slv.mkInteger(2);
- Term three = slv.mkInteger(3);
+ Term one = slv.mkReal(1);
+ Term two = slv.mkReal(2);
+ Term three = slv.mkReal(3);
Term singleton_one = slv.mkTerm(SINGLETON, one);
Term singleton_two = slv.mkTerm(SINGLETON, two);
diff --git a/examples/api/strings-new.cpp b/examples/api/strings-new.cpp
index 2010c6909..c88ccc9c0 100644
--- a/examples/api/strings-new.cpp
+++ b/examples/api/strings-new.cpp
@@ -57,7 +57,7 @@ int main()
// Length of y: |y|
Term leny = slv.mkTerm(STRING_LENGTH, y);
// |y| >= 0
- Term formula2 = slv.mkTerm(GEQ, leny, slv.mkInteger(0));
+ Term formula2 = slv.mkTerm(GEQ, leny, slv.mkReal(0));
// Regular expression: (ab[c-e]*f)|g|h
Term r = slv.mkTerm(REGEXP_UNION,
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 889260045..d9fc80a92 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -130,13 +130,19 @@ libcvc4_add_sources(
proof/array_proof.h
proof/bitvector_proof.cpp
proof/bitvector_proof.h
+ proof/clausal_bitvector_proof.cpp
+ proof/clausal_bitvector_proof.h
proof/clause_id.h
proof/cnf_proof.cpp
proof/cnf_proof.h
+ proof/drat/drat_proof.cpp
+ proof/drat/drat_proof.h
proof/lemma_proof.cpp
proof/lemma_proof.h
proof/lfsc_proof_printer.cpp
proof/lfsc_proof_printer.h
+ proof/lrat/lrat_proof.cpp
+ proof/lrat/lrat_proof.h
proof/proof.h
proof/proof_manager.cpp
proof/proof_manager.h
diff --git a/src/api/cvc4cpp.cpp b/src/api/cvc4cpp.cpp
index cd604a25c..123613797 100644
--- a/src/api/cvc4cpp.cpp
+++ b/src/api/cvc4cpp.cpp
@@ -16,6 +16,7 @@
#include "api/cvc4cpp.h"
+#include "base/configuration.h"
#include "base/cvc4_assert.h"
#include "base/cvc4_check.h"
#include "expr/expr.h"
@@ -28,10 +29,12 @@
#include "options/options.h"
#include "smt/model.h"
#include "smt/smt_engine.h"
+#include "theory/logic_info.h"
#include "util/random.h"
#include "util/result.h"
#include "util/utility.h"
+#include <cstring>
#include <sstream>
namespace CVC4 {
@@ -639,6 +642,10 @@ class CVC4ApiExceptionStream
CVC4_API_CHECK(!isNull()) << "Invalid call to '" << __PRETTY_FUNCTION__ \
<< "', expected non-null object";
+#define CVC4_API_ARG_CHECK_NOT_NULL(arg) \
+ CVC4_API_CHECK(arg != nullptr) \
+ << "Invalid null argument for '" << #arg << "'";
+
#define CVC4_API_KIND_CHECK(kind) \
CVC4_API_CHECK(isDefinedKind(kind)) \
<< "Invalid kind '" << kindToString(kind) << "'";
@@ -665,12 +672,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_FALSE(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_FALSE(cond) \
+ ? (void)0 \
+ : OstreamVoider() \
+ & CVC4ApiExceptionStream().ostream() \
+ << "Invalid " << what << " '" << arg << "' at index" << idx \
<< ", expected "
} // namespace
@@ -751,12 +758,16 @@ std::ostream& operator<<(std::ostream& out, const Result& r)
Sort::Sort(const CVC4::Type& t) : d_type(new CVC4::Type(t)) {}
+Sort::Sort() : d_type(new CVC4::Type()) {}
+
Sort::~Sort() {}
bool Sort::operator==(const Sort& s) const { return *d_type == *s.d_type; }
bool Sort::operator!=(const Sort& s) const { return *d_type != *s.d_type; }
+bool Sort::isNull() const { return d_type->isNull(); }
+
bool Sort::isBoolean() const { return d_type->isBoolean(); }
bool Sort::isInteger() const { return d_type->isInteger(); }
@@ -1025,9 +1036,11 @@ Term Term::notTerm() const
{
try
{
- return d_expr->notExpr();
+ Term res = d_expr->notExpr();
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
}
- catch (TypeCheckingException& e)
+ catch (const CVC4::TypeCheckingException& e)
{
throw CVC4ApiException(e.getMessage());
}
@@ -1037,9 +1050,11 @@ Term Term::andTerm(const Term& t) const
{
try
{
- return d_expr->andExpr(*t.d_expr);
+ Term res = d_expr->andExpr(*t.d_expr);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
}
- catch (TypeCheckingException& e)
+ catch (const CVC4::TypeCheckingException& e)
{
throw CVC4ApiException(e.getMessage());
}
@@ -1049,9 +1064,11 @@ Term Term::orTerm(const Term& t) const
{
try
{
- return d_expr->orExpr(*t.d_expr);
+ Term res = d_expr->orExpr(*t.d_expr);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
}
- catch (TypeCheckingException& e)
+ catch (const CVC4::TypeCheckingException& e)
{
throw CVC4ApiException(e.getMessage());
}
@@ -1061,9 +1078,11 @@ Term Term::xorTerm(const Term& t) const
{
try
{
- return d_expr->xorExpr(*t.d_expr);
+ Term res = d_expr->xorExpr(*t.d_expr);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
}
- catch (TypeCheckingException& e)
+ catch (const CVC4::TypeCheckingException& e)
{
throw CVC4ApiException(e.getMessage());
}
@@ -1073,9 +1092,11 @@ Term Term::eqTerm(const Term& t) const
{
try
{
- return d_expr->eqExpr(*t.d_expr);
+ Term res = d_expr->eqExpr(*t.d_expr);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
}
- catch (TypeCheckingException& e)
+ catch (const CVC4::TypeCheckingException& e)
{
throw CVC4ApiException(e.getMessage());
}
@@ -1085,9 +1106,11 @@ Term Term::impTerm(const Term& t) const
{
try
{
- return d_expr->impExpr(*t.d_expr);
+ Term res = d_expr->impExpr(*t.d_expr);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
}
- catch (TypeCheckingException& e)
+ catch (const CVC4::TypeCheckingException& e)
{
throw CVC4ApiException(e.getMessage());
}
@@ -1097,9 +1120,11 @@ Term Term::iteTerm(const Term& then_t, const Term& else_t) const
{
try
{
- return d_expr->iteExpr(*then_t.d_expr, *else_t.d_expr);
+ 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;
}
- catch (TypeCheckingException& e)
+ catch (const CVC4::TypeCheckingException& e)
{
throw CVC4ApiException(e.getMessage());
}
@@ -1451,6 +1476,14 @@ DatatypeConstructor::DatatypeConstructor(const CVC4::DatatypeConstructor& ctor)
DatatypeConstructor::~DatatypeConstructor() {}
+bool DatatypeConstructor::isResolved() const { return d_ctor->isResolved(); }
+
+Term DatatypeConstructor::getConstructorTerm() const
+{
+ CVC4_API_CHECK(isResolved()) << "Expected resolved datatype constructor.";
+ return Term(d_ctor->getConstructor());
+}
+
DatatypeSelector DatatypeConstructor::operator[](const std::string& name) const
{
// CHECK: selector with name exists?
@@ -1573,6 +1606,13 @@ Datatype::Datatype(const CVC4::Datatype& dtype)
Datatype::~Datatype() {}
+DatatypeConstructor Datatype::operator[](size_t idx) const
+{
+ // CHECK (maybe): is resolved?
+ CVC4_API_CHECK(idx < getNumConstructors()) << "Index out of bounds.";
+ return (*d_dtype)[idx];
+}
+
DatatypeConstructor Datatype::operator[](const std::string& name) const
{
// CHECK: cons with name exists?
@@ -1725,6 +1765,8 @@ Solver::~Solver() {}
/* Sorts Handling */
/* -------------------------------------------------------------------------- */
+Sort Solver::getNullSort(void) const { return Type(); }
+
Sort Solver::getBooleanSort(void) const { return d_exprMgr->booleanType(); }
Sort Solver::getIntegerSort(void) const { return d_exprMgr->integerType(); }
@@ -1744,6 +1786,10 @@ Sort Solver::getRoundingmodeSort(void) const
Sort Solver::mkArraySort(Sort indexSort, Sort elemSort) const
{
+ CVC4_API_ARG_CHECK_EXPECTED(!indexSort.isNull(), indexSort)
+ << "non-null index sort";
+ CVC4_API_ARG_CHECK_EXPECTED(!elemSort.isNull(), elemSort)
+ << "non-null element sort";
return d_exprMgr->mkArrayType(*indexSort.d_type, *elemSort.d_type);
}
@@ -1769,6 +1815,8 @@ Sort Solver::mkDatatypeSort(DatatypeDecl dtypedecl) const
Sort Solver::mkFunctionSort(Sort domain, Sort codomain) const
{
+ CVC4_API_ARG_CHECK_EXPECTED(!codomain.isNull(), codomain)
+ << "non-null codomain sort";
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)
@@ -1784,9 +1832,14 @@ Sort Solver::mkFunctionSort(const std::vector<Sort>& sorts, Sort codomain) const
for (size_t i = 0, size = sorts.size(); i < size; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ !sorts[i].isNull(), "parameter sort", sorts[i], i)
+ << "non-null sort";
+ 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_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. */
@@ -1806,6 +1859,9 @@ Sort Solver::mkPredicateSort(const std::vector<Sort>& sorts) const
for (size_t i = 0, size = sorts.size(); i < size; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ !sorts[i].isNull(), "parameter sort", sorts[i], i)
+ << "non-null sort";
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
sorts[i].isFirstClass(), "parameter sort", sorts[i], i)
<< "first-class sort as parameter sort for predicate sort";
}
@@ -1817,8 +1873,13 @@ Sort Solver::mkRecordSort(
const std::vector<std::pair<std::string, Sort>>& fields) const
{
std::vector<std::pair<std::string, Type>> f;
+ size_t i = 0;
for (const auto& p : fields)
{
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ !p.second.isNull(), "parameter sort", p.second, i)
+ << "non-null sort";
+ i += 1;
f.emplace_back(p.first, *p.second.d_type);
}
return d_exprMgr->mkRecordType(Record(f));
@@ -1826,6 +1887,8 @@ Sort Solver::mkRecordSort(
Sort Solver::mkSetSort(Sort elemSort) const
{
+ CVC4_API_ARG_CHECK_EXPECTED(!elemSort.isNull(), elemSort)
+ << "non-null element sort";
return d_exprMgr->mkSetType(*elemSort.d_type);
}
@@ -1846,6 +1909,9 @@ Sort Solver::mkTupleSort(const std::vector<Sort>& sorts) const
for (size_t i = 0, size = sorts.size(); i < size; ++i)
{
CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ !sorts[i].isNull(), "parameter sort", sorts[i], i)
+ << "non-null sort";
+ 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";
}
@@ -1873,328 +1939,439 @@ Term Solver::mkFalse(void) const { return d_exprMgr->mkConst<bool>(false); }
Term Solver::mkBoolean(bool val) const { return d_exprMgr->mkConst<bool>(val); }
-Term Solver::mkInteger(const char* s, uint32_t base) const
-{
- return d_exprMgr->mkConst(Rational(s, base));
-}
-
-Term Solver::mkInteger(const std::string& s, uint32_t base) const
-{
- return d_exprMgr->mkConst(Rational(s, base));
-}
-
-Term Solver::mkInteger(int32_t val) const
-{
- return d_exprMgr->mkConst(Rational(val));
-}
-
-Term Solver::mkInteger(uint32_t val) const
-{
- return d_exprMgr->mkConst(Rational(val));
-}
-
-Term Solver::mkInteger(int64_t val) const
+Term Solver::mkPi() const
{
- return d_exprMgr->mkConst(Rational(val));
+ try
+ {
+ Term res =
+ d_exprMgr->mkNullaryOperator(d_exprMgr->realType(), CVC4::kind::PI);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
-Term Solver::mkInteger(uint64_t val) const
+template <typename T>
+Term Solver::mkConstHelper(T t) const
{
- return d_exprMgr->mkConst(Rational(val));
+ try
+ {
+ Term res = d_exprMgr->mkConst(t);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
-Term Solver::mkPi() const
+/* Split out to avoid nested API calls (problematic with API tracing). */
+Term Solver::mkRealFromStrHelper(std::string s) const
{
- return d_exprMgr->mkNullaryOperator(d_exprMgr->realType(), CVC4::kind::PI);
+ /* CLN and GMP handle this case differently, CLN interprets it as 0, GMP
+ * throws an std::invalid_argument exception. For consistency, we treat it
+ * as invalid. */
+ CVC4_API_ARG_CHECK_EXPECTED(s != ".", s)
+ << "a string representing an integer, real or rational value.";
+ try
+ {
+ CVC4::Rational r = s.find('/') != std::string::npos
+ ? CVC4::Rational(s)
+ : CVC4::Rational::fromDecimal(s);
+ return mkConstHelper<CVC4::Rational>(r);
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
-Term Solver::mkReal(const char* s, uint32_t base) const
+Term Solver::mkReal(const char* s) const
{
- return d_exprMgr->mkConst(Rational(s, base));
+ CVC4_API_ARG_CHECK_NOT_NULL(s);
+ return mkRealFromStrHelper(std::string(s));
}
-Term Solver::mkReal(const std::string& s, uint32_t base) const
+Term Solver::mkReal(const std::string& s) const
{
- return d_exprMgr->mkConst(Rational(s, base));
+ return mkRealFromStrHelper(s);
}
Term Solver::mkReal(int32_t val) const
{
- return d_exprMgr->mkConst(Rational(val));
+ try
+ {
+ return mkConstHelper<CVC4::Rational>(CVC4::Rational(val));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
Term Solver::mkReal(int64_t val) const
{
- return d_exprMgr->mkConst(Rational(val));
+ try
+ {
+ return mkConstHelper<CVC4::Rational>(CVC4::Rational(val));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
Term Solver::mkReal(uint32_t val) const
{
- return d_exprMgr->mkConst(Rational(val));
+ try
+ {
+ return mkConstHelper<CVC4::Rational>(CVC4::Rational(val));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
Term Solver::mkReal(uint64_t val) const
{
- return d_exprMgr->mkConst(Rational(val));
+ try
+ {
+ return mkConstHelper<CVC4::Rational>(CVC4::Rational(val));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
Term Solver::mkReal(int32_t num, int32_t den) const
{
- return d_exprMgr->mkConst(Rational(num, den));
+ try
+ {
+ return mkConstHelper<CVC4::Rational>(CVC4::Rational(num, den));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
Term Solver::mkReal(int64_t num, int64_t den) const
{
- return d_exprMgr->mkConst(Rational(num, den));
+ try
+ {
+ return mkConstHelper<CVC4::Rational>(CVC4::Rational(num, den));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
Term Solver::mkReal(uint32_t num, uint32_t den) const
{
- return d_exprMgr->mkConst(Rational(num, den));
+ try
+ {
+ return mkConstHelper<CVC4::Rational>(CVC4::Rational(num, den));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
Term Solver::mkReal(uint64_t num, uint64_t den) const
{
- return d_exprMgr->mkConst(Rational(num, den));
+ try
+ {
+ return mkConstHelper<CVC4::Rational>(CVC4::Rational(num, den));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
Term Solver::mkRegexpEmpty() const
{
- return d_exprMgr->mkExpr(CVC4::kind::REGEXP_EMPTY, std::vector<Expr>());
+ try
+ {
+ Term res =
+ d_exprMgr->mkExpr(CVC4::kind::REGEXP_EMPTY, std::vector<CVC4::Expr>());
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkRegexpSigma() const
{
- return d_exprMgr->mkExpr(CVC4::kind::REGEXP_SIGMA, std::vector<Expr>());
+ try
+ {
+ Term res =
+ d_exprMgr->mkExpr(CVC4::kind::REGEXP_SIGMA, std::vector<CVC4::Expr>());
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkEmptySet(Sort s) const
{
- return d_exprMgr->mkConst(EmptySet(*s.d_type));
+ CVC4_API_ARG_CHECK_EXPECTED(s.isNull() || s.isSet(), s)
+ << "null sort or set sort";
+ return mkConstHelper<CVC4::EmptySet>(CVC4::EmptySet(*s.d_type));
}
Term Solver::mkSepNil(Sort sort) const
{
- return d_exprMgr->mkNullaryOperator(*sort.d_type, CVC4::kind::SEP_NIL);
+ try
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null 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;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
-Term Solver::mkString(const char* s) const
+Term Solver::mkString(const char* s, bool useEscSequences) const
{
- return d_exprMgr->mkConst(String(s));
+ return mkConstHelper<CVC4::String>(CVC4::String(s, useEscSequences));
}
-Term Solver::mkString(const std::string& s) const
+Term Solver::mkString(const std::string& s, bool useEscSequences) const
{
- return d_exprMgr->mkConst(String(s));
+ return mkConstHelper<CVC4::String>(CVC4::String(s, useEscSequences));
}
Term Solver::mkString(const unsigned char c) const
{
- return d_exprMgr->mkConst(String(std::string(1, c)));
+ return mkConstHelper<CVC4::String>(CVC4::String(std::string(1, c)));
}
Term Solver::mkString(const std::vector<unsigned>& s) const
{
- return d_exprMgr->mkConst(String(s));
+ return mkConstHelper<CVC4::String>(CVC4::String(s));
}
Term Solver::mkUniverseSet(Sort sort) const
{
- return d_exprMgr->mkNullaryOperator(*sort.d_type, CVC4::kind::UNIVERSE_SET);
+ try
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ Term 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;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
-Term Solver::mkBitVector(uint32_t size) const
+/* Split out to avoid nested API calls (problematic with API tracing). */
+Term Solver::mkBVFromIntHelper(uint32_t size, uint64_t val) const
{
- return d_exprMgr->mkConst(BitVector(size));
+ CVC4_API_ARG_CHECK_EXPECTED(size > 0, size) << "a bit-width > 0";
+ try
+ {
+ return mkConstHelper<CVC4::BitVector>(CVC4::BitVector(size, val));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
-Term Solver::mkBitVector(uint32_t size, uint32_t val) const
+Term Solver::mkBitVector(uint32_t size, uint64_t val) const
{
- return d_exprMgr->mkConst(BitVector(size, val));
+ return mkBVFromIntHelper(size, val);
}
-Term Solver::mkBitVector(uint32_t size, uint64_t val) const
+/* Split out to avoid nested API calls (problematic with API tracing). */
+Term Solver::mkBVFromStrHelper(std::string s, uint32_t base) const
{
- return d_exprMgr->mkConst(BitVector(size, val));
+ CVC4_API_ARG_CHECK_EXPECTED(!s.empty(), s) << "a non-empty string";
+ CVC4_API_ARG_CHECK_EXPECTED(base == 2 || base == 10 || base == 16, s)
+ << "base 2, 10, or 16";
+ try
+ {
+ return mkConstHelper<CVC4::BitVector>(CVC4::BitVector(s, base));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
+}
+
+Term Solver::mkBVFromStrHelper(uint32_t size,
+ std::string s,
+ uint32_t base) const
+{
+ CVC4_API_ARG_CHECK_EXPECTED(!s.empty(), s) << "a non-empty string";
+ CVC4_API_ARG_CHECK_EXPECTED(base == 2 || base == 10 || base == 16, s)
+ << "base 2, 10, or 16";
+ try
+ {
+ Integer val(s, base);
+ CVC4_API_CHECK(val.modByPow2(size) == val)
+ << "Overflow in bitvector construction (specified bitvector size "
+ << size << " too small to hold value " << s << ")";
+ return mkConstHelper<CVC4::BitVector>(CVC4::BitVector(size, val));
+ }
+ catch (const std::invalid_argument& e)
+ {
+ throw CVC4ApiException(e.what());
+ }
}
Term Solver::mkBitVector(const char* s, uint32_t base) const
{
- return d_exprMgr->mkConst(BitVector(s, base));
+ CVC4_API_ARG_CHECK_NOT_NULL(s);
+ return mkBVFromStrHelper(std::string(s), base);
}
-Term Solver::mkBitVector(std::string& s, uint32_t base) const
+Term Solver::mkBitVector(const std::string& s, uint32_t base) const
{
- return d_exprMgr->mkConst(BitVector(s, base));
+ return mkBVFromStrHelper(s, base);
}
-Term Solver::mkConst(RoundingMode rm) const
+Term Solver::mkBitVector(uint32_t size, const char* s, uint32_t base) const
{
- return d_exprMgr->mkConst(s_rmodes.at(rm));
+ CVC4_API_ARG_CHECK_NOT_NULL(s);
+ return mkBVFromStrHelper(size, s, base);
}
-Term Solver::mkConst(Kind kind, Sort arg) const
+Term Solver::mkBitVector(uint32_t size, std::string& s, uint32_t base) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == EMPTYSET, kind) << "EMPTY_SET";
- return d_exprMgr->mkConst(CVC4::EmptySet(*arg.d_type));
+ return mkBVFromStrHelper(size, s, base);
}
-Term Solver::mkConst(Kind kind, Sort arg1, int32_t arg2) const
+Term Solver::mkPosInf(uint32_t exp, uint32_t sig) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == UNINTERPRETED_CONSTANT, kind)
- << "UNINTERPRETED_CONSTANT";
- return d_exprMgr->mkConst(CVC4::UninterpretedConstant(*arg1.d_type, arg2));
+ CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
+ << "Expected CVC4 to be compiled with SymFPU support";
+ return mkConstHelper<CVC4::FloatingPoint>(
+ FloatingPoint::makeInf(FloatingPointSize(exp, sig), false));
}
-Term Solver::mkConst(Kind kind, bool arg) const
+Term Solver::mkNegInf(uint32_t exp, uint32_t sig) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == CONST_BOOLEAN, kind) << "CONST_BOOLEAN";
- return d_exprMgr->mkConst<bool>(arg);
+ CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
+ << "Expected CVC4 to be compiled with SymFPU support";
+ return mkConstHelper<CVC4::FloatingPoint>(
+ FloatingPoint::makeInf(FloatingPointSize(exp, sig), true));
}
-Term Solver::mkConst(Kind kind, const char* arg) const
+Term Solver::mkNaN(uint32_t exp, uint32_t sig) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == CONST_STRING, kind) << "CONST_STRING";
- return d_exprMgr->mkConst(CVC4::String(arg));
+ CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
+ << "Expected CVC4 to be compiled with SymFPU support";
+ return mkConstHelper<CVC4::FloatingPoint>(
+ FloatingPoint::makeNaN(FloatingPointSize(exp, sig)));
}
-Term Solver::mkConst(Kind kind, const std::string& arg) const
+Term Solver::mkPosZero(uint32_t exp, uint32_t sig) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == CONST_STRING, kind) << "CONST_STRING";
- return d_exprMgr->mkConst(CVC4::String(arg));
+ CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
+ << "Expected CVC4 to be compiled with SymFPU support";
+ return mkConstHelper<CVC4::FloatingPoint>(
+ FloatingPoint::makeZero(FloatingPointSize(exp, sig), false));
}
-Term Solver::mkConst(Kind kind, const char* arg1, uint32_t arg2) const
+Term Solver::mkNegZero(uint32_t exp, uint32_t sig) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == ABSTRACT_VALUE || kind == CONST_RATIONAL
- || kind == CONST_BITVECTOR,
- kind)
- << "ABSTRACT_VALUE or CONST_RATIONAL or CONST_BITVECTOR";
- if (kind == ABSTRACT_VALUE)
- {
- return d_exprMgr->mkConst(CVC4::AbstractValue(Integer(arg1, arg2)));
- }
- if (kind == CONST_RATIONAL)
- {
- return d_exprMgr->mkConst(CVC4::Rational(arg1, arg2));
- }
- return d_exprMgr->mkConst(CVC4::BitVector(arg1, arg2));
+ CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
+ << "Expected CVC4 to be compiled with SymFPU support";
+ return mkConstHelper<CVC4::FloatingPoint>(
+ FloatingPoint::makeZero(FloatingPointSize(exp, sig), true));
}
-Term Solver::mkConst(Kind kind, const std::string& arg1, uint32_t arg2) const
+Term Solver::mkRoundingMode(RoundingMode rm) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == ABSTRACT_VALUE || kind == CONST_RATIONAL
- || kind == CONST_BITVECTOR,
- kind)
- << "ABSTRACT_VALUE or CONST_RATIONAL or CONST_BITVECTOR";
- if (kind == ABSTRACT_VALUE)
- {
- return d_exprMgr->mkConst(CVC4::AbstractValue(Integer(arg1, arg2)));
- }
- if (kind == CONST_RATIONAL)
- {
- return d_exprMgr->mkConst(CVC4::Rational(arg1, arg2));
- }
- return d_exprMgr->mkConst(CVC4::BitVector(arg1, arg2));
+ return mkConstHelper<CVC4::RoundingMode>(s_rmodes.at(rm));
}
-Term Solver::mkConst(Kind kind, uint32_t arg) const
+Term Solver::mkUninterpretedConst(Sort sort, int32_t index) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == ABSTRACT_VALUE || kind == CONST_RATIONAL
- || kind == CONST_BITVECTOR,
- kind)
- << "ABSTRACT_VALUE or CONST_RATIONAL or CONST_BITVECTOR";
- if (kind == ABSTRACT_VALUE)
+ CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ return mkConstHelper<CVC4::UninterpretedConstant>(
+ CVC4::UninterpretedConstant(*sort.d_type, index));
+}
+
+Term Solver::mkAbstractValue(const std::string& index) const
+{
+ CVC4_API_ARG_CHECK_EXPECTED(!index.empty(), index) << "a non-empty string";
+ try
{
- return d_exprMgr->mkConst(CVC4::AbstractValue(Integer(arg)));
+ 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));
+ // do not call getType(), for abstract values, type can not be computed
+ // until it is substituted away
}
- if (kind == CONST_RATIONAL)
+ catch (const std::invalid_argument& e)
{
- return d_exprMgr->mkConst(CVC4::Rational(arg));
+ throw CVC4ApiException(e.what());
}
- return d_exprMgr->mkConst(CVC4::BitVector(arg));
-}
-
-Term Solver::mkConst(Kind kind, int32_t arg) const
-{
- CVC4_API_KIND_CHECK_EXPECTED(kind == ABSTRACT_VALUE || kind == CONST_RATIONAL,
- kind)
- << "ABSTRACT_VALUE or CONST_RATIONAL";
- if (kind == ABSTRACT_VALUE)
+ catch (const CVC4::TypeCheckingException& e)
{
- return d_exprMgr->mkConst(CVC4::AbstractValue(Integer(arg)));
+ throw CVC4ApiException(e.getMessage());
}
- return d_exprMgr->mkConst(CVC4::Rational(arg));
}
-Term Solver::mkConst(Kind kind, int64_t arg) const
+Term Solver::mkAbstractValue(uint64_t index) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == ABSTRACT_VALUE || kind == CONST_RATIONAL,
- kind)
- << "ABSTRACT_VALUE or CONST_RATIONAL";
- if (kind == ABSTRACT_VALUE)
+ try
{
- return d_exprMgr->mkConst(CVC4::AbstractValue(Integer(arg)));
+ CVC4_API_ARG_CHECK_EXPECTED(index > 0, index) << "an integer > 0";
+ return d_exprMgr->mkConst(CVC4::AbstractValue(Integer(index)));
+ // do not call getType(), for abstract values, type can not be computed
+ // until it is substituted away
}
- return d_exprMgr->mkConst(CVC4::Rational(arg));
-}
-
-Term Solver::mkConst(Kind kind, uint64_t arg) const
-{
- CVC4_API_KIND_CHECK_EXPECTED(kind == ABSTRACT_VALUE || kind == CONST_RATIONAL,
- kind)
- << "ABSTRACT_VALUE or CONST_RATIONAL";
- if (kind == ABSTRACT_VALUE)
+ catch (const std::invalid_argument& e)
{
- return d_exprMgr->mkConst(CVC4::AbstractValue(Integer(arg)));
+ throw CVC4ApiException(e.what());
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
}
- return d_exprMgr->mkConst(CVC4::Rational(arg));
-}
-
-Term Solver::mkConst(Kind kind, uint32_t arg1, uint32_t arg2) const
-{
- CVC4_API_KIND_CHECK_EXPECTED(kind == CONST_RATIONAL, kind)
- << "CONST_RATIONAL";
- return d_exprMgr->mkConst(CVC4::Rational(arg1, arg2));
-}
-
-Term Solver::mkConst(Kind kind, int32_t arg1, int32_t arg2) const
-{
- CVC4_API_KIND_CHECK_EXPECTED(kind == CONST_RATIONAL, kind)
- << "CONST_RATIONAL";
- return d_exprMgr->mkConst(CVC4::Rational(arg1, arg2));
-}
-
-Term Solver::mkConst(Kind kind, int64_t arg1, int64_t arg2) const
-{
- CVC4_API_KIND_CHECK_EXPECTED(kind == CONST_RATIONAL, kind)
- << "CONST_RATIONAL";
- return d_exprMgr->mkConst(CVC4::Rational(arg1, arg2));
-}
-
-Term Solver::mkConst(Kind kind, uint64_t arg1, uint64_t arg2) const
-{
- CVC4_API_KIND_CHECK_EXPECTED(kind == CONST_RATIONAL, kind)
- << "CONST_RATIONAL";
- return d_exprMgr->mkConst(CVC4::Rational(arg1, arg2));
-}
-
-Term Solver::mkConst(Kind kind, uint32_t arg1, uint64_t arg2) const
-{
- CVC4_API_KIND_CHECK_EXPECTED(kind == CONST_BITVECTOR, kind)
- << "CONST_BITVECTOR";
- return d_exprMgr->mkConst(CVC4::BitVector(arg1, arg2));
}
-Term Solver::mkConst(Kind kind, uint32_t arg1, uint32_t arg2, Term arg3) const
+Term Solver::mkFloatingPoint(uint32_t exp, uint32_t sig, Term val) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == CONST_FLOATINGPOINT, kind)
- << "CONST_FLOATINGPOINT";
+ CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
+ << "Expected CVC4 to be compiled with SymFPU support";
+ CVC4_API_ARG_CHECK_EXPECTED(exp > 0, exp) << "a value > 0";
+ CVC4_API_ARG_CHECK_EXPECTED(sig > 0, sig) << "a value > 0";
+ uint32_t bw = exp + sig;
+ 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_ARG_CHECK_EXPECTED(
- arg3.getSort().isBitVector() && arg3.d_expr->isConst(), arg3)
+ val.getSort().isBitVector() && val.d_expr->isConst(), val)
<< "bit-vector constant";
- return d_exprMgr->mkConst(
- CVC4::FloatingPoint(arg1, arg2, arg3.d_expr->getConst<BitVector>()));
+ return mkConstHelper<CVC4::FloatingPoint>(
+ CVC4::FloatingPoint(exp, sig, val.d_expr->getConst<BitVector>()));
}
/* Create variables */
@@ -2202,19 +2379,62 @@ Term Solver::mkConst(Kind kind, uint32_t arg1, uint32_t arg2, Term arg3) const
Term Solver::mkVar(const std::string& symbol, Sort sort) const
{
- return d_exprMgr->mkVar(symbol, *sort.d_type);
+ try
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ Term res = d_exprMgr->mkVar(symbol, *sort.d_type);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
-Term Solver::mkVar(Sort sort) const { return d_exprMgr->mkVar(*sort.d_type); }
+Term Solver::mkVar(Sort sort) const
+{
+ try
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ Term res = d_exprMgr->mkVar(*sort.d_type);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
+}
Term Solver::mkBoundVar(const std::string& symbol, Sort sort) const
{
- return d_exprMgr->mkBoundVar(symbol, *sort.d_type);
+ try
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ Term res = d_exprMgr->mkBoundVar(symbol, *sort.d_type);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkBoundVar(Sort sort) const
{
- return d_exprMgr->mkBoundVar(*sort.d_type);
+ try
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+ Term res = d_exprMgr->mkBoundVar(*sort.d_type);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
/* Create terms */
@@ -2269,88 +2489,218 @@ void Solver::checkMkOpTerm(OpTerm opTerm, uint32_t nchildren) const
Term Solver::mkTerm(Kind kind) const
{
- CVC4_API_KIND_CHECK_EXPECTED(
- kind == PI || kind == REGEXP_EMPTY || kind == REGEXP_SIGMA, kind)
- << "PI or REGEXP_EMPTY or REGEXP_SIGMA";
- if (kind == REGEXP_EMPTY || kind == REGEXP_SIGMA)
+ try
{
- CVC4::Kind k = extToIntKind(kind);
- Assert(isDefinedIntKind(k));
- return d_exprMgr->mkExpr(k, std::vector<Expr>());
+ CVC4_API_KIND_CHECK_EXPECTED(
+ kind == PI || kind == REGEXP_EMPTY || kind == REGEXP_SIGMA, kind)
+ << "PI or REGEXP_EMPTY or REGEXP_SIGMA";
+ Term res;
+ if (kind == REGEXP_EMPTY || kind == REGEXP_SIGMA)
+ {
+ CVC4::Kind k = extToIntKind(kind);
+ Assert(isDefinedIntKind(k));
+ res = d_exprMgr->mkExpr(k, std::vector<Expr>());
+ }
+ else
+ {
+ 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;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
}
- Assert(kind == PI);
- return d_exprMgr->mkNullaryOperator(d_exprMgr->realType(), CVC4::kind::PI);
}
Term Solver::mkTerm(Kind kind, Sort sort) const
{
- CVC4_API_KIND_CHECK_EXPECTED(kind == SEP_NIL || kind == UNIVERSE_SET, kind)
- << "SEP_NIL or UNIVERSE_SET";
- return d_exprMgr->mkNullaryOperator(*sort.d_type, extToIntKind(kind));
+ try
+ {
+ CVC4_API_KIND_CHECK_EXPECTED(kind == SEP_NIL, kind) << "SEP_NIL";
+ Term res = d_exprMgr->mkNullaryOperator(*sort.d_type, extToIntKind(kind));
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkTerm(Kind kind, Term child) const
{
- checkMkTerm(kind, 1);
- return d_exprMgr->mkExpr(extToIntKind(kind), *child.d_expr);
+ try
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(!child.isNull(), child) << "non-null term";
+ 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;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkTerm(Kind kind, Term child1, Term child2) const
{
- checkMkTerm(kind, 2);
- return d_exprMgr->mkExpr(extToIntKind(kind), *child1.d_expr, *child2.d_expr);
+ try
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(!child1.isNull(), child1) << "non-null term";
+ CVC4_API_ARG_CHECK_EXPECTED(!child2.isNull(), child2) << "non-null term";
+ checkMkTerm(kind, 2);
+ Term res =
+ d_exprMgr->mkExpr(extToIntKind(kind), *child1.d_expr, *child2.d_expr);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkTerm(Kind kind, Term child1, Term child2, Term child3) const
{
- checkMkTerm(kind, 3);
- std::vector<Expr> echildren{*child1.d_expr, *child2.d_expr, *child3.d_expr};
- CVC4::Kind k = extToIntKind(kind);
- Assert(isDefinedIntKind(k));
- return kind::isAssociative(k) ? d_exprMgr->mkAssociative(k, echildren)
- : d_exprMgr->mkExpr(k, echildren);
+ try
+ {
+ 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";
+ checkMkTerm(kind, 3);
+ std::vector<Expr> echildren{*child1.d_expr, *child2.d_expr, *child3.d_expr};
+ CVC4::Kind k = extToIntKind(kind);
+ Assert(isDefinedIntKind(k));
+ Term res = kind::isAssociative(k) ? d_exprMgr->mkAssociative(k, echildren)
+ : d_exprMgr->mkExpr(k, echildren);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkTerm(Kind kind, const std::vector<Term>& children) const
{
- checkMkTerm(kind, children.size());
- std::vector<Expr> echildren = termVectorToExprs(children);
- CVC4::Kind k = extToIntKind(kind);
- Assert(isDefinedIntKind(k));
- return kind::isAssociative(k) ? d_exprMgr->mkAssociative(k, echildren)
- : d_exprMgr->mkExpr(k, echildren);
-}
-
-Term Solver::mkTerm(OpTerm opTerm) const
-{
- checkMkOpTerm(opTerm, 0);
- return d_exprMgr->mkExpr(*opTerm.d_expr);
+ try
+ {
+ 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)
+ << "non-null term";
+ }
+ checkMkTerm(kind, children.size());
+ std::vector<Expr> echildren = termVectorToExprs(children);
+ CVC4::Kind k = extToIntKind(kind);
+ Assert(isDefinedIntKind(k));
+ Term res = kind::isAssociative(k) ? d_exprMgr->mkAssociative(k, echildren)
+ : d_exprMgr->mkExpr(k, echildren);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkTerm(OpTerm opTerm, Term child) const
{
- checkMkOpTerm(opTerm, 1);
- return d_exprMgr->mkExpr(*opTerm.d_expr, *child.d_expr);
+ try
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(!child.isNull(), child) << "non-null term";
+ checkMkOpTerm(opTerm, 1);
+ Term res = d_exprMgr->mkExpr(*opTerm.d_expr, *child.d_expr);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkTerm(OpTerm opTerm, Term child1, Term child2) const
{
- checkMkOpTerm(opTerm, 2);
- return d_exprMgr->mkExpr(*opTerm.d_expr, *child1.d_expr, *child2.d_expr);
+ try
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(!child1.isNull(), child1) << "non-null term";
+ CVC4_API_ARG_CHECK_EXPECTED(!child2.isNull(), child2) << "non-null term";
+ checkMkOpTerm(opTerm, 2);
+ Term res =
+ d_exprMgr->mkExpr(*opTerm.d_expr, *child1.d_expr, *child2.d_expr);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkTerm(OpTerm opTerm, Term child1, Term child2, Term child3) const
{
- checkMkOpTerm(opTerm, 3);
- return d_exprMgr->mkExpr(
- *opTerm.d_expr, *child1.d_expr, *child2.d_expr, *child3.d_expr);
+ try
+ {
+ 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";
+ checkMkOpTerm(opTerm, 3);
+ Term res = d_exprMgr->mkExpr(
+ *opTerm.d_expr, *child1.d_expr, *child2.d_expr, *child3.d_expr);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
}
Term Solver::mkTerm(OpTerm opTerm, const std::vector<Term>& children) const
{
- checkMkOpTerm(opTerm, children.size());
- std::vector<Expr> echildren = termVectorToExprs(children);
- return d_exprMgr->mkExpr(*opTerm.d_expr, echildren);
+ try
+ {
+ 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)
+ << "non-null term";
+ }
+ checkMkOpTerm(opTerm, children.size());
+ std::vector<Expr> echildren = termVectorToExprs(children);
+ Term res = d_exprMgr->mkExpr(*opTerm.d_expr, echildren);
+ (void)res.d_expr->getType(true); /* kick off type checking */
+ return res;
+ }
+ catch (const CVC4::TypeCheckingException& e)
+ {
+ throw CVC4ApiException(e.getMessage());
+ }
+}
+
+Term Solver::mkTuple(const std::vector<Sort>& sorts,
+ const std::vector<Term>& terms) const
+{
+ CVC4_API_CHECK(sorts.size() == terms.size())
+ << "Expected the same number of sorts and elements";
+ std::vector<Term> args;
+ for (size_t i = 0, size = sorts.size(); i < size; i++)
+ {
+ args.push_back(ensureTermSort(terms[i], sorts[i]));
+ }
+
+ Sort s = mkTupleSort(sorts);
+ Datatype dt = s.getDatatype();
+ args.insert(args.begin(), dt[0].getConstructorTerm());
+ return mkTerm(APPLY_CONSTRUCTOR, args);
}
std::vector<Expr> Solver::termVectorToExprs(
@@ -2370,14 +2720,15 @@ std::vector<Expr> Solver::termVectorToExprs(
OpTerm Solver::mkOpTerm(Kind kind, Kind k)
{
CVC4_API_KIND_CHECK_EXPECTED(kind == CHAIN_OP, kind) << "CHAIN_OP";
- return d_exprMgr->mkConst(CVC4::Chain(extToIntKind(k)));
+ return *mkConstHelper<CVC4::Chain>(CVC4::Chain(extToIntKind(k))).d_expr.get();
}
OpTerm Solver::mkOpTerm(Kind kind, const std::string& arg)
{
CVC4_API_KIND_CHECK_EXPECTED(kind == RECORD_UPDATE_OP, kind)
<< "RECORD_UPDATE_OP";
- return d_exprMgr->mkConst(CVC4::RecordUpdate(arg));
+ return *mkConstHelper<CVC4::RecordUpdate>(CVC4::RecordUpdate(arg))
+ .d_expr.get();
}
OpTerm Solver::mkOpTerm(Kind kind, uint32_t arg)
@@ -2386,39 +2737,60 @@ OpTerm Solver::mkOpTerm(Kind kind, uint32_t arg)
OpTerm res;
switch (kind)
{
- case DIVISIBLE_OP: res = d_exprMgr->mkConst(CVC4::Divisible(arg)); break;
+ case DIVISIBLE_OP:
+ res = *mkConstHelper<CVC4::Divisible>(CVC4::Divisible(arg)).d_expr.get();
+ break;
case BITVECTOR_REPEAT_OP:
- res = d_exprMgr->mkConst(CVC4::BitVectorRepeat(arg));
+ res = *mkConstHelper<CVC4::BitVectorRepeat>(CVC4::BitVectorRepeat(arg))
+ .d_expr.get();
break;
case BITVECTOR_ZERO_EXTEND_OP:
- res = d_exprMgr->mkConst(CVC4::BitVectorZeroExtend(arg));
+ res = *mkConstHelper<CVC4::BitVectorZeroExtend>(
+ CVC4::BitVectorZeroExtend(arg))
+ .d_expr.get();
break;
case BITVECTOR_SIGN_EXTEND_OP:
- res = d_exprMgr->mkConst(CVC4::BitVectorSignExtend(arg));
+ res = *mkConstHelper<CVC4::BitVectorSignExtend>(
+ CVC4::BitVectorSignExtend(arg))
+ .d_expr.get();
break;
case BITVECTOR_ROTATE_LEFT_OP:
- res = d_exprMgr->mkConst(CVC4::BitVectorRotateLeft(arg));
+ res = *mkConstHelper<CVC4::BitVectorRotateLeft>(
+ CVC4::BitVectorRotateLeft(arg))
+ .d_expr.get();
break;
case BITVECTOR_ROTATE_RIGHT_OP:
- res = d_exprMgr->mkConst(CVC4::BitVectorRotateRight(arg));
+ res = *mkConstHelper<CVC4::BitVectorRotateRight>(
+ CVC4::BitVectorRotateRight(arg))
+ .d_expr.get();
break;
case INT_TO_BITVECTOR_OP:
- res = d_exprMgr->mkConst(CVC4::IntToBitVector(arg));
+ res = *mkConstHelper<CVC4::IntToBitVector>(CVC4::IntToBitVector(arg))
+ .d_expr.get();
break;
case FLOATINGPOINT_TO_UBV_OP:
- res = d_exprMgr->mkConst(CVC4::FloatingPointToUBV(arg));
+ res = *mkConstHelper<CVC4::FloatingPointToUBV>(
+ CVC4::FloatingPointToUBV(arg))
+ .d_expr.get();
break;
case FLOATINGPOINT_TO_UBV_TOTAL_OP:
- res = d_exprMgr->mkConst(CVC4::FloatingPointToUBVTotal(arg));
+ res = *mkConstHelper<CVC4::FloatingPointToUBVTotal>(
+ CVC4::FloatingPointToUBVTotal(arg))
+ .d_expr.get();
break;
case FLOATINGPOINT_TO_SBV_OP:
- res = d_exprMgr->mkConst(CVC4::FloatingPointToSBV(arg));
+ res = *mkConstHelper<CVC4::FloatingPointToSBV>(
+ CVC4::FloatingPointToSBV(arg))
+ .d_expr.get();
break;
case FLOATINGPOINT_TO_SBV_TOTAL_OP:
- res = d_exprMgr->mkConst(CVC4::FloatingPointToSBVTotal(arg));
+ res = *mkConstHelper<CVC4::FloatingPointToSBVTotal>(
+ CVC4::FloatingPointToSBVTotal(arg))
+ .d_expr.get();
break;
case TUPLE_UPDATE_OP:
- res = d_exprMgr->mkConst(CVC4::TupleUpdate(arg));
+ res = *mkConstHelper<CVC4::TupleUpdate>(CVC4::TupleUpdate(arg))
+ .d_expr.get();
break;
default:
CVC4_API_KIND_CHECK_EXPECTED(false, kind)
@@ -2435,29 +2807,39 @@ OpTerm Solver::mkOpTerm(Kind kind, uint32_t arg1, uint32_t arg2)
switch (kind)
{
case BITVECTOR_EXTRACT_OP:
- res = d_exprMgr->mkConst(CVC4::BitVectorExtract(arg1, arg2));
+ res = *mkConstHelper<CVC4::BitVectorExtract>(
+ CVC4::BitVectorExtract(arg1, arg2))
+ .d_expr.get();
break;
case FLOATINGPOINT_TO_FP_IEEE_BITVECTOR_OP:
- res =
- d_exprMgr->mkConst(CVC4::FloatingPointToFPIEEEBitVector(arg1, arg2));
+ res = *mkConstHelper<CVC4::FloatingPointToFPIEEEBitVector>(
+ CVC4::FloatingPointToFPIEEEBitVector(arg1, arg2))
+ .d_expr.get();
break;
case FLOATINGPOINT_TO_FP_FLOATINGPOINT_OP:
- res =
- d_exprMgr->mkConst(CVC4::FloatingPointToFPFloatingPoint(arg1, arg2));
+ res = *mkConstHelper<CVC4::FloatingPointToFPFloatingPoint>(
+ CVC4::FloatingPointToFPFloatingPoint(arg1, arg2))
+ .d_expr.get();
break;
case FLOATINGPOINT_TO_FP_REAL_OP:
- res = d_exprMgr->mkConst(CVC4::FloatingPointToFPReal(arg1, arg2));
+ res = *mkConstHelper<CVC4::FloatingPointToFPReal>(
+ CVC4::FloatingPointToFPReal(arg1, arg2))
+ .d_expr.get();
break;
case FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR_OP:
- res = d_exprMgr->mkConst(
- CVC4::FloatingPointToFPSignedBitVector(arg1, arg2));
+ res = *mkConstHelper<CVC4::FloatingPointToFPSignedBitVector>(
+ CVC4::FloatingPointToFPSignedBitVector(arg1, arg2))
+ .d_expr.get();
break;
case FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR_OP:
- res = d_exprMgr->mkConst(
- CVC4::FloatingPointToFPUnsignedBitVector(arg1, arg2));
+ res = *mkConstHelper<CVC4::FloatingPointToFPUnsignedBitVector>(
+ CVC4::FloatingPointToFPUnsignedBitVector(arg1, arg2))
+ .d_expr.get();
break;
case FLOATINGPOINT_TO_FP_GENERIC_OP:
- res = d_exprMgr->mkConst(CVC4::FloatingPointToFPGeneric(arg1, arg2));
+ res = *mkConstHelper<CVC4::FloatingPointToFPGeneric>(
+ CVC4::FloatingPointToFPGeneric(arg1, arg2))
+ .d_expr.get();
break;
default:
CVC4_API_KIND_CHECK_EXPECTED(false, kind)
@@ -2993,26 +3375,70 @@ void Solver::reset(void) const { d_smtEngine->reset(); }
*/
void Solver::resetAssertions(void) const { d_smtEngine->resetAssertions(); }
+// TODO: issue #2781
+void Solver::setLogicHelper(const std::string& logic) 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());
+ }
+}
+
/**
* ( set-info <attribute> )
*/
void Solver::setInfo(const std::string& keyword, const std::string& value) const
{
- // CHECK:
- // if keyword == "cvc4-logic": value must be string
- // if keyword == "status": must be sat, unsat or unknown
- // if keyword == "smt-lib-version": supported?
+ bool is_cvc4_keyword = false;
+
+ /* Check for CVC4-specific info keys (prefixed with "cvc4-" or "cvc4_") */
+ if (keyword.length() > 5)
+ {
+ std::string prefix = keyword.substr(0, 5);
+ if (prefix == "cvc4-" || prefix == "cvc4_")
+ {
+ is_cvc4_keyword = true;
+ std::string cvc4key = keyword.substr(5);
+ CVC4_API_ARG_CHECK_EXPECTED(cvc4key == "logic", keyword)
+ << "keyword 'cvc4-logic'";
+ setLogicHelper(value);
+ }
+ }
+ if (!is_cvc4_keyword)
+ {
+ CVC4_API_ARG_CHECK_EXPECTED(
+ keyword == "source" || keyword == "category" || keyword == "difficulty"
+ || keyword == "filename" || keyword == "license"
+ || keyword == "name" || keyword == "notes"
+ || keyword == "smt-lib-version" || keyword == "status",
+ keyword)
+ << "'source', 'category', 'difficulty', 'filename', 'license', 'name', "
+ "'notes', 'smt-lib-version' or 'status'";
+ CVC4_API_ARG_CHECK_EXPECTED(keyword != "smt-lib-version" || value == "2"
+ || value == "2.0" || value == "2.5"
+ || value == "2.6" || value == "2.6.1",
+ value)
+ << "'2.0', '2.5', '2.6' or '2.6.1'";
+ CVC4_API_ARG_CHECK_EXPECTED(keyword != "status" || value == "sat"
+ || value == "unsat" || value == "unknown",
+ value)
+ << "'sat', 'unsat' or 'unknown'";
+ }
+
d_smtEngine->setInfo(keyword, value);
}
/**
* ( set-logic <symbol> )
*/
-void Solver::setLogic(const std::string& logic) const
-{
- // CHECK: !d_smtEngine->d_fullyInited
- d_smtEngine->setLogic(logic);
-}
+void Solver::setLogic(const std::string& logic) const { setLogicHelper(logic); }
/**
* ( set-option <option> )
@@ -3020,9 +3446,41 @@ void Solver::setLogic(const std::string& logic) const
void Solver::setOption(const std::string& option,
const std::string& value) const
{
- // CHECK: option exists?
- // CHECK: !d_smtEngine->d_fullInited, else option can't be set
- d_smtEngine->setOption(option, value);
+ 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());
+ }
+}
+
+Term Solver::ensureTermSort(const Term& t, const Sort& s) const
+{
+ CVC4_API_CHECK(t.getSort() == s || (t.getSort().isInteger() && s.isReal()))
+ << "Expected conversion from Int to Real";
+
+ if (t.getSort() == s)
+ {
+ return t;
+ }
+
+ // Integers are reals, too
+ Assert(t.getSort().isReal());
+ Term res = t;
+ if (t.getSort().isInteger())
+ {
+ // Must cast to Real to ensure correct type is passed to parametric type
+ // 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 = mkTerm(DIVISION, *t.d_expr, mkReal(1));
+ }
+ Assert(res.getSort() == s);
+ return res;
}
/**
diff --git a/src/api/cvc4cpp.h b/src/api/cvc4cpp.h
index d06955a05..a06f2e415 100644
--- a/src/api/cvc4cpp.h
+++ b/src/api/cvc4cpp.h
@@ -24,8 +24,8 @@
#include <map>
#include <memory>
#include <set>
-#include <string>
#include <sstream>
+#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
@@ -53,9 +53,10 @@ class CVC4_PUBLIC CVC4ApiException : public std::exception
{
public:
CVC4ApiException(const std::string& str) : d_msg(str) {}
- CVC4ApiException(const std::stringstream& stream) :d_msg(stream.str()) {}
+ CVC4ApiException(const std::stringstream& stream) : d_msg(stream.str()) {}
std::string getMessage() const { return d_msg; }
const char* what() const noexcept override { return d_msg.c_str(); }
+
private:
std::string d_msg;
};
@@ -192,6 +193,11 @@ class CVC4_PUBLIC Sort
Sort(const CVC4::Type& t);
/**
+ * Constructor.
+ */
+ Sort();
+
+ /**
* Destructor.
*/
~Sort();
@@ -211,6 +217,11 @@ class CVC4_PUBLIC Sort
bool operator!=(const Sort& s) const;
/**
+ * @return true if this Sort is a null sort.
+ */
+ bool isNull() const;
+
+ /**
* Is this a Boolean sort?
* @return true if the sort is a Boolean sort
*/
@@ -1125,7 +1136,7 @@ class CVC4_PUBLIC DatatypeConstructor
/**
* Constructor.
* @param ctor the internal datatype constructor to be wrapped
- * @return thte DatatypeConstructor
+ * @return the DatatypeConstructor
*/
DatatypeConstructor(const CVC4::DatatypeConstructor& ctor);
@@ -1135,6 +1146,17 @@ class CVC4_PUBLIC DatatypeConstructor
~DatatypeConstructor();
/**
+ * @return true if this datatype constructor has been resolved.
+ */
+ bool isResolved() const;
+
+ /**
+ * Get the constructor operator of this datatype constructor.
+ * @return the constructor operator
+ */
+ Term getConstructorTerm() const;
+
+ /**
* Get the datatype selector with the given name.
* This is a linear search through the selectors, so in case of
* multiple, similarly-named selectors, the first is returned.
@@ -1276,6 +1298,13 @@ class CVC4_PUBLIC Datatype
~Datatype();
/**
+ * Get the datatype constructor at a given index.
+ * @param idx the index of the datatype constructor to return
+ * @return the datatype constructor with the given index
+ */
+ DatatypeConstructor operator[](size_t idx) const;
+
+ /**
* Get the datatype constructor with the given name.
* This is a linear search through the constructors, so in case of multiple,
* similarly-named constructors, the first is returned.
@@ -1511,6 +1540,11 @@ class CVC4_PUBLIC Solver
/* .................................................................... */
/**
+ * @return sort null
+ */
+ Sort getNullSort() const;
+
+ /**
* @return sort Boolean
*/
Sort getBooleanSort() const;
@@ -1691,14 +1725,6 @@ class CVC4_PUBLIC Solver
Term mkTerm(Kind kind, const std::vector<Term>& children) const;
/**
- * Create term with no children from a given operator term.
- * Create operator terms with mkOpTerm().
- * @param the operator term
- * @return the Term
- */
- Term mkTerm(OpTerm opTerm) const;
-
- /**
* Create unary term from a given operator term.
* Create operator terms with mkOpTerm().
* @param the operator term
@@ -1737,6 +1763,16 @@ class CVC4_PUBLIC Solver
*/
Term mkTerm(OpTerm opTerm, const std::vector<Term>& children) const;
+ /**
+ * Create a tuple term. Terms are automatically converted if sorts are
+ * compatible.
+ * @param sorts The sorts of the elements in the tuple
+ * @param terms The elements in the tuple
+ * @return the tuple Term
+ */
+ Term mkTuple(const std::vector<Sort>& sorts,
+ const std::vector<Term>& terms) const;
+
/* .................................................................... */
/* Create Operator Terms */
/* .................................................................... */
@@ -1819,128 +1855,84 @@ class CVC4_PUBLIC Solver
Term mkBoolean(bool val) const;
/**
- * Create an Integer constant.
- * @param s the string represetntation of the constant
- * @param base the base of the string representation
- * @return the Integer constant
- */
- Term mkInteger(const char* s, uint32_t base = 10) const;
-
- /**
- * Create an Integer constant.
- * @param s the string represetntation of the constant
- * @param base the base of the string representation
- * @return the Integer constant
- */
- Term mkInteger(const std::string& s, uint32_t base = 10) const;
-
- /**
- * Create an Integer constant.
- * @param val the value of the constant
- * @return the Integer constant
- */
- Term mkInteger(int32_t val) const;
-
- /**
- * Create an Integer constant.
- * @param val the value of the constant
- * @return the Integer constant
- */
- Term mkInteger(uint32_t val) const;
-
- /**
- * Create an Integer constant.
- * @param val the value of the constant
- * @return the Integer constant
- */
- Term mkInteger(int64_t val) const;
-
- /**
- * Create an Integer constant.
- * @param val the value of the constant
- * @return the Integer constant
- */
- Term mkInteger(uint64_t val) const;
-
- /**
* Create a constant representing the number Pi.
* @return a constant representing Pi
*/
Term mkPi() const;
/**
- * Create an Real constant.
- * @param s the string represetntation of the constant
- * @param base the base of the string representation
- * @return the Real constant
+ * Create a real constant from a string.
+ * @param s the string representation of the constant, may represent an
+ * integer (e.g., "123") or real constant (e.g., "12.34" or "12/34").
+ * @return a constant of sort Real or Integer (if 's' represents an integer)
*/
- Term mkReal(const char* s, uint32_t base = 10) const;
+ Term mkReal(const char* s) const;
/**
- * Create an Real constant.
- * @param s the string represetntation of the constant
- * @param base the base of the string representation
- * @return the Real constant
+ * Create a real constant from a string.
+ * @param s the string representation of the constant, may represent an
+ * integer (e.g., "123") or real constant (e.g., "12.34" or "12/34").
+ * @return a constant of sort Real or Integer (if 's' represents an integer)
*/
- Term mkReal(const std::string& s, uint32_t base = 10) const;
+ Term mkReal(const std::string& s) const;
/**
- * Create an Real constant.
+ * Create a real constant from an integer.
* @param val the value of the constant
- * @return the Real constant
+ * @return a constant of sort Integer
*/
Term mkReal(int32_t val) const;
/**
- * Create an Real constant.
+ * Create a real constant from an integer.
* @param val the value of the constant
- * @return the Real constant
+ * @return a constant of sort Integer
*/
Term mkReal(int64_t val) const;
/**
- * Create an Real constant.
+ * Create a real constant from an unsigned integer.
* @param val the value of the constant
- * @return the Real constant
+ * @return a constant of sort Integer
*/
Term mkReal(uint32_t val) const;
/**
- * Create an Real constant.
+ * Create a real constant from an unsigned integer.
* @param val the value of the constant
- * @return the Real constant
+ * @return a constant of sort Integer
*/
Term mkReal(uint64_t val) const;
/**
- * Create an Rational constant.
+ * Create a real constant from a rational.
* @param num the value of the numerator
* @param den the value of the denominator
- * @return the Rational constant
+ * @return a constant of sort Real or Integer (if 'num' is divisible by 'den')
*/
Term mkReal(int32_t num, int32_t den) const;
/**
- * Create an Rational constant.
+ * Create a real constant from a rational.
* @param num the value of the numerator
* @param den the value of the denominator
- * @return the Rational constant
+ * @return a constant of sort Real or Integer (if 'num' is divisible by 'den')
*/
Term mkReal(int64_t num, int64_t den) const;
/**
- * Create an Rational constant.
+ * Create a real constant from a rational.
* @param num the value of the numerator
* @param den the value of the denominator
- * @return the Rational constant
+ * @return a constant of sort Real or Integer (if 'num' is divisible by 'den')
*/
Term mkReal(uint32_t num, uint32_t den) const;
/**
- * Create an Rational constant.
+ * Create a real constant from a rational.
* @param num the value of the numerator
* @param den the value of the denominator
- * @return the Rational constant
+ * @return a constant of sort Real or Integer (if 'num' is divisible by 'den')
*/
Term mkReal(uint64_t num, uint64_t den) const;
@@ -1973,16 +1965,20 @@ class CVC4_PUBLIC Solver
/**
* Create a String constant.
* @param s the string this constant represents
+ * @param useEscSequences determines whether escape sequences in \p s should
+ * be converted to the corresponding character
* @return the String constant
*/
- Term mkString(const char* s) const;
+ Term mkString(const char* s, bool useEscSequences = false) const;
/**
* Create a String constant.
* @param s the string this constant represents
+ * @param useEscSequences determines whether escape sequences in \p s should
+ * be converted to the corresponding character
* @return the String constant
*/
- Term mkString(const std::string& s) const;
+ Term mkString(const std::string& s, bool useEscSequences = false) const;
/**
* Create a String constant.
@@ -2006,222 +2002,125 @@ class CVC4_PUBLIC Solver
Term mkUniverseSet(Sort sort) const;
/**
- * Create a bit-vector constant of given size with value 0.
- * @param size the bit-width of the bit-vector sort
- * @return the bit-vector constant
- */
- Term mkBitVector(uint32_t size) const;
-
- /**
- * Create a bit-vector constant of given size and value.
- * @param size the bit-width of the bit-vector sort
- * @param val the value of the constant
- * @return the bit-vector constant
- */
- Term mkBitVector(uint32_t size, uint32_t val) const;
-
- /**
* Create a bit-vector constant of given size and value.
* @param size the bit-width of the bit-vector sort
* @param val the value of the constant
* @return the bit-vector constant
*/
- Term mkBitVector(uint32_t size, uint64_t val) const;
+ Term mkBitVector(uint32_t size, uint64_t val = 0) const;
/**
* Create a bit-vector constant from a given string.
- * @param s the string represetntation of the constant
- * @param base the base of the string representation
+ * @param s the string representation of the constant
+ * @param base the base of the string representation (2, 10, or 16)
* @return the bit-vector constant
*/
Term mkBitVector(const char* s, uint32_t base = 2) const;
/**
* Create a bit-vector constant from a given string.
- * @param s the string represetntation of the constant
- * @param base the base of the string representation
+ * @param s the string representation of the constant
+ * @param base the base of the string representation (2, 10, or 16)
* @return the bit-vector constant
*/
- Term mkBitVector(std::string& s, uint32_t base = 2) const;
-
- /**
- * Create constant of kind:
- * - CONST_ROUNDINGMODE
- * @param rm the floating point rounding mode this constant represents
- */
- Term mkConst(RoundingMode rm) const;
-
- /*
- * Create constant of kind:
- * - EMPTYSET
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg the argument to this kind
- */
- Term mkConst(Kind kind, Sort arg) const;
-
- /**
- * Create constant of kind:
- * - UNINTERPRETED_CONSTANT
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg1 the first argument to this kind
- * @param arg2 the second argument to this kind
- */
- Term mkConst(Kind kind, Sort arg1, int32_t arg2) const;
-
- /**
- * Create constant of kind:
- * - BOOLEAN
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg the argument to this kind
- */
- Term mkConst(Kind kind, bool arg) const;
+ Term mkBitVector(const std::string& s, uint32_t base = 2) const;
/**
- * Create constant of kind:
- * - CONST_STRING
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg the argument to this kind
- */
- Term mkConst(Kind kind, const char* arg) const;
-
- /**
- * Create constant of kind:
- * - CONST_STRING
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg the argument to this kind
- */
- Term mkConst(Kind kind, const std::string& arg) const;
-
- /**
- * Create constant of kind:
- * - ABSTRACT_VALUE
- * - CONST_RATIONAL (for integers, reals)
- * - CONST_BITVECTOR
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg1 the first argument to this kind
- * @param arg2 the second argument to this kind
+ * Create a bit-vector constant of a given bit-width from a given string.
+ * @param size the bit-width of the constant
+ * @param s the string representation of the constant
+ * @param base the base of the string representation (2, 10, or 16)
+ * @return the bit-vector constant
*/
- Term mkConst(Kind kind, const char* arg1, uint32_t arg2 = 10) const;
+ Term mkBitVector(uint32_t size, const char* s, uint32_t base) const;
/**
- * Create constant of kind:
- * - ABSTRACT_VALUE
- * - CONST_RATIONAL (for integers, reals)
- * - CONST_BITVECTOR
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg1 the first argument to this kind
- * @param arg2 the second argument to this kind
+ * Create a bit-vector constant of a given bit-width from a given string.
+ * @param size the bit-width of the constant
+ * @param s the string representation of the constant
+ * @param base the base of the string representation (2, 10, or 16)
+ * @return the bit-vector constant
*/
- Term mkConst(Kind kind, const std::string& arg1, uint32_t arg2 = 10) const;
+ Term mkBitVector(uint32_t size, std::string& s, uint32_t base) const;
/**
- * Create constant of kind:
- * - ABSTRACT_VALUE
- * - CONST_RATIONAL (for integers, reals)
- * - CONST_BITVECTOR
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg the argument to this kind
+ * Create a positive infinity floating-point constant. Requires CVC4 to be
+ * compiled with SymFPU support.
+ * @param exp Number of bits in the exponent
+ * @param sig Number of bits in the significand
+ * @return the floating-point constant
*/
- Term mkConst(Kind kind, uint32_t arg) const;
+ Term mkPosInf(uint32_t exp, uint32_t sig) const;
/**
- * Create constant of kind:
- * - ABSTRACT_VALUE
- * - CONST_RATIONAL (for integers, reals)
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg the argument to this kind
+ * Create a negative infinity floating-point constant. Requires CVC4 to be
+ * compiled with SymFPU support.
+ * @param exp Number of bits in the exponent
+ * @param sig Number of bits in the significand
+ * @return the floating-point constant
*/
- Term mkConst(Kind kind, int32_t arg) const;
+ Term mkNegInf(uint32_t exp, uint32_t sig) const;
/**
- * Create constant of kind:
- * - ABSTRACT_VALUE
- * - CONST_RATIONAL (for integers, reals)
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg the argument to this kind
+ * Create a not-a-number (NaN) floating-point constant. Requires CVC4 to be
+ * compiled with SymFPU support.
+ * @param exp Number of bits in the exponent
+ * @param sig Number of bits in the significand
+ * @return the floating-point constant
*/
- Term mkConst(Kind kind, int64_t arg) const;
+ Term mkNaN(uint32_t exp, uint32_t sig) const;
/**
- * Create constant of kind:
- * - ABSTRACT_VALUE
- * - CONST_RATIONAL (for integers, reals)
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg the argument to this kind
+ * Create a positive zero (+0.0) floating-point constant. Requires CVC4 to be
+ * compiled with SymFPU support.
+ * @param exp Number of bits in the exponent
+ * @param sig Number of bits in the significand
+ * @return the floating-point constant
*/
- Term mkConst(Kind kind, uint64_t arg) const;
+ Term mkPosZero(uint32_t exp, uint32_t sig) const;
/**
- * Create constant of kind:
- * - CONST_RATIONAL (for rationals)
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg1 the first argument to this kind
- * @param arg2 the second argument to this kind
+ * Create a negative zero (-0.0) floating-point constant. Requires CVC4 to be
+ * compiled with SymFPU support.
+ * @param exp Number of bits in the exponent
+ * @param sig Number of bits in the significand
+ * @return the floating-point constant
*/
- Term mkConst(Kind kind, int32_t arg1, int32_t arg2) const;
+ Term mkNegZero(uint32_t exp, uint32_t sig) const;
/**
- * Create constant of kind:
- * - CONST_RATIONAL (for rationals)
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg1 the first argument to this kind
- * @param arg2 the second argument to this kind
+ * Create a roundingmode constant.
+ * @param rm the floating point rounding mode this constant represents
*/
- Term mkConst(Kind kind, int64_t arg1, int64_t arg2) const;
+ Term mkRoundingMode(RoundingMode rm) const;
/**
- * Create constant of kind:
- * - CONST_RATIONAL (for rationals)
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg1 the first argument to this kind
- * @param arg2 the second argument to this kind
+ * Create uninterpreted constant.
+ * @param arg1 Sort of the constant
+ * @param arg2 Index of the constant
*/
- Term mkConst(Kind kind, uint32_t arg1, uint32_t arg2) const;
+ Term mkUninterpretedConst(Sort sort, int32_t index) const;
/**
- * Create constant of kind:
- * - CONST_RATIONAL (for rationals)
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg1 the first argument to this kind
- * @param arg2 the second argument to this kind
+ * Create an abstract value constant.
+ * @param index Index of the abstract value
*/
- Term mkConst(Kind kind, uint64_t arg1, uint64_t arg2) const;
+ Term mkAbstractValue(const std::string& index) const;
/**
- * Create constant of kind:
- * - CONST_BITVECTOR
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg1 the first argument to this kind
- * @param arg2 the second argument to this kind
+ * Create an abstract value constant.
+ * @param index Index of the abstract value
*/
- Term mkConst(Kind kind, uint32_t arg1, uint64_t arg2) const;
+ Term mkAbstractValue(uint64_t index) const;
/**
- * Create constant of kind:
- * - CONST_FLOATINGPOINT
- * See enum Kind for a description of the parameters.
- * @param kind the kind of the constant
- * @param arg1 the first argument to this kind
- * @param arg2 the second argument to this kind
- * @param arg3 the third argument to this kind
+ * Create a floating-point constant (requires CVC4 to be compiled with symFPU
+ * support).
+ * @param exp Size of the exponent
+ * @param sig Size of the significand
+ * @param val Value of the floating-point constant as a bit-vector term
*/
- Term mkConst(Kind kind, uint32_t arg1, uint32_t arg2, Term arg3) const;
+ Term mkFloatingPoint(uint32_t exp, uint32_t sig, Term val) const;
/* .................................................................... */
/* Create Variables */
@@ -2339,9 +2238,8 @@ class CVC4_PUBLIC Solver
* @param ctors the constructor declarations of the datatype sort
* @return the datatype sort
*/
- Sort declareDatatype(
- const std::string& symbol,
- const std::vector<DatatypeConstructorDecl>& ctors) const;
+ Sort declareDatatype(const std::string& symbol,
+ const std::vector<DatatypeConstructorDecl>& ctors) const;
/**
* Declare 0-arity function symbol.
@@ -2564,6 +2462,15 @@ class CVC4_PUBLIC Solver
*/
void setOption(const std::string& option, const std::string& value) const;
+ /**
+ * If needed, convert this term to a given sort. Note that the sort of the
+ * term must be convertible into the target sort. Currently only Int to Real
+ * conversions are supported.
+ * @param s the target sort
+ * @return the term wrapped into a sort conversion if needed
+ */
+ Term ensureTermSort(const Term& t, const Sort& s) const;
+
// !!! This is only temporarily available until the parser is fully migrated
// to the new API. !!!
ExprManager* getExprManager(void) const;
@@ -2581,6 +2488,28 @@ class CVC4_PUBLIC Solver
void checkMkOpTerm(OpTerm opTerm, uint32_t nchildren) const;
/* Helper to check for API misuse in mkOpTerm functions. */
void checkMkTerm(Kind kind, uint32_t nchildren) const;
+ /* Helper for mk-functions that call d_exprMgr->mkConst(). */
+ template <typename T>
+ Term mkConstHelper(T t) const;
+ /* Helper for mkReal functions that take a string as argument. */
+ Term mkRealFromStrHelper(std::string s) const;
+ /* Helper for mkBitVector functions that take a string as argument. */
+ Term mkBVFromStrHelper(std::string s, uint32_t base) const;
+ /* Helper for mkBitVector functions that take a string and a size as
+ * arguments. */
+ Term mkBVFromStrHelper(uint32_t size, std::string s, uint32_t base) const;
+ /* Helper for mkBitVector functions that take an integer as argument. */
+ Term mkBVFromIntHelper(uint32_t size, uint64_t val) const;
+ /* Helper for setLogic. */
+ void setLogicHelper(const std::string& logic) const;
+
+ /**
+ * Helper function that ensures that a given term is of sort real (as opposed
+ * to being of sort integer).
+ * @param term a term of sort integer or real
+ * @return a term of sort real
+ */
+ Term ensureRealSort(Term expr) const;
/* The expression manager of this solver. */
std::unique_ptr<ExprManager> d_exprMgr;
diff --git a/src/api/cvc4cppkind.h b/src/api/cvc4cppkind.h
index f91f934f9..a7f6926bb 100644
--- a/src/api/cvc4cppkind.h
+++ b/src/api/cvc4cppkind.h
@@ -62,7 +62,7 @@ enum CVC4_PUBLIC Kind : int32_t
* -[1]: Sort of the constant
* -[2]: Index of the constant
* Create with:
- * mkConst(Kind, Sort, int32_t)
+ * mkUninterpretedConst(Sort sort, int32_t index)
*/
UNINTERPRETED_CONSTANT,
/**
@@ -70,12 +70,8 @@ enum CVC4_PUBLIC Kind : int32_t
* Parameters: 1
* -[1]: Index of the abstract value
* Create with:
- * mkConst(Kind kind, const char* s, uint32_t base = 10)
- * mkConst(Kind kind, const std::string& s, uint32_t base = 10)
- * mkConst(Kind kind, uint32_t arg)
- * mkConst(Kind kind, int32_t arg)
- * mkConst(Kind kind, int64_t arg)
- * mkConst(Kind kind, uint64_t arg)
+ * mkAbstractValue(const std::string& index);
+ * mkAbstractValue(uint64_t index);
*/
ABSTRACT_VALUE,
#if 0
@@ -204,7 +200,6 @@ enum CVC4_PUBLIC Kind : int32_t
* mkTrue()
* mkFalse()
* mkBoolean(bool val)
- * mkConst(Kind kind, bool arg)
*/
CONST_BOOLEAN,
/* Logical not.
@@ -568,20 +563,10 @@ enum CVC4_PUBLIC Kind : int32_t
* mkReal(int64_t val)
* mkReal(uint32_t val)
* mkReal(uint64_t val)
- * mkRational(int32_t num, int32_t den)
- * mkRational(int64_t num, int64_t den)
- * mkRational(uint32_t num, uint32_t den)
- * mkRational(uint64_t num, uint64_t den)
- * mkConst(Kind kind, const char* s, uint32_t base = 10)
- * mkConst(Kind kind, const std::string& s, uint32_t base = 10)
- * mkConst(Kind kind, uint32_t arg)
- * mkConst(Kind kind, int64_t arg)
- * mkConst(Kind kind, uint64_t arg)
- * mkConst(Kind kind, int32_t arg)
- * mkConst(Kind kind, int32_t arg1, int32_t arg2)
- * mkConst(Kind kind, int64_t arg1, int64_t arg2)
- * mkConst(Kind kind, uint32_t arg1, uint32_t arg2)
- * mkConst(Kind kind, uint64_t arg1, uint64_t arg2)
+ * mkReal(int32_t num, int32_t den)
+ * mkReal(int64_t num, int64_t den)
+ * mkReal(uint32_t num, uint32_t den)
+ * mkReal(uint64_t num, uint64_t den)
*/
CONST_RATIONAL,
/**
@@ -658,15 +643,9 @@ enum CVC4_PUBLIC Kind : int32_t
* Parameters:
* See mkBitVector().
* Create with:
- * mkBitVector(uint32_t size)
- * mkBitVector(uint32_t size, uint32_t val)
* mkBitVector(uint32_t size, uint64_t val)
* mkBitVector(const char* s, uint32_t base = 2)
* mkBitVector(std::string& s, uint32_t base = 2)
- * mkConst(Kind kind, const char* s, uint32_t base = 10)
- * mkConst(Kind kind, const std::string& s, uint32_t base = 10)
- * mkConst(Kind kind, uint32_t arg)
- * mkConst(Kind kind, uint32_t arg1, uint64_t arg2)
*/
CONST_BITVECTOR,
/**
@@ -1169,13 +1148,13 @@ enum CVC4_PUBLIC Kind : int32_t
* -[2]: Size of the significand
* -[3]: Value of the floating-point constant as a bit-vector term
* Create with:
- * mkConst(Kind kind, uint32_t arg1, uint32_t arg2, Term arg3)
+ * mkFloatingPoint(uint32_t sig, uint32_t exp, Term val)
*/
CONST_FLOATINGPOINT,
/**
* Floating-point rounding mode term.
* Create with:
- * mkConst(RoundingMode rm)
+ * mkRoundingMode(RoundingMode rm)
*/
CONST_ROUNDINGMODE,
/**
@@ -1833,7 +1812,6 @@ enum CVC4_PUBLIC Kind : int32_t
* -[1]: Sort of the set elements
* Create with:
* mkEmptySet(Sort sort)
- * mkConst(Sort sort)
*/
EMPTYSET,
/**
@@ -1922,7 +1900,6 @@ enum CVC4_PUBLIC Kind : int32_t
* All set variables must be interpreted as subsets of it.
* Create with:
* mkUniverseSet(Sort sort)
- * mkTerm(Kind kind, Sort sort)
*/
UNIVERSE_SET,
/**
@@ -2125,8 +2102,6 @@ enum CVC4_PUBLIC Kind : int32_t
* mkString(const std::string& s)
* mkString(const unsigned char c)
* mkString(const std::vector<unsigned>& s)
- * mkConst(Kind kind, const char* s)
- * mkConst(Kind kind, const std::string& s)
*/
CONST_STRING,
/**
diff --git a/src/options/CMakeLists.txt b/src/options/CMakeLists.txt
index b86db8d00..fc725978e 100644
--- a/src/options/CMakeLists.txt
+++ b/src/options/CMakeLists.txt
@@ -37,6 +37,8 @@ libcvc4_add_sources(
set_language.h
smt_modes.cpp
smt_modes.h
+ strings_process_loop_mode.cpp
+ strings_process_loop_mode.h
sygus_out_mode.h
theoryof_mode.cpp
theoryof_mode.h
diff --git a/src/options/bv_bitblast_mode.cpp b/src/options/bv_bitblast_mode.cpp
index 9cfa2d6d3..59a97c5a2 100644
--- a/src/options/bv_bitblast_mode.cpp
+++ b/src/options/bv_bitblast_mode.cpp
@@ -68,4 +68,17 @@ std::ostream& operator<<(std::ostream& out, theory::bv::SatSolverMode solver) {
return out;
}
+std::ostream& operator<<(std::ostream& out, theory::bv::BvProofFormat format)
+{
+ switch (format)
+ {
+ case theory::bv::BITVECTOR_PROOF_ER: out << "BITVECTOR_PROOF_ER"; break;
+ case theory::bv::BITVECTOR_PROOF_DRAT: out << "BITVECTOR_PROOF_DRAT"; break;
+ case theory::bv::BITVECTOR_PROOF_LRAT: out << "BITVECTOR_PROOF_LRAT"; break;
+ default: out << "BvProofFormat:UNKNOWN![" << unsigned(format) << "]";
+ }
+
+ return out;
+}
+
}/* CVC4 namespace */
diff --git a/src/options/bv_bitblast_mode.h b/src/options/bv_bitblast_mode.h
index 530632674..fa5791ac9 100644
--- a/src/options/bv_bitblast_mode.h
+++ b/src/options/bv_bitblast_mode.h
@@ -68,12 +68,33 @@ enum SatSolverMode
SAT_SOLVER_CADICAL,
}; /* enum SatSolver */
+/**
+ * When the BV solver does eager bitblasting backed by CryptoMiniSat, proofs
+ * can be written in a variety of formats.
+ */
+enum BvProofFormat
+{
+ /**
+ * Write extended resolution proofs.
+ */
+ BITVECTOR_PROOF_ER,
+ /**
+ * Write DRAT proofs.
+ */
+ BITVECTOR_PROOF_DRAT,
+ /**
+ * Write LRAT proofs.
+ */
+ BITVECTOR_PROOF_LRAT,
+};
+
}/* CVC4::theory::bv namespace */
}/* CVC4::theory namespace */
std::ostream& operator<<(std::ostream& out, theory::bv::BitblastMode mode);
std::ostream& operator<<(std::ostream& out, theory::bv::BvSlicerMode mode);
std::ostream& operator<<(std::ostream& out, theory::bv::SatSolverMode mode);
+std::ostream& operator<<(std::ostream& out, theory::bv::BvProofFormat format);
}/* CVC4 namespace */
diff --git a/src/options/bv_options.toml b/src/options/bv_options.toml
index 00290da7d..0422ae06f 100644
--- a/src/options/bv_options.toml
+++ b/src/options/bv_options.toml
@@ -3,6 +3,17 @@ name = "Bitvector theory"
header = "options/bv_options.h"
[[option]]
+ name = "bvProofFormat"
+ category = "expert"
+ long = "bv-proof-format=MODE"
+ type = "CVC4::theory::bv::BvProofFormat"
+ default = "CVC4::theory::bv::BITVECTOR_PROOF_LRAT"
+ handler = "stringToBvProofFormat"
+ predicates = ["satSolverEnabledBuild"]
+ includes = ["options/bv_bitblast_mode.h"]
+ help = "choose which UNSAT proof format to use, see --bv-sat-solver=help"
+
+[[option]]
name = "bvSatSolver"
smt_name = "bv-sat-solver"
category = "expert"
diff --git a/src/options/options_handler.cpp b/src/options/options_handler.cpp
index 36144e70e..32f77a09f 100644
--- a/src/options/options_handler.cpp
+++ b/src/options/options_handler.cpp
@@ -1203,6 +1203,48 @@ theory::bv::SatSolverMode OptionsHandler::stringToSatSolver(std::string option,
}
}
+const std::string OptionsHandler::s_bvProofFormatHelp =
+ "\
+Proof formats currently supported by the --bv-proof-format option:\n\
+\n\
+ lrat : DRAT with unit propagation hints to accelerate checking (default)\n\
+\n\
+ drat : Deletion and Resolution Asymmetric Tautology Additions \n\
+\n\
+ er : Extended Resolution, i.e. resolution with new variable definitions\n\
+\n\
+This option controls which underlying UNSAT proof format is used in BV proofs.\n\
+\n\
+Note: Currently this option does nothing. BV proofs are a work in progress!\
+";
+
+theory::bv::BvProofFormat OptionsHandler::stringToBvProofFormat(
+ std::string option, std::string optarg)
+{
+ if (optarg == "er")
+ {
+ return theory::bv::BITVECTOR_PROOF_ER;
+ }
+ else if (optarg == "lrat")
+ {
+ return theory::bv::BITVECTOR_PROOF_LRAT;
+ }
+ else if (optarg == "drat")
+ {
+ return theory::bv::BITVECTOR_PROOF_DRAT;
+ }
+ else if (optarg == "help")
+ {
+ puts(s_bvProofFormatHelp.c_str());
+ exit(1);
+ }
+ else
+ {
+ throw OptionException(std::string("unknown option for --bv-proof-format: `")
+ + optarg + "'. Try --bv-proof-format=help.");
+ }
+}
+
const std::string OptionsHandler::s_bitblastingModeHelp = "\
Bit-blasting modes currently supported by the --bitblast option:\n\
\n\
@@ -1295,6 +1337,61 @@ theory::bv::BvSlicerMode OptionsHandler::stringToBvSlicerMode(
}
}
+const std::string OptionsHandler::s_stringToStringsProcessLoopModeHelp =
+ "Loop processing modes supported by the --strings-process-loop-mode "
+ "option:\n"
+ "\n"
+ "full (default)\n"
+ "+ Perform full processing of looping word equations\n"
+ "\n"
+ "simple\n"
+ "+ Omit normal loop breaking\n"
+ "\n"
+ "simple-abort\n"
+ "+ Abort when normal loop breaking is required\n"
+ "\n"
+ "none\n"
+ "+ Omit loop processing\n"
+ "\n"
+ "abort\n"
+ "+ Abort if looping word equations are encountered\n";
+
+theory::strings::ProcessLoopMode OptionsHandler::stringToStringsProcessLoopMode(
+ std::string option, std::string optarg)
+{
+ if (optarg == "full")
+ {
+ return theory::strings::ProcessLoopMode::FULL;
+ }
+ else if (optarg == "simple")
+ {
+ return theory::strings::ProcessLoopMode::SIMPLE;
+ }
+ else if (optarg == "simple-abort")
+ {
+ return theory::strings::ProcessLoopMode::SIMPLE_ABORT;
+ }
+ else if (optarg == "none")
+ {
+ return theory::strings::ProcessLoopMode::NONE;
+ }
+ else if (optarg == "abort")
+ {
+ return theory::strings::ProcessLoopMode::ABORT;
+ }
+ else if (optarg == "help")
+ {
+ puts(s_stringToStringsProcessLoopModeHelp.c_str());
+ exit(1);
+ }
+ else
+ {
+ throw OptionException(
+ std::string("unknown option for --strings-process-loop-mode: `")
+ + optarg + "'. Try --strings-process-loop-mode=help.");
+ }
+}
+
const std::string OptionsHandler::s_boolToBVModeHelp =
"\
BoolToBV pass modes supported by the --bool-to-bv option:\n\
diff --git a/src/options/options_handler.h b/src/options/options_handler.h
index f96632696..8b2629db7 100644
--- a/src/options/options_handler.h
+++ b/src/options/options_handler.h
@@ -37,6 +37,7 @@
#include "options/printer_modes.h"
#include "options/quantifiers_modes.h"
#include "options/smt_modes.h"
+#include "options/strings_process_loop_mode.h"
#include "options/sygus_out_mode.h"
#include "options/theoryof_mode.h"
#include "options/ufss_mode.h"
@@ -145,6 +146,12 @@ public:
theory::bv::SatSolverMode stringToSatSolver(std::string option,
std::string optarg);
+ theory::bv::BvProofFormat stringToBvProofFormat(std::string option,
+ std::string optarg);
+
+ theory::strings::ProcessLoopMode stringToStringsProcessLoopMode(
+ std::string option, std::string optarg);
+
// theory/uf/options_handlers.h
theory::uf::UfssMode stringToUfssMode(std::string option, std::string optarg);
@@ -230,8 +237,10 @@ public:
/* Help strings */
static const std::string s_bitblastingModeHelp;
static const std::string s_bvSatSolverHelp;
+ static const std::string s_bvProofFormatHelp;
static const std::string s_booleanTermConversionModeHelp;
static const std::string s_bvSlicerModeHelp;
+ static const std::string s_stringToStringsProcessLoopModeHelp;
static const std::string s_boolToBVModeHelp;
static const std::string s_cegqiFairModeHelp;
static const std::string s_decisionModeHelp;
diff --git a/src/options/strings_options.toml b/src/options/strings_options.toml
index 414a9cfa6..bc5fbedd6 100644
--- a/src/options/strings_options.toml
+++ b/src/options/strings_options.toml
@@ -129,22 +129,14 @@ header = "options/strings_options.h"
help = "check entailment between length terms to reduce splitting"
[[option]]
- name = "stringProcessLoop"
- category = "regular"
- long = "strings-process-loop"
- type = "bool"
- default = "true"
- read_only = true
- help = "reduce looping word equations to regular expressions"
-
-[[option]]
- name = "stringAbortLoop"
- category = "regular"
- long = "strings-abort-loop"
- type = "bool"
- default = "false"
- read_only = true
- help = "abort when a looping word equation is encountered"
+ name = "stringProcessLoopMode"
+ category = "expert"
+ long = "strings-process-loop-mode=MODE"
+ type = "CVC4::theory::strings::ProcessLoopMode"
+ default = "CVC4::theory::strings::ProcessLoopMode::FULL"
+ handler = "stringToStringsProcessLoopMode"
+ includes = ["options/strings_process_loop_mode.h"]
+ help = "choose how to process looping string equations, see --strings-process-loop-mode=help for details"
[[option]]
name = "stringInferAsLemmas"
diff --git a/src/options/strings_process_loop_mode.cpp b/src/options/strings_process_loop_mode.cpp
new file mode 100644
index 000000000..a1a81bbf3
--- /dev/null
+++ b/src/options/strings_process_loop_mode.cpp
@@ -0,0 +1,46 @@
+/********************* */
+/*! \file strings_process_loop_mode.cpp
+ ** \verbatim
+ ** 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
+ ** in the top-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 Modes for processing looping word equations in the string solver.
+ **
+ ** Modes for processing looping word equations in the string solver.
+ **/
+
+#include "options/strings_process_loop_mode.h"
+
+#include <iostream>
+
+namespace CVC4 {
+
+std::ostream& operator<<(std::ostream& out,
+ theory::strings::ProcessLoopMode mode)
+{
+ switch (mode)
+ {
+ case theory::strings::ProcessLoopMode::FULL:
+ out << "ProcessLoopMode::FULL";
+ break;
+ case theory::strings::ProcessLoopMode::SIMPLE:
+ out << "ProcessLoopMode::SIMPLE";
+ break;
+ case theory::strings::ProcessLoopMode::SIMPLE_ABORT:
+ out << "ProcessLoopMode::SIMPLE_ABORT";
+ break;
+ case theory::strings::ProcessLoopMode::NONE:
+ out << "ProcessLoopMode::NONE";
+ break;
+ case theory::strings::ProcessLoopMode::ABORT:
+ out << "ProcessLoopMode::ABORT";
+ break;
+ }
+}
+
+} // namespace CVC4
diff --git a/src/options/strings_process_loop_mode.h b/src/options/strings_process_loop_mode.h
new file mode 100644
index 000000000..2933e034f
--- /dev/null
+++ b/src/options/strings_process_loop_mode.h
@@ -0,0 +1,55 @@
+/********************* */
+/*! \file strings_process_loop_mode.h
+ ** \verbatim
+ ** 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
+ ** in the top-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 Modes for processing looping word equations in the string solver.
+ **
+ ** Modes for processing looping word equations in the string solver.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__STRINGS__PROCESS_LOOP_MODE_H
+#define __CVC4__THEORY__STRINGS__PROCESS_LOOP_MODE_H
+
+#include <iosfwd>
+
+namespace CVC4 {
+namespace theory {
+namespace strings {
+
+/** Enumeration of bit-blasting modes */
+enum class ProcessLoopMode
+{
+ /** Perform full loop processing. */
+ FULL,
+
+ /** Omit normal loop breaking. */
+ SIMPLE,
+
+ /** Abort if normal loop breaking is required. */
+ SIMPLE_ABORT,
+
+ /** Omit loop processing. */
+ NONE,
+
+ /** Abort if looping word equations are encountered. */
+ ABORT
+}; // enum ProcessLoopMode
+
+} // namespace strings
+} // namespace theory
+
+std::ostream& operator<<(std::ostream& out,
+ theory::strings::ProcessLoopMode mode);
+
+} // namespace CVC4
+
+#endif /* __CVC4__THEORY__BV__BITBLAST_MODE_H */
diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp
index 8ddefb2f4..71d226c98 100644
--- a/src/parser/parser.cpp
+++ b/src/parser/parser.cpp
@@ -81,6 +81,8 @@ ExprManager* Parser::getExprManager() const
return d_solver->getExprManager();
}
+api::Solver* Parser::getSolver() const { return d_solver; }
+
Expr Parser::getSymbol(const std::string& name, SymbolType type) {
checkDeclaration(name, CHECK_DECLARED, type);
assert(isDeclared(name, type));
diff --git a/src/parser/parser.h b/src/parser/parser.h
index f22fc3789..8c18055a7 100644
--- a/src/parser/parser.h
+++ b/src/parser/parser.h
@@ -269,6 +269,9 @@ public:
/** Get the associated <code>ExprManager</code>. */
ExprManager* getExprManager() const;
+ /** Get the associated solver. */
+ api::Solver* getSolver() const;
+
/** Get the associated input. */
inline Input* getInput() const {
return d_input;
diff --git a/src/parser/smt2/Smt2.g b/src/parser/smt2/Smt2.g
index 7143824d6..c72a4f99b 100644
--- a/src/parser/smt2/Smt2.g
+++ b/src/parser/smt2/Smt2.g
@@ -100,6 +100,10 @@ namespace CVC4 {
};/* struct myExpr */
}/* CVC4::parser::smt2 namespace */
}/* CVC4::parser namespace */
+
+ namespace api {
+ class Term;
+ }
}/* CVC4 namespace */
}/* @parser::includes */
@@ -112,6 +116,7 @@ namespace CVC4 {
#include <unordered_set>
#include <vector>
+#include "api/cvc4cpp.h"
#include "base/output.h"
#include "expr/expr.h"
#include "expr/kind.h"
@@ -141,6 +146,8 @@ using namespace CVC4::parser;
#define MK_EXPR EXPR_MANAGER->mkExpr
#undef MK_CONST
#define MK_CONST EXPR_MANAGER->mkConst
+#undef SOLVER
+#define SOLVER PARSER_STATE->getSolver()
#define UNSUPPORTED PARSER_STATE->unimplementedFeature
static bool isClosed(const Expr& e, std::set<Expr>& free, std::unordered_set<Expr, ExprHashFunction>& closedCache) {
@@ -878,7 +885,7 @@ sygusGTerm[CVC4::SygusGTerm& sgt, std::string& fun]
std::vector< Expr > let_vars;
bool readingLet = false;
std::string s;
- CVC4::Expr atomExpr;
+ CVC4::api::Term atomTerm;
}
: LPAREN_TOK
//read operator
@@ -973,15 +980,16 @@ sygusGTerm[CVC4::SygusGTerm& sgt, std::string& fun]
PARSER_STATE->popScope();
}
}
- | termAtomic[atomExpr] {
- Debug("parser-sygus") << "Sygus grammar " << fun << " : atomic "
- << "expression " << atomExpr << std::endl;
- std::stringstream ss;
- ss << atomExpr;
- sgt.d_expr = atomExpr;
- sgt.d_name = ss.str();
- sgt.d_gterm_type = SygusGTerm::gterm_op;
- }
+ | termAtomic[atomTerm]
+ {
+ Debug("parser-sygus") << "Sygus grammar " << fun << " : atomic "
+ << "expression " << atomTerm << std::endl;
+ std::stringstream ss;
+ ss << atomTerm;
+ sgt.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
@@ -1709,6 +1717,7 @@ termNonVariable[CVC4::Expr& expr, CVC4::Expr& expr2]
std::vector<Type> match_ptypes;
Type type;
Type type2;
+ api::Term atomTerm;
}
: /* a built-in operator application */
LPAREN_TOK builtinOp[kind] termList[args,expr] RPAREN_TOK
@@ -2207,19 +2216,17 @@ termNonVariable[CVC4::Expr& expr, CVC4::Expr& expr2]
| LPAREN_TOK TUPLE_CONST_TOK termList[args,expr] RPAREN_TOK
{
- std::vector<Type> types;
- for (std::vector<Expr>::const_iterator i = args.begin(); i != args.end();
- ++i)
+ std::vector<api::Sort> sorts;
+ std::vector<api::Term> terms;
+ for (const Expr& arg : args)
{
- types.push_back((*i).getType());
+ sorts.emplace_back(arg.getType());
+ terms.emplace_back(arg);
}
- DatatypeType t = EXPR_MANAGER->mkTupleType(types);
- const Datatype& dt = t.getDatatype();
- args.insert(args.begin(), dt[0].getConstructor());
- expr = MK_EXPR(kind::APPLY_CONSTRUCTOR, args);
+ expr = SOLVER->mkTuple(sorts, terms).getExpr();
}
| /* an atomic term (a term with no subterms) */
- termAtomic[expr]
+ termAtomic[atomTerm] { expr = atomTerm.getExpr(); }
;
@@ -2227,128 +2234,145 @@ termNonVariable[CVC4::Expr& expr, CVC4::Expr& expr2]
* Matches an atomic term (a term with no subterms).
* @return the expression expr representing the term or formula.
*/
-termAtomic[CVC4::Expr& expr]
+termAtomic[CVC4::api::Term& atomTerm]
@init {
- std::vector<Expr> args;
Type type;
Type type2;
std::string s;
}
/* constants */
: INTEGER_LITERAL
- { expr = MK_CONST( AntlrInput::tokenToInteger($INTEGER_LITERAL) ); }
-
+ {
+ std::string intStr = AntlrInput::tokenText($INTEGER_LITERAL);
+ atomTerm = SOLVER->mkReal(intStr);
+ }
| DECIMAL_LITERAL
- { // FIXME: This doesn't work because an SMT rational is not a
- // valid GMP rational string
- expr = MK_CONST( AntlrInput::tokenToRational($DECIMAL_LITERAL) );
- if(expr.getType().isInteger()) {
- // Must cast to Real to ensure correct type is passed to parametric type 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.
- expr = MK_EXPR(kind::DIVISION, expr, MK_CONST(Rational(1)));
- }
+ {
+ std::string realStr = AntlrInput::tokenText($DECIMAL_LITERAL);
+ atomTerm = SOLVER->ensureTermSort(SOLVER->mkReal(realStr),
+ SOLVER->getRealSort());
}
+ // Pi constant
+ | REAL_PI_TOK { atomTerm = SOLVER->mkPi(); }
+
+ // Constants using indexed identifiers, e.g. (_ +oo 8 24) (positive infinity
+ // as a 32-bit floating-point constant)
| LPAREN_TOK INDEX_TOK
( bvLit=SIMPLE_SYMBOL size=INTEGER_LITERAL
- { if(AntlrInput::tokenText($bvLit).find("bv") == 0) {
- expr = MK_CONST( AntlrInput::tokenToBitvector($bvLit, $size) );
- } else {
+ {
+ if(AntlrInput::tokenText($bvLit).find("bv") == 0)
+ {
+ std::string bvStr = AntlrInput::tokenTextSubstr($bvLit, 2);
+ uint32_t bvSize = AntlrInput::tokenToUnsigned($size);
+ atomTerm = SOLVER->mkBitVector(bvSize, bvStr, 10);
+ }
+ else
+ {
PARSER_STATE->parseError("Unexpected symbol `" +
AntlrInput::tokenText($bvLit) + "'");
}
}
+
+ // Floating-point constants
| FP_PINF_TOK eb=INTEGER_LITERAL sb=INTEGER_LITERAL
- { expr = MK_CONST(FloatingPoint::makeInf(FloatingPointSize(AntlrInput::tokenToUnsigned($eb),
- AntlrInput::tokenToUnsigned($sb)),
- false)); }
+ {
+ atomTerm = SOLVER->mkPosInf(AntlrInput::tokenToUnsigned($eb),
+ AntlrInput::tokenToUnsigned($sb));
+ }
| FP_NINF_TOK eb=INTEGER_LITERAL sb=INTEGER_LITERAL
- { expr = MK_CONST(FloatingPoint::makeInf(FloatingPointSize(AntlrInput::tokenToUnsigned($eb),
- AntlrInput::tokenToUnsigned($sb)),
- true)); }
+ {
+ atomTerm = SOLVER->mkNegInf(AntlrInput::tokenToUnsigned($eb),
+ AntlrInput::tokenToUnsigned($sb));
+ }
| FP_NAN_TOK eb=INTEGER_LITERAL sb=INTEGER_LITERAL
- { expr = MK_CONST(FloatingPoint::makeNaN(FloatingPointSize(AntlrInput::tokenToUnsigned($eb),
- AntlrInput::tokenToUnsigned($sb)))); }
-
+ {
+ atomTerm = SOLVER->mkNaN(AntlrInput::tokenToUnsigned($eb),
+ AntlrInput::tokenToUnsigned($sb));
+ }
| FP_PZERO_TOK eb=INTEGER_LITERAL sb=INTEGER_LITERAL
- { expr = MK_CONST(FloatingPoint::makeZero(FloatingPointSize(AntlrInput::tokenToUnsigned($eb),
- AntlrInput::tokenToUnsigned($sb)),
- false)); }
+ {
+ atomTerm = SOLVER->mkPosZero(AntlrInput::tokenToUnsigned($eb),
+ AntlrInput::tokenToUnsigned($sb));
+ }
| FP_NZERO_TOK eb=INTEGER_LITERAL sb=INTEGER_LITERAL
- { expr = MK_CONST(FloatingPoint::makeZero(FloatingPointSize(AntlrInput::tokenToUnsigned($eb),
- AntlrInput::tokenToUnsigned($sb)),
- true)); }
+ {
+ atomTerm = SOLVER->mkNegZero(AntlrInput::tokenToUnsigned($eb),
+ AntlrInput::tokenToUnsigned($sb));
+ }
+
+ // Empty heap constant in seperation logic
| EMP_TOK
sortSymbol[type,CHECK_DECLARED]
sortSymbol[type2,CHECK_DECLARED]
{
- Expr v1 = PARSER_STATE->mkVar("_emp1", type);
- Expr v2 = PARSER_STATE->mkVar("_emp2", type2);
- expr = MK_EXPR(kind::SEP_EMP,v1,v2);
+ api::Term v1 = SOLVER->mkVar("_emp1", api::Sort(type));
+ api::Term v2 = SOLVER->mkVar("_emp2", api::Sort(type2));
+ atomTerm = SOLVER->mkTerm(api::SEP_EMP, v1, v2);
}
- // NOTE: Theory parametric constants go here
+ // NOTE: Theory parametric constants go here
)
RPAREN_TOK
+ // Bit-vector constants
| HEX_LITERAL
- { assert( AntlrInput::tokenText($HEX_LITERAL).find("#x") == 0 );
- std::string hexString = AntlrInput::tokenTextSubstr($HEX_LITERAL, 2);
- expr = MK_CONST( BitVector(hexString, 16) ); }
-
- | BINARY_LITERAL
- { assert( AntlrInput::tokenText($BINARY_LITERAL).find("#b") == 0 );
- std::string binString = AntlrInput::tokenTextSubstr($BINARY_LITERAL, 2);
- expr = MK_CONST( BitVector(binString, 2) ); }
-
- | str[s,false]
- { expr = MK_CONST( ::CVC4::String(s, true) ); }
- | FP_RNE_TOK { expr = MK_CONST(roundNearestTiesToEven); }
- | FP_RNA_TOK { expr = MK_CONST(roundNearestTiesToAway); }
- | FP_RTP_TOK { expr = MK_CONST(roundTowardPositive); }
- | FP_RTN_TOK { expr = MK_CONST(roundTowardNegative); }
- | FP_RTZ_TOK { expr = MK_CONST(roundTowardZero); }
- | FP_RNE_FULL_TOK { expr = MK_CONST(roundNearestTiesToEven); }
- | FP_RNA_FULL_TOK { expr = MK_CONST(roundNearestTiesToAway); }
- | FP_RTP_FULL_TOK { expr = MK_CONST(roundTowardPositive); }
- | FP_RTN_FULL_TOK { expr = MK_CONST(roundTowardNegative); }
- | FP_RTZ_FULL_TOK { expr = MK_CONST(roundTowardZero); }
-
- | REAL_PI_TOK {
- expr = EXPR_MANAGER->mkNullaryOperator(EXPR_MANAGER->realType(), kind::PI);
+ {
+ assert(AntlrInput::tokenText($HEX_LITERAL).find("#x") == 0);
+ std::string hexStr = AntlrInput::tokenTextSubstr($HEX_LITERAL, 2);
+ atomTerm = SOLVER->mkBitVector(hexStr, 16);
}
-
- | RENOSTR_TOK
- { std::vector< Expr > nvec;
- expr = MK_EXPR( CVC4::kind::REGEXP_EMPTY, nvec );
+ | BINARY_LITERAL
+ {
+ assert(AntlrInput::tokenText($BINARY_LITERAL).find("#b") == 0);
+ std::string binStr = AntlrInput::tokenTextSubstr($BINARY_LITERAL, 2);
+ atomTerm = SOLVER->mkBitVector(binStr, 2);
+ }
+
+ // Floating-point rounding mode constants
+ | FP_RNE_TOK { atomTerm = SOLVER->mkRoundingMode(api::ROUND_NEAREST_TIES_TO_EVEN); }
+ | FP_RNA_TOK { atomTerm = SOLVER->mkRoundingMode(api::ROUND_NEAREST_TIES_TO_AWAY); }
+ | FP_RTP_TOK { atomTerm = SOLVER->mkRoundingMode(api::ROUND_TOWARD_POSITIVE); }
+ | FP_RTN_TOK { atomTerm = SOLVER->mkRoundingMode(api::ROUND_TOWARD_NEGATIVE); }
+ | FP_RTZ_TOK { atomTerm = SOLVER->mkRoundingMode(api::ROUND_TOWARD_ZERO); }
+ | FP_RNE_FULL_TOK { atomTerm = SOLVER->mkRoundingMode(api::ROUND_NEAREST_TIES_TO_EVEN); }
+ | FP_RNA_FULL_TOK { atomTerm = SOLVER->mkRoundingMode(api::ROUND_NEAREST_TIES_TO_AWAY); }
+ | FP_RTP_FULL_TOK { atomTerm = SOLVER->mkRoundingMode(api::ROUND_TOWARD_POSITIVE); }
+ | FP_RTN_FULL_TOK { atomTerm = SOLVER->mkRoundingMode(api::ROUND_TOWARD_NEGATIVE); }
+ | FP_RTZ_FULL_TOK { atomTerm = SOLVER->mkRoundingMode(api::ROUND_TOWARD_ZERO); }
+
+ // String constant
+ | str[s,false] { atomTerm = SOLVER->mkString(s, true); }
+
+ // Regular expression constants
+ | RENOSTR_TOK { atomTerm = SOLVER->mkRegexpEmpty(); }
+ | REALLCHAR_TOK { atomTerm = SOLVER->mkRegexpSigma(); }
+
+ // Set constants
+ | EMPTYSET_TOK { atomTerm = SOLVER->mkEmptySet(SOLVER->getNullSort()); }
+ | UNIVSET_TOK
+ {
+ // the Boolean sort is a placeholder here since we don't have type info
+ // without type annotation
+ atomTerm = SOLVER->mkUniverseSet(SOLVER->getBooleanSort());
}
- | REALLCHAR_TOK
- { std::vector< Expr > nvec;
- expr = MK_EXPR( CVC4::kind::REGEXP_SIGMA, nvec );
+ // Separation logic constants
+ | NILREF_TOK
+ {
+ // the Boolean sort is a placeholder here since we don't have type info
+ // without type annotation
+ atomTerm = SOLVER->mkSepNil(SOLVER->getBooleanSort());
}
- | EMPTYSET_TOK
- { expr = MK_CONST( ::CVC4::EmptySet(Type())); }
-
- | UNIVSET_TOK
- { //booleanType is placeholder here since we don't have type info without type annotation
- expr = EXPR_MANAGER->mkNullaryOperator(EXPR_MANAGER->booleanType(), kind::UNIVERSE_SET); }
-
- | NILREF_TOK
- { //booleanType is placeholder here since we don't have type info without type annotation
- expr = EXPR_MANAGER->mkNullaryOperator(EXPR_MANAGER->booleanType(), kind::SEP_NIL); }
- // NOTE: Theory constants go here
+ // NOTE: Theory constants go here
+ // Empty tuple constant
| TUPLE_CONST_TOK
- { std::vector<Type> types;
- DatatypeType t = EXPR_MANAGER->mkTupleType(types);
- const Datatype& dt = t.getDatatype();
- args.insert(args.begin(), dt[0].getConstructor());
- expr = MK_EXPR(kind::APPLY_CONSTRUCTOR, args);
+ {
+ atomTerm = SOLVER->mkTuple(std::vector<api::Sort>(),
+ std::vector<api::Term>());
}
-
;
/**
diff --git a/src/printer/cvc/cvc_printer.cpp b/src/printer/cvc/cvc_printer.cpp
index 6fa7eadeb..e6ff02f10 100644
--- a/src/printer/cvc/cvc_printer.cpp
+++ b/src/printer/cvc/cvc_printer.cpp
@@ -917,6 +917,7 @@ void CvcPrinter::toStream(
case kind::STRING_LENGTH:
out << "LENGTH";
break;
+ case kind::STRING_SUBSTR: out << "SUBSTR"; break;
default:
Warning() << "Kind printing not implemented for the case of " << n.getKind() << endl;
diff --git a/src/proof/arith_proof.cpp b/src/proof/arith_proof.cpp
index 1d51f99e1..0d2bb5be0 100644
--- a/src/proof/arith_proof.cpp
+++ b/src/proof/arith_proof.cpp
@@ -19,10 +19,14 @@
#include <memory>
#include <stack>
+#include "expr/node.h"
#include "proof/proof_manager.h"
#include "proof/theory_proof.h"
+#include "theory/arith/constraint_forward.h"
#include "theory/arith/theory_arith.h"
+#define CVC4_ARITH_VAR_TERM_PREFIX "term."
+
namespace CVC4 {
inline static Node eqNode(TNode n1, TNode n2) {
@@ -674,151 +678,169 @@ void LFSCArithProof::printOwnedTerm(Expr term, std::ostream& os, const ProofLetM
// !d_realMode <--> term.getType().isInteger()
Assert (theory::Theory::theoryOf(term) == theory::THEORY_ARITH);
- switch (term.getKind()) {
+ switch (term.getKind())
+ {
+ case kind::CONST_RATIONAL:
+ {
+ Assert(term.getNumChildren() == 0);
+ Assert(term.getType().isInteger() || term.getType().isReal());
- case kind::CONST_RATIONAL: {
- Assert (term.getNumChildren() == 0);
- Assert (term.getType().isInteger() || term.getType().isReal());
+ const Rational& r = term.getConst<Rational>();
+ bool neg = (r < 0);
- const Rational& r = term.getConst<Rational>();
- bool neg = (r < 0);
+ os << (!d_realMode ? "(a_int " : "(a_real ");
- os << (!d_realMode ? "(a_int " : "(a_real ");
+ if (neg)
+ {
+ os << "(~ ";
+ }
- if (neg) {
- os << "(~ ";
- }
+ if (!d_realMode)
+ {
+ os << r.abs();
+ }
+ else
+ {
+ printRational(os, r.abs());
+ }
- if (!d_realMode) {
- os << r.abs();
- } else {
- os << r.abs().getNumerator();
- os << "/";
- os << r.getDenominator();
+ if (neg)
+ {
+ os << ") ";
+ }
+
+ os << ") ";
+ return;
}
- if (neg) {
+ case kind::UMINUS:
+ {
+ Assert(term.getNumChildren() == 1);
+ Assert(term.getType().isInteger() || term.getType().isReal());
+ os << (!d_realMode ? "(u-_Int " : "(u-_Real ");
+ d_proofEngine->printBoundTerm(term[0], os, map);
os << ") ";
+ return;
}
- os << ") ";
- return;
- }
+ case kind::PLUS:
+ {
+ Assert(term.getNumChildren() >= 2);
- case kind::UMINUS: {
- Assert (term.getNumChildren() == 1);
- Assert (term.getType().isInteger() || term.getType().isReal());
- os << (!d_realMode ? "(u-_Int " : "(u-_Real ");
- d_proofEngine->printBoundTerm(term[0], os, map);
- os << ") ";
- return;
- }
+ std::stringstream paren;
+ for (unsigned i = 0; i < term.getNumChildren() - 1; ++i)
+ {
+ os << (!d_realMode ? "(+_Int " : "(+_Real ");
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ os << " ";
+ paren << ") ";
+ }
- case kind::PLUS: {
- Assert (term.getNumChildren() >= 2);
+ d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
+ os << paren.str();
+ return;
+ }
- std::stringstream paren;
- for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
- os << (!d_realMode ? "(+_Int " : "(+_Real ");
- d_proofEngine->printBoundTerm(term[i], os, map);
- os << " ";
- paren << ") ";
+ case kind::MINUS:
+ {
+ Assert(term.getNumChildren() >= 2);
+
+ std::stringstream paren;
+ for (unsigned i = 0; i < term.getNumChildren() - 1; ++i)
+ {
+ os << (!d_realMode ? "(-_Int " : "(-_Real ");
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ os << " ";
+ paren << ") ";
+ }
+
+ d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
+ os << paren.str();
+ return;
}
- d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
- os << paren.str();
- return;
- }
+ case kind::MULT:
+ {
+ Assert(term.getNumChildren() >= 2);
- case kind::MINUS: {
- Assert (term.getNumChildren() >= 2);
+ std::stringstream paren;
+ for (unsigned i = 0; i < term.getNumChildren() - 1; ++i)
+ {
+ os << (!d_realMode ? "(*_Int " : "(*_Real ");
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ os << " ";
+ paren << ") ";
+ }
- std::stringstream paren;
- for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
- os << (!d_realMode ? "(-_Int " : "(-_Real ");
- d_proofEngine->printBoundTerm(term[i], os, map);
- os << " ";
- paren << ") ";
+ d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
+ os << paren.str();
+ return;
}
- d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
- os << paren.str();
- return;
- }
+ case kind::DIVISION:
+ case kind::DIVISION_TOTAL:
+ {
+ Assert(term.getNumChildren() >= 2);
- case kind::MULT: {
- Assert (term.getNumChildren() >= 2);
+ std::stringstream paren;
+ for (unsigned i = 0; i < term.getNumChildren() - 1; ++i)
+ {
+ os << (!d_realMode ? "(/_Int " : "(/_Real ");
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ os << " ";
+ paren << ") ";
+ }
- std::stringstream paren;
- for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
- os << (!d_realMode ? "(*_Int " : "(*_Real ");
- d_proofEngine->printBoundTerm(term[i], os, map);
- os << " ";
- paren << ") ";
+ d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
+ os << paren.str();
+ return;
}
- d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
- os << paren.str();
- return;
- }
+ case kind::GT:
+ Assert(term.getNumChildren() == 2);
+ os << (!d_realMode ? "(>_Int " : "(>_Real ");
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os << " ";
+ d_proofEngine->printBoundTerm(term[1], os, map);
+ os << ") ";
+ return;
- case kind::DIVISION:
- case kind::DIVISION_TOTAL: {
- Assert (term.getNumChildren() >= 2);
+ case kind::GEQ:
+ Assert(term.getNumChildren() == 2);
+ os << (!d_realMode ? "(>=_Int " : "(>=_Real ");
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os << " ";
+ d_proofEngine->printBoundTerm(term[1], os, map);
+ os << ") ";
+ return;
- std::stringstream paren;
- for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
- os << (!d_realMode ? "(/_Int " : "(/_Real ");
- d_proofEngine->printBoundTerm(term[i], os, map);
+ case kind::LT:
+ Assert(term.getNumChildren() == 2);
+ os << (!d_realMode ? "(<_Int " : "(<_Real ");
+ d_proofEngine->printBoundTerm(term[0], os, map);
os << " ";
- paren << ") ";
- }
+ d_proofEngine->printBoundTerm(term[1], os, map);
+ os << ") ";
+ return;
- d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
- os << paren.str();
- return;
- }
+ case kind::LEQ:
+ Assert(term.getNumChildren() == 2);
+ os << (!d_realMode ? "(<=_Int " : "(<=_Real ");
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os << " ";
+ d_proofEngine->printBoundTerm(term[1], os, map);
+ os << ") ";
+ return;
- case kind::GT:
- Assert (term.getNumChildren() == 2);
- os << (!d_realMode ? "(>_Int " : "(>_Real ");
- d_proofEngine->printBoundTerm(term[0], os, map);
- os << " ";
- d_proofEngine->printBoundTerm(term[1], os, map);
- os << ") ";
- return;
-
- case kind::GEQ:
- Assert (term.getNumChildren() == 2);
- os << (!d_realMode ? "(>=_Int " : "(>=_Real ");
- d_proofEngine->printBoundTerm(term[0], os, map);
- os << " ";
- d_proofEngine->printBoundTerm(term[1], os, map);
- os << ") ";
- return;
-
- case kind::LT:
- Assert (term.getNumChildren() == 2);
- os << (!d_realMode ? "(<_Int " : "(<_Real ");
- d_proofEngine->printBoundTerm(term[0], os, map);
- os << " ";
- d_proofEngine->printBoundTerm(term[1], os, map);
- os << ") ";
- return;
-
- case kind::LEQ:
- Assert (term.getNumChildren() == 2);
- os << (!d_realMode ? "(<=_Int " : "(<=_Real ");
- d_proofEngine->printBoundTerm(term[0], os, map);
- os << " ";
- d_proofEngine->printBoundTerm(term[1], os, map);
- os << ") ";
- return;
+ case kind::VARIABLE:
+ case kind::SKOLEM:
+ os << CVC4_ARITH_VAR_TERM_PREFIX << ProofManager::sanitize(term);
+ return;
- default:
- Debug("pf::arith") << "Default printing of term: " << term << std::endl;
- os << term;
- return;
+ default:
+ Debug("pf::arith") << "Default printing of term: " << term << std::endl;
+ os << term;
+ return;
}
}
@@ -833,26 +855,327 @@ void LFSCArithProof::printOwnedSort(Type type, std::ostream& os) {
}
}
-void LFSCArithProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map) {
- os << " ;; Arith Theory Lemma \n;;";
- for (unsigned i = 0; i < lemma.size(); ++i) {
- os << lemma[i] <<" ";
+void LFSCArithProof::printRational(std::ostream& o, const Rational& r)
+{
+ if (r.sgn() < 0)
+ {
+ o << "(~ " << r.getNumerator().abs() << "/" << r.getDenominator().abs()
+ << ")";
+ }
+ else
+ {
+ o << r.getNumerator() << "/" << r.getDenominator();
+ }
+}
+
+void LFSCArithProof::printLinearPolynomialNormalizer(std::ostream& o,
+ const Node& n)
+{
+ switch (n.getKind())
+ {
+ case kind::PLUS:
+ {
+ // Since our axioms are binary, but n may be n-ary, we rig up
+ // a right-associative tree.
+ size_t nchildren = n.getNumChildren();
+ for (size_t i = 0; i < nchildren; ++i)
+ {
+ if (i < nchildren - 1)
+ {
+ o << "\n (pn_+ _ _ _ _ _ ";
+ }
+ printLinearMonomialNormalizer(o, n[i]);
+ }
+ std::fill_n(std::ostream_iterator<char>(o), nchildren - 1, ')');
+ break;
+ }
+ case kind::MULT:
+ case kind::VARIABLE:
+ case kind::CONST_RATIONAL:
+ case kind::SKOLEM:
+ {
+ printLinearMonomialNormalizer(o, n);
+ break;
+ }
+ default:
+#ifdef CVC4_ASSERTIONS
+ std::ostringstream msg;
+ msg << "Invalid operation " << n.getKind() << " in linear polynomial";
+ Unreachable(msg.str().c_str());
+#endif // CVC4_ASSERTIONS
+ break;
+ }
+}
+
+void LFSCArithProof::printLinearMonomialNormalizer(std::ostream& o,
+ const Node& n)
+{
+ switch (n.getKind())
+ {
+ case kind::MULT: {
+#ifdef CVC4_ASSERTIONS
+ std::ostringstream s;
+ s << "node " << n << " is not a linear monomial";
+ s << " " << n[0].getKind() << " " << n[1].getKind();
+ Assert((n[0].getKind() == kind::CONST_RATIONAL
+ && (n[1].getKind() == kind::VARIABLE
+ || n[1].getKind() == kind::SKOLEM)),
+ s.str().c_str());
+#endif // CVC4_ASSERTIONS
+
+ o << "\n (pn_mul_c_L _ _ _ ";
+ printConstRational(o, n[0]);
+ o << " ";
+ printVariableNormalizer(o, n[1]);
+ o << ")";
+ break;
+ }
+ case kind::CONST_RATIONAL:
+ {
+ o << "\n (pn_const ";
+ printConstRational(o, n);
+ o << ")";
+ break;
+ }
+ case kind::VARIABLE:
+ case kind::SKOLEM:
+ {
+ o << "\n ";
+ printVariableNormalizer(o, n);
+ break;
+ }
+ default:
+#ifdef CVC4_ASSERTIONS
+ std::ostringstream msg;
+ msg << "Invalid operation " << n.getKind() << " in linear monomial";
+ Unreachable(msg.str().c_str());
+#endif // CVC4_ASSERTIONS
+ break;
+ }
+}
+
+void LFSCArithProof::printConstRational(std::ostream& o, const Node& n)
+{
+ Assert(n.getKind() == kind::CONST_RATIONAL);
+ const Rational value = n.getConst<Rational>();
+ printRational(o, value);
+}
+
+void LFSCArithProof::printVariableNormalizer(std::ostream& o, const Node& n)
+{
+ std::ostringstream msg;
+ msg << "Invalid variable kind " << n.getKind() << " in linear monomial";
+ Assert(n.getKind() == kind::VARIABLE || n.getKind() == kind::SKOLEM,
+ msg.str().c_str());
+ o << "(pn_var " << n << ")";
+}
+
+void LFSCArithProof::printLinearPolynomialPredicateNormalizer(std::ostream& o,
+ const Node& n)
+{
+ Assert(n.getKind() == kind::GEQ,
+ "can only print normalization witnesses for (>=) nodes");
+ Assert(n[1].getKind() == kind::CONST_RATIONAL);
+ o << "(poly_formula_norm_>= _ _ _ ";
+ o << "\n (pn_- _ _ _ _ _ ";
+ printLinearPolynomialNormalizer(o, n[0]);
+ o << "\n (pn_const ";
+ printConstRational(o, n[1]);
+ o << ")))";
+}
+
+void LFSCArithProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
+ std::ostream& os,
+ std::ostream& paren,
+ const ProofLetMap& map)
+{
+ Debug("pf::arith") << "Printing proof for lemma " << lemma << std::endl;
+ // Prefixes for the names of linearity witnesses
+ const char* linearityWitnessPrefix = "lp";
+ const char* linearizedProofPrefix = "pf_lp";
+ std::ostringstream lemmaParen;
+
+ // Construct the set of conflicting literals
+ std::set<Node> conflictSet;
+ std::transform(lemma.begin(),
+ lemma.end(),
+ std::inserter(conflictSet, conflictSet.begin()),
+ [](const Expr& e) {
+ return NodeManager::currentNM()->fromExpr(e).negate();
+ });
+
+ // If we have Farkas coefficients stored for this lemma, use them to write a
+ // proof. Otherwise, just `trust` the lemma.
+ if (d_recorder.hasFarkasCoefficients(conflictSet))
+ {
+ // Get farkas coefficients & literal order
+ const auto& farkasInfo = d_recorder.getFarkasCoefficients(conflictSet);
+ const Node& conflict = farkasInfo.first;
+ theory::arith::RationalVectorCP farkasCoefficients = farkasInfo.second;
+ Assert(farkasCoefficients != theory::arith::RationalVectorCPSentinel);
+ Assert(conflict.getNumChildren() == farkasCoefficients->size());
+ const size_t nAntecedents = conflict.getNumChildren();
+
+ // Print proof
+ os << "\n;; Farkas Proof" << std::endl;
+
+ // Construct witness that the literals are linear polynomials
+ os << "; Linear Polynomial Normalization Witnesses" << std::endl;
+ for (size_t i = 0; i != nAntecedents; ++i)
+ {
+ const Node& antecedent = conflict[i];
+ const Rational farkasC = (*farkasCoefficients)[i];
+ os << "\n; " << antecedent << " w/ farkas c = " << farkasC << std::endl;
+ os << " (@ "
+ << ProofManager::getLitName(antecedent.negate(),
+ linearityWitnessPrefix)
+ << " ";
+ const Node& nonneg =
+ antecedent.getKind() == kind::NOT ? antecedent[0] : antecedent;
+ printLinearPolynomialPredicateNormalizer(os, nonneg);
+ lemmaParen << ")";
+ }
+
+ // Prove linear polynomial constraints
+ os << "\n; Linear Polynomial Proof Conversions";
+ for (size_t i = 0; i != nAntecedents; ++i)
+ {
+ const Node& antecedent = conflict[i];
+ os << "\n (@ "
+ << ProofManager::getLitName(antecedent.negate(), linearizedProofPrefix)
+ << " ";
+ lemmaParen << ")";
+ switch (conflict[i].getKind())
+ {
+ case kind::NOT:
+ {
+ Assert(conflict[i][0].getKind() == kind::GEQ);
+ os << "(poly_flip_not_>= _ _ "
+ << "(poly_form_not _ _ "
+ << ProofManager::getLitName(antecedent.negate(),
+ linearityWitnessPrefix)
+ << " " << ProofManager::getLitName(antecedent.negate(), "")
+ << "))";
+ break;
+ }
+ case kind::GEQ:
+ {
+ os << "(poly_form _ _ "
+ << ProofManager::getLitName(antecedent.negate(),
+ linearityWitnessPrefix)
+ << " " << ProofManager::getLitName(antecedent.negate(), "") << ")";
+ break;
+ }
+ default: Unreachable();
+ }
+ }
+
+ /* Combine linear polynomial constraints to derive a contradiction.
+ *
+ * The linear polynomial constraints are refered to as **antecedents**,
+ * since they are antecedents to the contradiction.
+ *
+ * The structure of the combination is a tree
+ *
+ * (=> <=)
+ * |
+ * + 0
+ * / \
+ * * + 1
+ * / \
+ * * + 2
+ * / \
+ * * ... i
+ * \
+ * + n-1
+ * / \
+ * * (0 >= 0)
+ *
+ * Where each * is a linearized antecedant being scaled by a farkas
+ * coefficient and each + is the sum of inequalities. The tricky bit is that
+ * each antecedent can be strict (>) or relaxed (>=) and the axiom used for
+ * each * and + depends on this... The axiom for * depends on the
+ * strictness of its linear polynomial input, and the axiom for + depends
+ * on the strictness of **both** its inputs. The contradiction axiom is
+ * also a function of the strictness of its input.
+ *
+ * There are n *s and +s and we precompute
+ * 1. The strictness of the ith antecedant (`ith_antecedent_is_strict`)
+ * 2. The strictness of the right argument of the ith sum
+ * (`ith_acc_is_strict`)
+ * 3. The strictness of the final result (`strict_contradiction`)
+ *
+ * Precomupation is helpful since
+ * the computation is post-order,
+ * but printing is pre-order.
+ */
+ std::vector<bool> ith_antecedent_is_strict(nAntecedents, false);
+ std::vector<bool> ith_acc_is_strict(nAntecedents, false);
+ for (int i = nAntecedents - 1; i >= 0; --i)
+ {
+ ith_antecedent_is_strict[i] = conflict[i].getKind() == kind::NOT;
+ if (i == (int)nAntecedents - 1)
+ {
+ ith_acc_is_strict[i] = false;
+ }
+ else
+ {
+ ith_acc_is_strict[i] =
+ ith_acc_is_strict[i + 1] || ith_antecedent_is_strict[i + 1];
+ }
+ }
+ bool strict_contradiction =
+ ith_acc_is_strict[0] || ith_antecedent_is_strict[0];
+
+ // Now, print the proof
+ os << "\n; Farkas Combination";
+ // Choose the appropriate contradiction axiom
+ os << "\n (lra_contra_" << (strict_contradiction ? ">" : ">=") << " _ ";
+ for (size_t i = 0; i != nAntecedents; ++i)
+ {
+ const Node& lit = conflict[i];
+ const char* ante_op = ith_antecedent_is_strict[i] ? ">" : ">=";
+ const char* acc_op = ith_acc_is_strict[i] ? ">" : ">=";
+ os << "\n (lra_add_" << ante_op << "_" << acc_op << " _ _ _ ";
+ os << "\n (lra_mul_c_" << ante_op << " _ _ ";
+ printRational(os, (*farkasCoefficients)[i].abs());
+ os << " " << ProofManager::getLitName(lit.negate(), linearizedProofPrefix)
+ << ")"
+ << " ; " << lit;
+ }
+
+ // The basis, at least, is always the same...
+ os << "\n (lra_axiom_>= 0/1)";
+ std::fill_n(std::ostream_iterator<char>(os),
+ nAntecedents,
+ ')'); // close lra_add_*_*
+ os << ")"; // close lra_contra_*
+
+ os << lemmaParen.str(); // close normalizers and proof-normalizers
+ }
+ else
+ {
+ os << "\n; Arithmetic proofs which use reasoning more complex than Farkas "
+ "proofs are currently unsupported\n(clausify_false trust)\n";
}
- os <<"\n";
- //os << " (clausify_false trust)";
- ArithProof::printTheoryLemmaProof(lemma, os, paren, map);
}
void LFSCArithProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
}
void LFSCArithProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
- for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
+ for (ExprSet::const_iterator it = d_declarations.begin();
+ it != d_declarations.end();
+ ++it)
+ {
Expr term = *it;
Assert(term.isVariable());
- os << "(% " << ProofManager::sanitize(term) << " ";
- os << "(term ";
- os << term.getType() << ")\n";
+ os << "(% " << ProofManager::sanitize(term) << " var_real\n";
+ os << "(@ " << CVC4_ARITH_VAR_TERM_PREFIX << ProofManager::sanitize(term)
+ << " ";
+ os << "(a_var_real " << ProofManager::sanitize(term) << ")\n";
+ paren << ")";
paren << ")";
}
}
diff --git a/src/proof/arith_proof.h b/src/proof/arith_proof.h
index a58294998..640d2db8d 100644
--- a/src/proof/arith_proof.h
+++ b/src/proof/arith_proof.h
@@ -64,7 +64,7 @@ protected:
ExprSet d_declarations; // all the variable/function declarations
/**
- * @brief Where farkas proofs of lemmas are stored.
+ * Where farkas proofs of lemmas are stored.
*/
proof::ArithProofRecorder d_recorder;
@@ -86,6 +86,76 @@ public:
std::ostream& os,
const ProofLetMap& map) override;
void printOwnedSort(Type type, std::ostream& os) override;
+
+ /**
+ * Print a rational number in LFSC format.
+ * e.g. 5/8 or (~ 1/1)
+ *
+ * @param o ostream to print to.
+ * @param r the rational to print
+ */
+ static void printRational(std::ostream& o, const Rational& r);
+
+ /**
+ * Print a value of type poly_formula_norm
+ *
+ * @param o ostream to print to
+ * @param n node (asserted to be of the form [linear polynomial >= constant])
+ */
+ static void printLinearPolynomialPredicateNormalizer(std::ostream& o,
+ const Node& n);
+
+ /**
+ * Print a value of type poly_norm
+ *
+ * @param o ostream to print to
+ * @param n node (asserted to be a linear polynomial)
+ */
+ static void printLinearPolynomialNormalizer(std::ostream& o, const Node& n);
+
+ /**
+ * Print a value of type poly_norm
+ *
+ * @param o ostream to print to
+ * @param n node (asserted to be a linear monomial)
+ */
+ static void printLinearMonomialNormalizer(std::ostream& o, const Node& n);
+
+ /**
+ * Print a LFSC rational
+ *
+ * @param o ostream to print to
+ * @param n node (asserted to be a const rational)
+ */
+ static void printConstRational(std::ostream& o, const Node& n);
+
+ /**
+ * print the pn_var normalizer for n (type poly_norm)
+ *
+ * @param o the ostream to print to
+ * @param n the node to print (asserted to be a variable)
+ */
+ static void printVariableNormalizer(std::ostream& o, const Node& n);
+ /**
+ * print a proof of the lemma
+ *
+ * First, we print linearity witnesses, i.e. witnesses that each literal has
+ * the form:
+ * [linear polynomial] >= 0 OR
+ * [linear polynomial] > 0
+ *
+ * Then we use those witnesses to prove that the above linearized constraints
+ * hold.
+ *
+ * Then we use the farkas coefficients to combine the literals into a
+ * variable-free contradiction. The literals may be a mix of strict and
+ * relaxed inequalities.
+ *
+ * @param lemma the set of literals disjoined in the lemma
+ * @param os stream to print the proof to
+ * @param paren global closing stream (unused)
+ * @param map let map (unused)
+ */
void printTheoryLemmaProof(std::vector<Expr>& lemma,
std::ostream& os,
std::ostream& paren,
diff --git a/src/proof/arith_proof_recorder.cpp b/src/proof/arith_proof_recorder.cpp
index d654ea073..097fdb51e 100644
--- a/src/proof/arith_proof_recorder.cpp
+++ b/src/proof/arith_proof_recorder.cpp
@@ -30,17 +30,25 @@ ArithProofRecorder::ArithProofRecorder() : d_lemmasToFarkasCoefficients()
void ArithProofRecorder::saveFarkasCoefficients(
Node conflict, theory::arith::RationalVectorCP farkasCoefficients)
{
+ // Verify that the conflict is a conjuction of (possibly negated) real bounds
+ // Verify that the conflict is a conjunciton ...
Assert(conflict.getKind() == kind::AND);
Assert(conflict.getNumChildren() == farkasCoefficients->size());
- for (size_t i = 0; i < conflict.getNumChildren(); ++i)
+ for (size_t i = 0, nchildren = conflict.getNumChildren(); i < nchildren; ++i)
{
const Node& child = conflict[i];
- Assert(child.getType().isBoolean() && child[0].getType().isReal());
+ // ... of possibly negated ...
+ const Node& nonNegativeChild =
+ child.getKind() == kind::NOT ? child[0] : child;
+ // ... real bounds
+ Assert(nonNegativeChild.getType().isBoolean()
+ && nonNegativeChild[0].getType().isReal());
}
Debug("pf::arith") << "Saved Farkas Coefficients:" << std::endl;
if (Debug.isOn("pf::arith"))
{
- for (size_t i = 0; i < conflict.getNumChildren(); ++i)
+ for (size_t i = 0, nchildren = conflict.getNumChildren(); i < nchildren;
+ ++i)
{
const Node& child = conflict[i];
const Rational& r = (*farkasCoefficients)[i];
diff --git a/src/proof/bitvector_proof.cpp b/src/proof/bitvector_proof.cpp
index ba3533cc3..90c0c9b30 100644
--- a/src/proof/bitvector_proof.cpp
+++ b/src/proof/bitvector_proof.cpp
@@ -18,10 +18,13 @@
#include "options/proof_options.h"
#include "proof/proof_output_channel.h"
#include "proof/theory_proof.h"
+#include "prop/sat_solver_types.h"
#include "theory/bv/bitblast/bitblaster.h"
#include "theory/bv/theory_bv.h"
namespace CVC4 {
+
+namespace proof {
BitVectorProof::BitVectorProof(theory::bv::TheoryBV* bv,
TheoryProofEngine* proofEngine)
: TheoryProof(bv, proofEngine),
@@ -118,13 +121,6 @@ std::string BitVectorProof::getBBTermName(Expr expr)
return os.str();
}
-void BitVectorProof::initCnfProof(prop::CnfStream* cnfStream,
- context::Context* cnf)
-{
- Assert(d_cnfProof == nullptr);
- d_cnfProof.reset(new LFSCCnfProof(cnfStream, cnf, "bb"));
-}
-
void BitVectorProof::printOwnedTerm(Expr term,
std::ostream& os,
const ProofLetMap& map)
@@ -709,6 +705,8 @@ void BitVectorProof::printBitblasting(std::ostream& os, std::ostream& paren)
}
}
+theory::TheoryId BitVectorProof::getTheoryId() { return theory::THEORY_BV; }
+
const std::set<Node>* BitVectorProof::getAtomsInBitblastingProof()
{
return &d_atomsInBitblastingProof;
@@ -774,4 +772,6 @@ void BitVectorProof::printRewriteProof(std::ostream& os,
os << ")";
}
+} // namespace proof
+
} // namespace CVC4
diff --git a/src/proof/bitvector_proof.h b/src/proof/bitvector_proof.h
index 466efa6a7..4b897a6c6 100644
--- a/src/proof/bitvector_proof.h
+++ b/src/proof/bitvector_proof.h
@@ -24,14 +24,28 @@
#include <unordered_map>
#include <unordered_set>
#include <vector>
+
#include "expr/expr.h"
#include "proof/cnf_proof.h"
#include "proof/theory_proof.h"
-#include "theory/bv/bitblast/bitblaster.h"
+#include "prop/sat_solver.h"
#include "theory/bv/theory_bv.h"
+// Since TBitblaster and BitVectorProof are cyclically dependent, we need this
+// forward declaration
+namespace CVC4 {
+namespace theory {
+namespace bv {
+template <class T>
+class TBitblaster;
+}
+} // namespace theory
+} // namespace CVC4
+
namespace CVC4 {
+namespace proof {
+
typedef std::unordered_set<Expr, ExprHashFunction> ExprSet;
typedef std::unordered_map<Expr, ClauseId, ExprHashFunction> ExprToClauseId;
typedef std::unordered_map<Expr, unsigned, ExprHashFunction> ExprToId;
@@ -118,6 +132,8 @@ class BitVectorProof : public TheoryProof
*/
std::unique_ptr<CnfProof> d_cnfProof;
+ theory::TheoryId getTheoryId() override;
+
public:
void printOwnedTerm(Expr term,
std::ostream& os,
@@ -132,6 +148,28 @@ class BitVectorProof : public TheoryProof
virtual void calculateAtomsInBitblastingProof() = 0;
/**
+ * Prints out a declaration of the bit-blasting, and the subsequent
+ * conversion of the result to CNF
+ *
+ * @param os the stream to print to
+ * @param paren a stream that will be placed at the back of the proof (for
+ * closing parens)
+ * @param letMap The let-map, which contains information about LFSC
+ * identifiers and the values they reference.
+ */
+ virtual void printBBDeclarationAndCnf(std::ostream& os,
+ std::ostream& paren,
+ ProofLetMap& letMap) = 0;
+
+ /**
+ * Prints a proof of the empty clause.
+ *
+ * @param os the stream to print to
+ * @param paren any parentheses to add to the end of the global proof
+ */
+ virtual void printEmptyClauseProof(std::ostream& os, std::ostream& paren) = 0;
+
+ /**
* Read the d_atomsInBitblastingProof member.
* See its documentation.
*/
@@ -153,13 +191,41 @@ class BitVectorProof : public TheoryProof
/**
* This must be done before registering any terms or atoms, since the CNF
* proof must reflect the result of bitblasting those
+ *
+ * Feeds the SAT solver's true and false variables into the CNF stream.
*/
- virtual void initCnfProof(prop::CnfStream* cnfStream, context::Context* ctx);
+ virtual void initCnfProof(prop::CnfStream* cnfStream,
+ context::Context* cnf,
+ prop::SatVariable trueVar,
+ prop::SatVariable falseVar) = 0;
CnfProof* getCnfProof() { return d_cnfProof.get(); }
+ /**
+ * Attaches this BVP to the given SAT solver, initializing a SAT proof.
+ *
+ * This must be invoked before `initCnfProof` because a SAT proof must already
+ * exist to initialize a CNF proof.
+ */
+ virtual void attachToSatSolver(prop::SatSolver& sat_solver) = 0;
+
void setBitblaster(theory::bv::TBitblaster<Node>* bb);
+ /**
+ * Kind of a mess. Used for resulution-based BVP's, where in eager mode this
+ * must be invoked before printing a proof of the empty clause. In lazy mode
+ * the behavior and purpose are both highly unclear.
+ *
+ * This exists as a virtual method of BitVectorProof, and not
+ * ResolutionBitVectorProof, because the machinery that invokes it is
+ * high-level enough that it doesn't know the difference between clausal and
+ * resolution proofs.
+ *
+ * TODO(aozdemir) figure out what is going on and clean this up
+ * Issue: https://github.com/CVC4/CVC4/issues/2789
+ */
+ virtual void finalizeConflicts(std::vector<Expr>& conflicts){};
+
private:
ExprToString d_exprToVariableName;
@@ -206,6 +272,8 @@ class BitVectorProof : public TheoryProof
const Node& n2) override;
};
+} // namespace proof
+
}/* CVC4 namespace */
#endif /* __CVC4__BITVECTOR__PROOF_H */
diff --git a/src/proof/clausal_bitvector_proof.cpp b/src/proof/clausal_bitvector_proof.cpp
new file mode 100644
index 000000000..bb875d1d8
--- /dev/null
+++ b/src/proof/clausal_bitvector_proof.cpp
@@ -0,0 +1,115 @@
+/********************* */
+/*! \file clausal_bitvector_proof.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 Bitvector proof using the DRAT proof format
+ **
+ ** Contains DRAT-specific printing logic.
+ **/
+
+#include "cvc4_private.h"
+
+#include <algorithm>
+#include <iterator>
+#include <set>
+#include "options/bv_options.h"
+#include "proof/clausal_bitvector_proof.h"
+#include "proof/drat/drat_proof.h"
+#include "proof/lfsc_proof_printer.h"
+#include "theory/bv/theory_bv.h"
+
+namespace CVC4 {
+
+namespace proof {
+
+ClausalBitVectorProof::ClausalBitVectorProof(theory::bv::TheoryBV* bv,
+ TheoryProofEngine* proofEngine)
+ : BitVectorProof(bv, proofEngine), d_usedClauses(), d_binaryDratProof()
+{
+}
+
+void ClausalBitVectorProof::attachToSatSolver(prop::SatSolver& sat_solver)
+{
+ sat_solver.setClausalProofLog(this);
+}
+
+void ClausalBitVectorProof::initCnfProof(prop::CnfStream* cnfStream,
+ context::Context* cnf,
+ prop::SatVariable trueVar,
+ prop::SatVariable falseVar)
+{
+ Assert(d_cnfProof == nullptr);
+ d_cnfProof.reset(new LFSCCnfProof(cnfStream, cnf, "bb"));
+
+ // Create a clause which forces the true variable to be true, and register it
+ int trueClauseId = ClauseId(ProofManager::currentPM()->nextId());
+ // with the CNF proof
+ d_cnfProof->registerTrueUnitClause(trueClauseId);
+ // and with (this) bit-vector proof
+ prop::SatClause c{prop::SatLiteral(trueVar, false)};
+ registerUsedClause(trueClauseId, c);
+
+ // The same for false.
+ int falseClauseId = ClauseId(ProofManager::currentPM()->nextId());
+ d_cnfProof->registerFalseUnitClause(falseClauseId);
+ c[0] = prop::SatLiteral(falseVar, true);
+ registerUsedClause(falseClauseId, c);
+}
+
+void ClausalBitVectorProof::registerUsedClause(ClauseId id,
+ prop::SatClause& clause)
+{
+ d_usedClauses.emplace_back(
+ id, std::unique_ptr<prop::SatClause>(new prop::SatClause(clause)));
+};
+
+void ClausalBitVectorProof::calculateAtomsInBitblastingProof()
+{
+ if (Debug.isOn("bv::clausal"))
+ {
+ std::string serializedDratProof = d_binaryDratProof.str();
+ Debug("bv::clausal") << "binary DRAT proof byte count: "
+ << serializedDratProof.size() << std::endl;
+ Debug("bv::clausal") << "Parsing DRAT proof ... " << std::endl;
+ drat::DratProof dratProof =
+ drat::DratProof::fromBinary(serializedDratProof);
+
+ Debug("bv::clausal") << "Printing DRAT proof ... " << std::endl;
+ dratProof.outputAsText(Debug("bv::clausal"));
+ }
+ Unimplemented();
+}
+
+void LfscClausalBitVectorProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
+ std::ostream& os,
+ std::ostream& paren,
+ const ProofLetMap& map)
+{
+ Unreachable(
+ "Clausal bit-vector proofs should only be used in combination with eager "
+ "bitblasting, which **does not use theory lemmas**");
+}
+
+void LfscClausalBitVectorProof::printBBDeclarationAndCnf(std::ostream& os,
+ std::ostream& paren,
+ ProofLetMap& letMap)
+{
+ Unimplemented();
+}
+
+void LfscClausalBitVectorProof::printEmptyClauseProof(std::ostream& os,
+ std::ostream& paren)
+{
+ Unimplemented();
+}
+
+} // namespace proof
+
+}; // namespace CVC4
diff --git a/src/proof/clausal_bitvector_proof.h b/src/proof/clausal_bitvector_proof.h
new file mode 100644
index 000000000..85e409e0d
--- /dev/null
+++ b/src/proof/clausal_bitvector_proof.h
@@ -0,0 +1,97 @@
+/********************* */
+/*! \file clausal_bitvector_proof.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 Bitvector proof for clausal (DRAT/LRAT) formats
+ **
+ ** An internal string stream is hooked up to CryptoMiniSat, which spits out a
+ ** binary DRAT proof. Depending on which kind of proof we're going to turn
+ ** that into, we process it in different ways.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__PROOF__CLAUSAL_BITVECTOR_PROOF_H
+#define __CVC4__PROOF__CLAUSAL_BITVECTOR_PROOF_H
+
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "expr/expr.h"
+#include "proof/bitvector_proof.h"
+#include "proof/drat/drat_proof.h"
+#include "proof/lrat/lrat_proof.h"
+#include "proof/theory_proof.h"
+#include "prop/cnf_stream.h"
+#include "prop/sat_solver_types.h"
+#include "theory/bv/theory_bv.h"
+
+namespace CVC4 {
+
+namespace proof {
+
+class ClausalBitVectorProof : public BitVectorProof
+{
+ public:
+ ClausalBitVectorProof(theory::bv::TheoryBV* bv,
+ TheoryProofEngine* proofEngine);
+
+ ~ClausalBitVectorProof() = default;
+
+ void attachToSatSolver(prop::SatSolver& sat_solver) override;
+
+ void initCnfProof(prop::CnfStream* cnfStream,
+ context::Context* cnf,
+ prop::SatVariable trueVar,
+ prop::SatVariable falseVar) override;
+
+ std::ostream& getDratOstream() { return d_binaryDratProof; }
+
+ void registerUsedClause(ClauseId id, prop::SatClause& clause);
+
+ void calculateAtomsInBitblastingProof() override;
+
+ protected:
+ // A list of all clauses and their ids which are passed into the SAT solver
+ std::vector<std::pair<ClauseId, std::unique_ptr<prop::SatClause>>>
+ d_usedClauses;
+ // Stores the proof recieved from the SAT solver.
+ std::ostringstream d_binaryDratProof;
+};
+
+/**
+ * A representation of a clausal proof of a bitvector problem's UNSAT nature
+ */
+class LfscClausalBitVectorProof : public ClausalBitVectorProof
+{
+ public:
+ LfscClausalBitVectorProof(theory::bv::TheoryBV* bv,
+ TheoryProofEngine* proofEngine)
+ : ClausalBitVectorProof(bv, proofEngine)
+ {
+ // That's all!
+ }
+
+ void printTheoryLemmaProof(std::vector<Expr>& lemma,
+ std::ostream& os,
+ std::ostream& paren,
+ const ProofLetMap& map) override;
+ void printBBDeclarationAndCnf(std::ostream& os,
+ std::ostream& paren,
+ ProofLetMap& letMap) override;
+ void printEmptyClauseProof(std::ostream& os, std::ostream& paren) override;
+};
+
+} // namespace proof
+
+} // namespace CVC4
+
+#endif /* __CVC4__PROOF__CLAUSAL_BITVECTOR_PROOF_H */
diff --git a/src/proof/cnf_proof.cpp b/src/proof/cnf_proof.cpp
index 016198735..4e8d20162 100644
--- a/src/proof/cnf_proof.cpp
+++ b/src/proof/cnf_proof.cpp
@@ -105,6 +105,30 @@ void CnfProof::registerConvertedClause(ClauseId clause, bool explanation) {
setClauseDefinition(clause, current_expr);
}
+void CnfProof::registerTrueUnitClause(ClauseId clauseId)
+{
+ Node trueNode = NodeManager::currentNM()->mkConst<bool>(true);
+ pushCurrentAssertion(trueNode);
+ pushCurrentDefinition(trueNode);
+ registerConvertedClause(clauseId);
+ popCurrentAssertion();
+ popCurrentDefinition();
+ d_cnfStream->ensureLiteral(trueNode);
+ d_trueUnitClause = clauseId;
+}
+
+void CnfProof::registerFalseUnitClause(ClauseId clauseId)
+{
+ Node falseNode = NodeManager::currentNM()->mkConst<bool>(false).notNode();
+ pushCurrentAssertion(falseNode);
+ pushCurrentDefinition(falseNode);
+ registerConvertedClause(clauseId);
+ popCurrentAssertion();
+ popCurrentDefinition();
+ d_cnfStream->ensureLiteral(falseNode);
+ d_falseUnitClause = clauseId;
+}
+
void CnfProof::setClauseAssertion(ClauseId clause, Node expr) {
Debug("proof:cnf") << "CnfProof::setClauseAssertion "
<< clause << " assertion " << expr << std::endl;
diff --git a/src/proof/cnf_proof.h b/src/proof/cnf_proof.h
index 32833d9a1..78ddeebd0 100644
--- a/src/proof/cnf_proof.h
+++ b/src/proof/cnf_proof.h
@@ -78,6 +78,11 @@ protected:
ClauseIdSet d_explanations;
+ // The clause ID of the unit clause defining the true SAT literal.
+ ClauseId d_trueUnitClause;
+ // The clause ID of the unit clause defining the false SAT literal.
+ ClauseId d_falseUnitClause;
+
bool isDefinition(Node node);
Node getDefinitionForClause(ClauseId clause);
@@ -110,6 +115,14 @@ public:
// already in CNF
void registerConvertedClause(ClauseId clause, bool explanation=false);
+ // The CNF proof has a special relationship to true and false.
+ // In particular, it need to know the identity of clauses defining
+ // canonical true and false literals in the underlying SAT solver.
+ void registerTrueUnitClause(ClauseId clauseId);
+ void registerFalseUnitClause(ClauseId clauseId);
+ inline ClauseId getTrueUnitClause() { return d_trueUnitClause; };
+ inline ClauseId getFalseUnitClause() { return d_falseUnitClause; };
+
/** Clause is one of the clauses defining the node expression*/
void setClauseDefinition(ClauseId clause, Node node);
diff --git a/src/proof/drat/drat_proof.cpp b/src/proof/drat/drat_proof.cpp
new file mode 100644
index 000000000..c2f2fa49e
--- /dev/null
+++ b/src/proof/drat/drat_proof.cpp
@@ -0,0 +1,287 @@
+/********************* */
+/*! \file drat_proof.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Alex Ozdemir
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief DRAT Proof Format
+ **
+ ** Defines deserialization for DRAT proofs.
+ **/
+
+#include "proof/drat/drat_proof.h"
+
+#include <algorithm>
+#include <bitset>
+#include <iostream>
+
+#include "proof/proof_manager.h"
+
+namespace CVC4 {
+namespace proof {
+namespace drat {
+
+// helper functions for parsing the binary DRAT format.
+
+/**
+ * Parses a binary literal which starts at `start` and must not go beyond `end`
+ *
+ * Leaves the iterator one past the last byte that is a part of the clause.
+ *
+ * If the literal overruns `end`, then raises a `InvalidDratProofException`.
+ */
+SatLiteral parse_binary_literal(std::string::const_iterator& start,
+ const std::string::const_iterator& proof_end)
+{
+ // lit is encoded as uint represented by a variable-length byte sequence
+ uint64_t literal_represented_as_uint = 0;
+ for (uint8_t shift = 0; start != proof_end; ++start, shift += 7)
+ {
+ // Check whether shift is so large that we're going to lose some
+ // information
+ if (shift + 7 >= 64)
+ {
+ throw InvalidDratProofException(
+ "While parsing a DRAT proof, encountered a literal that was too "
+ "long");
+ }
+ unsigned char byte = *start;
+ // The MSB of the byte is an indicator of whether the sequence continues
+ bool continued = (byte >> 7) & 1;
+ uint64_t numeric_part = byte & 0x7f;
+ literal_represented_as_uint |= numeric_part << shift;
+ if (!continued)
+ {
+ // LSB of `literal_represented_as_uint` indicates negation.
+ bool negated = literal_represented_as_uint & 1;
+ // Rest is the literal number
+ SatVariable var_number = literal_represented_as_uint >> 1;
+ ++start;
+ // Internal clauses start at 0, external ones start at 1.
+ return SatLiteral(var_number - 1, negated);
+ }
+ }
+ throw InvalidDratProofException(
+ "Literal in DRAT proof was not done when "
+ "EOF was encountered");
+}
+
+/**
+ * Parses a binary clause which starts at `start` and must not go beyond `end`
+ *
+ * Leaves the iterator one past the last byte that is a part of the clause.
+ * That is, one past the null byte.
+ *
+ * If the clause overruns `end`, then raises a `InvalidDratProofException`.
+ */
+SatClause parse_binary_clause(std::string::const_iterator& start,
+ const std::string::const_iterator& proof_end)
+{
+ SatClause clause;
+ // A clause is a 0-terminated sequence of literals
+ while (start != proof_end)
+ {
+ // Is the clause done?
+ if (*start == 0)
+ {
+ ++start;
+ return clause;
+ }
+ else
+ {
+ // If not, parse another literal
+ clause.emplace_back(parse_binary_literal(start, proof_end));
+ }
+ }
+ // We've overrun the end of the byte stream.
+ throw InvalidDratProofException(
+ "Clause in DRAT proof was not done when "
+ "EOF was encountered");
+}
+
+/**
+ * Writes this SAT literal in the textual DIMACS format. i.e. as a non-zero
+ * integer.
+ *
+ * Since internally +0 and -0 are valid literals, we add one to each
+ * literal's number (SAT variable) when outputtting it.
+ *
+ * @param os the stream to write to
+ * @param l the literal to write
+ */
+void outputLiteralAsDimacs(std::ostream& os, SatLiteral l)
+{
+ if (l.isNegated())
+ {
+ os << '-';
+ }
+ // add 1 to convert between internal literals and their DIMACS
+ // representaations.
+ os << l.getSatVariable() + 1;
+}
+
+// DratInstruction implementation
+
+DratInstruction::DratInstruction(DratInstructionKind kind, SatClause clause)
+ : d_kind(kind), d_clause(clause)
+{
+ // All intialized
+}
+
+void DratInstruction::outputAsText(std::ostream& os) const
+{
+ switch (d_kind)
+ {
+ case DratInstructionKind::ADDITION:
+ {
+ for (const SatLiteral& l : d_clause)
+ {
+ outputLiteralAsDimacs(os, l);
+ os << ' ';
+ }
+ os << '0' << std::endl;
+ break;
+ }
+ case DratInstructionKind::DELETION:
+ {
+ os << "d ";
+ for (const SatLiteral& l : d_clause)
+ {
+ outputLiteralAsDimacs(os, l);
+ os << ' ';
+ }
+ os << '0' << std::endl;
+ break;
+ }
+ default: { Unreachable("Unknown DRAT instruction kind");
+ }
+ }
+}
+
+// DratProof implementation
+
+DratProof::DratProof() : d_instructions() {}
+
+// See the "binary format" section of
+// https://www.cs.utexas.edu/~marijn/drat-trim/
+DratProof DratProof::fromBinary(const std::string& s)
+{
+ DratProof proof;
+ if (Debug.isOn("pf::drat"))
+ {
+ Debug("pf::drat") << "Parsing binary DRAT proof" << std::endl;
+ Debug("pf::drat") << "proof length: " << s.length() << " bytes"
+ << std::endl;
+ Debug("pf::drat") << "proof as bytes: ";
+ for (char i : s)
+ {
+ if (i == 'a' || i == 'd')
+ {
+ Debug("pf::drat") << std::endl << " " << std::bitset<8>(i);
+ }
+ else
+ {
+ Debug("pf::drat") << " " << std::bitset<8>(i);
+ }
+ }
+ Debug("pf::drat") << std::endl << "parsing proof..." << std::endl;
+ }
+
+ // For each instruction
+ for (auto i = s.cbegin(), end = s.cend(); i != end;)
+ {
+ switch (*i)
+ {
+ case 'a':
+ {
+ ++i;
+ proof.d_instructions.emplace_back(ADDITION,
+ parse_binary_clause(i, end));
+ break;
+ }
+ case 'd':
+ {
+ ++i;
+ proof.d_instructions.emplace_back(DELETION,
+ parse_binary_clause(i, end));
+ break;
+ }
+ default:
+ {
+ std::ostringstream s;
+ s << "Invalid instruction in Drat proof. Instruction bits: "
+ << std::bitset<8>(*i)
+ << ". Expected 'a' (01100001) or 'd' "
+ "(01100100).";
+ throw InvalidDratProofException(s.str());
+ }
+ }
+ }
+
+ if (Debug.isOn("pf::drat"))
+ {
+ Debug("pf::drat") << "Printing out DRAT in textual format:" << std::endl;
+ proof.outputAsText(Debug("pf::drat"));
+ }
+
+ return proof;
+};
+
+const std::vector<DratInstruction>& DratProof::getInstructions() const
+{
+ return d_instructions;
+};
+
+void DratProof::outputAsText(std::ostream& os) const
+{
+ for (const DratInstruction& instruction : d_instructions)
+ {
+ instruction.outputAsText(os);
+ os << "\n";
+ }
+};
+
+void DratProof::outputAsLfsc(std::ostream& os, uint8_t indentation) const
+{
+ for (const DratInstruction& i : d_instructions)
+ {
+ if (indentation > 0)
+ {
+ std::fill_n(std::ostream_iterator<char>(os), indentation, ' ');
+ }
+ os << "(";
+ switch (i.d_kind)
+ {
+ case ADDITION:
+ {
+ os << "DRATProofa";
+ break;
+ }
+ case DELETION:
+ {
+ os << "DRATProofd";
+ break;
+ }
+ default: { Unreachable("Unrecognized DRAT instruction kind");
+ }
+ }
+ for (const SatLiteral& l : i.d_clause)
+ {
+ os << "(clc (" << (l.isNegated() ? "neg " : "pos ")
+ << ProofManager::getVarName(l.getSatVariable()) << ") ";
+ }
+ os << "cln";
+ std::fill_n(std::ostream_iterator<char>(os), i.d_clause.size(), ')');
+ os << "\n";
+ }
+ os << "DRATProofn";
+ std::fill_n(std::ostream_iterator<char>(os), d_instructions.size(), ')');
+}
+} // namespace drat
+} // namespace proof
+} // namespace CVC4
diff --git a/src/proof/drat/drat_proof.h b/src/proof/drat/drat_proof.h
new file mode 100644
index 000000000..4715b38f4
--- /dev/null
+++ b/src/proof/drat/drat_proof.h
@@ -0,0 +1,140 @@
+/********************* */
+/*! \file drat_proof.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Alex Ozdemir
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief DRAT Proof Format
+ **
+ ** Declares C++ types that represent a DRAT proof.
+ ** Defines serialization for these types.
+ **
+ ** You can find an introduction to DRAT in the drat-trim paper:
+ ** http://www.cs.utexas.edu/~marijn/publications/drat-trim.pdf
+ **
+ **/
+
+#ifndef __CVC4__PROOF__DRAT__DRAT_PROOF_H
+#define __CVC4__PROOF__DRAT__DRAT_PROOF_H
+
+#include "cvc4_private.h"
+#include "prop/sat_solver.h"
+#include "prop/sat_solver_types.h"
+
+namespace CVC4 {
+namespace proof {
+namespace drat {
+
+using CVC4::prop::SatClause;
+using CVC4::prop::SatLiteral;
+using CVC4::prop::SatVariable;
+
+class CVC4_PUBLIC InvalidDratProofException : public CVC4::Exception
+{
+ public:
+ InvalidDratProofException() : Exception("Invalid DRAT Proof") {}
+
+ InvalidDratProofException(const std::string& msg) : Exception(msg) {}
+
+ InvalidDratProofException(const char* msg) : Exception(msg) {}
+}; /* class InvalidDratProofException */
+
+enum DratInstructionKind
+{
+ ADDITION,
+ DELETION
+};
+
+struct DratInstruction
+{
+ DratInstruction(DratInstructionKind kind, SatClause clause);
+
+ /**
+ * Write the DRAT instruction in textual format.
+ * The format is described in:
+ * http://www.cs.utexas.edu/~marijn/publications/drat-trim.pdf
+ *
+ * @param os the stream to write to
+ */
+ void outputAsText(std::ostream& os) const;
+
+ DratInstructionKind d_kind;
+ SatClause d_clause;
+};
+
+class DratProof
+{
+ public:
+ DratProof(const DratProof&) = default;
+
+ DratProof(DratProof&&) = default;
+
+ ~DratProof() = default;
+
+ /**
+ * Parses a DRAT proof from the **binary format**.
+ * The format is described at:
+ * https://www.cs.utexas.edu/~marijn/drat-trim/#contact
+ *
+ * What do the standard authors mean by the format being "binary"?
+ * They just mean that proofs in this format should be understood as
+ * sequences of bytes, not sequences of ASCII/Unicode/your favorite character
+ * set characters.
+ *
+ * @param binaryProof a string containing the bytes of the binary proof.
+ * Even though the proof isn't text, it's safe to store it in a string
+ * because C++ strings don't make any gaurantees about the encoding of
+ * their contents. This makes them (effectively) just byte sequences.
+ *
+ * @return the parsed proof
+ */
+ static DratProof fromBinary(const std::string& binaryProof);
+
+ /**
+ * @return The instructions in this proof
+ */
+ const std::vector<DratInstruction>& getInstructions() const;
+
+ /**
+ * Write the DRAT proof in textual format.
+ * The format is described in:
+ * http://www.cs.utexas.edu/~marijn/publications/drat-trim.pdf
+ *
+ * @param os the stream to write to
+ */
+ void outputAsText(std::ostream& os) const;
+
+ /**
+ * Write the DRAT proof as an LFSC value
+ * The format is from the LFSC signature drat.plf
+ *
+ * Reads the current `ProofManager` to determine what the variables should be
+ * named.
+ *
+ * @param os the stream to write to
+ * @param indentation the number of spaces to indent each proof instruction
+ */
+ void outputAsLfsc(std::ostream& os, uint8_t indentation) const;
+
+ private:
+ /**
+ * Create an DRAT proof with no instructions.
+ */
+ DratProof();
+
+ /**
+ * The instructions of the DRAT proof.
+ */
+ std::vector<DratInstruction> d_instructions;
+};
+
+} // namespace drat
+} // namespace proof
+} // namespace CVC4
+
+#endif // __CVC4__PROOF__DRAT__DRAT_PROOF_H
diff --git a/src/proof/lfsc_proof_printer.cpp b/src/proof/lfsc_proof_printer.cpp
index e1fa3acdb..be1259837 100644
--- a/src/proof/lfsc_proof_printer.cpp
+++ b/src/proof/lfsc_proof_printer.cpp
@@ -16,7 +16,9 @@
#include "proof/lfsc_proof_printer.h"
+#include <algorithm>
#include <iostream>
+#include <iterator>
#include "prop/bvminisat/core/Solver.h"
#include "prop/minisat/core/Solver.h"
@@ -144,6 +146,45 @@ void LFSCProofPrinter::printResolutionEmptyClause(TSatProof<Solver>* satProof,
printResolution(satProof, satProof->getEmptyClauseId(), out, paren);
}
+void LFSCProofPrinter::printSatInputProof(const std::vector<ClauseId>& clauses,
+ std::ostream& out,
+ const std::string& namingPrefix)
+{
+ for (auto i = clauses.begin(), end = clauses.end(); i != end; ++i)
+ {
+ out << "\n (cnfc_proof _ _ _ "
+ << ProofManager::getInputClauseName(*i, namingPrefix) << " ";
+ }
+ out << "cnfn_proof";
+ std::fill_n(std::ostream_iterator<char>(out), clauses.size(), ')');
+}
+
+void LFSCProofPrinter::printCMapProof(const std::vector<ClauseId>& clauses,
+ std::ostream& out,
+ const std::string& namingPrefix)
+{
+ for (size_t i = 0, n = clauses.size(); i < n; ++i)
+ {
+ out << "\n (CMapc_proof " << (i + 1) << " _ _ _ "
+ << ProofManager::getInputClauseName(clauses[i], namingPrefix) << " ";
+ }
+ out << "CMapn_proof";
+ std::fill_n(std::ostream_iterator<char>(out), clauses.size(), ')');
+}
+
+void LFSCProofPrinter::printSatClause(const prop::SatClause& clause,
+ std::ostream& out,
+ const std::string& namingPrefix)
+{
+ for (auto i = clause.cbegin(); i != clause.cend(); ++i)
+ {
+ out << "(clc " << (i->isNegated() ? "(neg " : "(pos ")
+ << ProofManager::getVarName(i->getSatVariable(), namingPrefix) << ") ";
+ }
+ out << "cln";
+ std::fill_n(std::ostream_iterator<char>(out), clause.size(), ')');
+}
+
// Template specializations
template void LFSCProofPrinter::printAssumptionsResolution(
TSatProof<CVC4::Minisat::Solver>* satProof,
diff --git a/src/proof/lfsc_proof_printer.h b/src/proof/lfsc_proof_printer.h
index bf4bfabad..36a3490f7 100644
--- a/src/proof/lfsc_proof_printer.h
+++ b/src/proof/lfsc_proof_printer.h
@@ -74,7 +74,56 @@ class LFSCProofPrinter
std::ostream& out,
std::ostream& paren);
+ /**
+ * The SAT solver is given a list of clauses.
+ * Assuming that each clause has alreay been individually proven,
+ * defines a proof of the input to the SAT solver.
+ *
+ * Prints an LFSC value corresponding to the proof, i.e. a value of type
+ * (cnf_holds ...)
+ *
+ * @param clauses The clauses to print a proof of
+ * @param out The stream to print to
+ * @param namingPrefix The prefix for LFSC names
+ */
+ static void printSatInputProof(const std::vector<ClauseId>& clauses,
+ std::ostream& out,
+ const std::string& namingPrefix);
+
+ /**
+ * The LRAT proof signature uses the concept of a _clause map_ (CMap), which
+ * represents an indexed collection of (conjoined) clauses.
+ *
+ * Specifically, the signatures rely on a proof that a CMap containing the
+ * clauses given to the SAT solver hold.
+ *
+ * Assuming that the individual clauses already have proofs, this function
+ * prints a proof of the CMap mapping 1 to the first clause, 2 to the second,
+ * and so on.
+ *
+ * That is, it prints a value of type (CMap_holds ...)
+ *
+ * @param clauses The clauses to print a proof of
+ * @param out The stream to print to
+ * @param namingPrefix The prefix for LFSC names
+ */
+ static void printCMapProof(const std::vector<ClauseId>& clauses,
+ std::ostream& out,
+ const std::string& namingPrefix);
+
+ /**
+ * Prints a clause
+ *
+ * @param clause The clause to print
+ * @param out The stream to print to
+ * @param namingPrefix The prefix for LFSC names
+ */
+ static void printSatClause(const prop::SatClause& clause,
+ std::ostream& out,
+ const std::string& namingPrefix);
+
private:
+
/**
* Maps a clause id to a string identifier used in the LFSC proof.
*
diff --git a/src/proof/lrat/lrat_proof.cpp b/src/proof/lrat/lrat_proof.cpp
new file mode 100644
index 000000000..3b4bac3f0
--- /dev/null
+++ b/src/proof/lrat/lrat_proof.cpp
@@ -0,0 +1,385 @@
+/********************* */
+/*! \file lrat_proof.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Alex Ozdemir
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief DRAT Proof Format
+ **
+ ** Defines deserialization for DRAT proofs.
+ **/
+
+#include "proof/lrat/lrat_proof.h"
+
+#include <algorithm>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <unordered_map>
+
+#include "base/cvc4_assert.h"
+#include "base/output.h"
+#include "proof/lfsc_proof_printer.h"
+
+#if CVC4_USE_DRAT2ER
+#include "drat2er_options.h"
+#include "drat_trim_interface.h"
+#endif
+
+namespace CVC4 {
+namespace proof {
+namespace lrat {
+
+using prop::SatClause;
+using prop::SatLiteral;
+using prop::SatVariable;
+
+namespace {
+// Prints the literal as a (+) or (-) int
+// Not operator<< b/c that represents negation as ~
+std::ostream& textOut(std::ostream& o, const SatLiteral& l)
+{
+ if (l.isNegated())
+ {
+ o << "-";
+ }
+ return o << l.getSatVariable();
+}
+
+// Prints the clause as a space-separated list of ints
+// Not operator<< b/c that represents negation as ~
+std::ostream& textOut(std::ostream& o, const SatClause& c)
+{
+ for (const auto l : c)
+ {
+ textOut(o, l) << " ";
+ }
+ return o << "0";
+}
+
+// Prints the trace as a space-separated list of (+) ints with a space at the
+// end.
+std::ostream& operator<<(std::ostream& o, const LratUPTrace& trace)
+{
+ for (const auto& i : trace)
+ {
+ o << i << " ";
+ }
+ return o;
+}
+
+/**
+ * Print a list of clause indices to go to while doing UP.
+ *
+ * i.e. a value of type Trace
+ *
+ * @param o where to print to
+ * @param trace the trace (list of clauses) to print
+ */
+void printTrace(std::ostream& o, const LratUPTrace& trace)
+{
+ for (ClauseIdx idx : trace)
+ {
+ o << "(Tracec " << idx << " ";
+ }
+ o << "Tracen";
+ std::fill_n(std::ostream_iterator<char>(o), trace.size(), ')');
+}
+
+/**
+ * Print the RAT hints for a clause addition.
+ *
+ * i.e. prints an LFSC value of type RATHints
+ *
+ * @param o where to print to
+ * @param hints the RAT hints to print
+ */
+void printHints(std::ostream& o,
+ const std::vector<std::pair<ClauseIdx, LratUPTrace>>& hints)
+{
+ for (auto& hint : hints)
+ {
+ o << "\n (RATHintsc " << hint.first << " ";
+ printTrace(o, hint.second);
+ o << " ";
+ }
+ o << "RATHintsn";
+ std::fill_n(std::ostream_iterator<char>(o), hints.size(), ')');
+}
+
+/**
+ * Print an index list
+ *
+ * i.e. prints an LFSC value of type CIList
+ *
+ * @param o where to print to
+ * @param indices the list of indices to print
+ */
+void printIndices(std::ostream& o, const std::vector<ClauseIdx>& indices)
+{
+ // Verify that the indices are sorted!
+ for (size_t i = 0, n = indices.size() - 1; i < n; ++i)
+ {
+ Assert(indices[i] < indices[i + 1]);
+ }
+
+ for (ClauseIdx idx : indices)
+ {
+ o << "(CIListc " << idx << " ";
+ }
+ o << "CIListn";
+ std::fill_n(std::ostream_iterator<char>(o), indices.size(), ')');
+}
+
+} // namespace
+
+// Prints the LRAT addition line in textual format
+
+LratProof LratProof::fromDratProof(
+ const std::unordered_map<ClauseId, SatClause*>& usedClauses,
+ const std::vector<ClauseId>& clauseOrder,
+ const std::string& dratBinary)
+{
+ std::ostringstream cmd;
+ char formulaFilename[] = "/tmp/cvc4-dimacs-XXXXXX";
+ char dratFilename[] = "/tmp/cvc4-drat-XXXXXX";
+ char lratFilename[] = "/tmp/cvc4-lrat-XXXXXX";
+ int r;
+ r = mkstemp(formulaFilename);
+ AlwaysAssert(r > 0);
+ close(r);
+ r = mkstemp(dratFilename);
+ AlwaysAssert(r > 0);
+ close(r);
+ r = mkstemp(lratFilename);
+ AlwaysAssert(r > 0);
+ close(r);
+ std::ofstream formStream(formulaFilename);
+ size_t maxVar = 0;
+ for (auto& c : usedClauses)
+ {
+ for (auto l : *(c.second))
+ {
+ if (l.getSatVariable() + 1 > maxVar)
+ {
+ maxVar = l.getSatVariable() + 1;
+ }
+ }
+ }
+ formStream << "p cnf " << maxVar << " " << usedClauses.size() << '\n';
+ for (auto ci : clauseOrder)
+ {
+ auto iterator = usedClauses.find(ci);
+ Assert(iterator != usedClauses.end());
+ for (auto l : *(iterator->second))
+ {
+ if (l.isNegated())
+ {
+ formStream << '-';
+ }
+ formStream << l.getSatVariable() + 1 << " ";
+ }
+ formStream << "0\n";
+ }
+ formStream.close();
+
+ std::ofstream dratStream(dratFilename);
+ dratStream << dratBinary;
+ dratStream.close();
+
+#if CVC4_USE_DRAT2ER
+ drat2er::drat_trim::CheckAndConvertToLRAT(
+ formulaFilename, dratFilename, lratFilename, drat2er::options::QUIET);
+#else
+ Unimplemented("LRAT proof production requires drat2er.\n"
+ "Run contrib/get-drat2er, reconfigure with --drat2er, and rebuild");
+#endif
+
+ std::ifstream lratStream(lratFilename);
+ LratProof lrat(lratStream);
+ remove(formulaFilename);
+ remove(dratFilename);
+ remove(lratFilename);
+ return lrat;
+}
+
+std::istream& operator>>(std::istream& in, SatLiteral& l)
+{
+ int64_t i;
+ in >> i;
+ l = SatLiteral(std::abs(i), i < 0);
+ return in;
+}
+
+// This parser is implemented to parse the textual RAT format found in
+// "Efficient Certified RAT Verification", by Cruz-Filipe et. All
+LratProof::LratProof(std::istream& textualProof)
+{
+ for (size_t line = 0;; ++line)
+ {
+ // Read beginning of instruction. EOF indicates that we're done.
+ size_t clauseIdx;
+ textualProof >> clauseIdx;
+ if (textualProof.eof())
+ {
+ return;
+ }
+
+ // Read the first word of the instruction. A 'd' indicates deletion.
+ std::string first;
+ textualProof >> first;
+ Trace("pf::lrat") << "First word: " << first << std::endl;
+ Assert(textualProof.good());
+ if (first == "d")
+ {
+ std::vector<ClauseIdx> clauses;
+ while (true)
+ {
+ ClauseIdx di;
+ textualProof >> di;
+ Assert(textualProof.good());
+ if (di == 0)
+ {
+ break;
+ }
+ clauses.push_back(di);
+ }
+ std::sort(clauses.begin(), clauses.end());
+ std::unique_ptr<LratInstruction> instr(
+ new LratDeletion(clauseIdx, std::move(clauses)));
+ d_instructions.push_back(std::move(instr));
+ }
+ else
+ {
+ // We need to reparse the first word as a literal to read the clause
+ // we're parsing. It ends with a 0;
+ std::istringstream firstS(first);
+ SatLiteral lit;
+ firstS >> lit;
+ Trace("pf::lrat") << "First lit: " << lit << std::endl;
+ Assert(!firstS.fail(), "Couldn't parse first literal from addition line");
+
+ SatClause clause;
+ for (; lit != 0; textualProof >> lit)
+ {
+ Assert(textualProof.good());
+ clause.emplace_back(lit.getSatVariable() - 1, lit.isNegated());
+ }
+
+ // Now we read the AT UP trace. It ends at the first non-(+) #
+ std::vector<ClauseIdx> atTrace;
+ int64_t i;
+ textualProof >> i;
+ for (; i > 0; textualProof >> i)
+ {
+ Assert(textualProof.good());
+ atTrace.push_back(i);
+ }
+
+ // For each RAT hint... (each RAT hint starts with a (-)).
+ std::vector<std::pair<ClauseIdx, LratUPTrace>> resolvants;
+ for (; i<0; textualProof>> i)
+ {
+ Assert(textualProof.good());
+ // Create an entry in the RAT hint list
+ resolvants.emplace_back(-i, std::vector<ClauseIdx>());
+
+ // Record the UP trace. It ends with a (-) or 0.
+ textualProof >> i;
+ for (; i > 0; textualProof >> i)
+ {
+ resolvants.back().second.push_back(i);
+ }
+ }
+ // Pairs compare based on the first element, so this sorts by the
+ // resolution target index
+ std::sort(resolvants.begin(), resolvants.end());
+ std::unique_ptr<LratInstruction> instr(
+ new LratAddition(clauseIdx,
+ std::move(clause),
+ std::move(atTrace),
+ std::move(resolvants)));
+ d_instructions.push_back(std::move(instr));
+ }
+ }
+}
+
+void LratProof::outputAsLfsc(std::ostream& o) const
+{
+ std::ostringstream closeParen;
+ for (const auto& i : d_instructions)
+ {
+ i->outputAsLfsc(o, closeParen);
+ }
+ o << "LRATProofn";
+ o << closeParen.str();
+}
+
+void LratAddition::outputAsText(std::ostream& o) const
+{
+ o << d_idxOfClause << " ";
+ textOut(o, d_clause) << " ";
+ o << d_atTrace; // Inludes a space at the end.
+ for (const auto& rat : d_resolvants)
+ {
+ o << "-" << rat.first << " ";
+ o << rat.second; // Includes a space at the end.
+ }
+ o << "0\n";
+}
+
+void LratAddition::outputAsLfsc(std::ostream& o, std::ostream& closeParen) const
+{
+ o << "\n (LRATProofa " << d_idxOfClause << " ";
+ closeParen << ")";
+ LFSCProofPrinter::printSatClause(d_clause, o, "bb");
+ o << " ";
+ printTrace(o, d_atTrace);
+ o << " ";
+ printHints(o, d_resolvants);
+ o << " ";
+}
+
+void LratDeletion::outputAsText(std::ostream& o) const
+{
+ o << d_idxOfClause << " d ";
+ for (const auto& idx : d_clauses)
+ {
+ o << idx << " ";
+ }
+ o << "0\n";
+}
+
+void LratDeletion::outputAsLfsc(std::ostream& o, std::ostream& closeParen) const
+{
+ o << "\n (LRATProofd ";
+ closeParen << ")";
+ printIndices(o, d_clauses);
+ o << " ";
+}
+
+std::ostream& operator<<(std::ostream& o, const LratProof& p)
+{
+ for (const auto& instr : p.getInstructions())
+ {
+ o << *instr;
+ }
+ return o;
+}
+
+std::ostream& operator<<(std::ostream& o, const LratInstruction& i)
+{
+ i.outputAsText(o);
+ return o;
+}
+
+} // namespace lrat
+} // namespace proof
+} // namespace CVC4
diff --git a/src/proof/lrat/lrat_proof.h b/src/proof/lrat/lrat_proof.h
new file mode 100644
index 000000000..fb05bd71b
--- /dev/null
+++ b/src/proof/lrat/lrat_proof.h
@@ -0,0 +1,182 @@
+/********************* */
+/*! \file lrat_proof.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Alex Ozdemir
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief LRAT Proof Format
+ **
+ ** Declares C++ types that represent a LRAT proof.
+ ** Defines serialization for these types.
+ **
+ ** Represents an **abstract** LRAT proof.
+ ** Does **not** represent an LFSC LRAT proof, or an LRAT proof being used to
+ ** prove things about bit-vectors.
+ **
+ ** Paper on LRAT: https://www.cs.utexas.edu/~marijn/publications/lrat.pdf
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__PROOF__LRAT__LRAT_PROOF_H
+#define __CVC4__PROOF__LRAT__LRAT_PROOF_H
+
+#include <iosfwd>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "proof/clause_id.h"
+// Included because we need operator<< for the SAT types
+#include "prop/sat_solver.h"
+
+namespace CVC4 {
+namespace proof {
+namespace lrat {
+
+// Refers to clause position within an LRAT proof
+using ClauseIdx = size_t;
+
+// This is conceptually an Either<Addition,Deletion>
+class LratInstruction
+{
+ public:
+ /**
+ * Write this LRAT instruction in textual format
+ *
+ * @param out the stream to write to
+ */
+ virtual void outputAsText(std::ostream& out) const = 0;
+ /**
+ * Write this LRAT instruction as an LFSC value
+ *
+ * @param out the stream to write to
+ * @param closeParen the stream to write any closing parentheses to
+ *
+ */
+ virtual void outputAsLfsc(std::ostream& o,
+ std::ostream& closeParen) const = 0;
+ virtual ~LratInstruction() = default;
+};
+
+class LratDeletion : public LratInstruction
+{
+ public:
+ LratDeletion(ClauseIdx idxOfClause, std::vector<ClauseIdx>&& clauses)
+ : d_idxOfClause(idxOfClause), d_clauses(clauses)
+ {
+ // Nothing left to do
+ }
+
+ LratDeletion() = default;
+
+ void outputAsText(std::ostream& out) const override;
+ void outputAsLfsc(std::ostream& o, std::ostream& closeParen) const override;
+
+ private:
+ // This idx doesn't really matter, but it's in the format anyway, so we parse
+ // it.
+ ClauseIdx d_idxOfClause;
+
+ // Clauses to delete
+ std::vector<ClauseIdx> d_clauses;
+};
+
+// A sequence of locations that will contain unit clauses during unit
+// propegation
+using LratUPTrace = std::vector<ClauseIdx>;
+
+class LratAddition : public LratInstruction
+{
+ public:
+ LratAddition(ClauseIdx idxOfClause,
+ prop::SatClause&& clause,
+ LratUPTrace&& atTrace,
+ std::vector<std::pair<ClauseIdx, LratUPTrace>> resolvants)
+ : d_idxOfClause(idxOfClause),
+ d_clause(clause),
+ d_atTrace(atTrace),
+ d_resolvants(resolvants)
+ {
+ // Nothing left to do
+ }
+
+ void outputAsText(std::ostream& out) const override;
+ void outputAsLfsc(std::ostream& o, std::ostream& closeParen) const override;
+
+ private:
+ // The idx for the new clause
+ ClauseIdx d_idxOfClause;
+ // The new clause
+ prop::SatClause d_clause;
+ // UP trace based on the negation of that clause
+ LratUPTrace d_atTrace;
+
+ // Clauses that can resolve with `clause` on its first variable,
+ // together with a UP trace after that resolution.
+ // Used for RAT checks.
+ std::vector<std::pair<ClauseIdx, LratUPTrace>> d_resolvants;
+};
+
+class LratProof
+{
+ public:
+ /**
+ * @brief Construct an LRAT proof from a DRAT proof, using drat-trim
+ *
+ * @param usedClauses The CNF formula that we're deriving bottom from.
+ * It's a map because other parts of the system represent
+ * it this way.
+ * @param clauseOrder A record of the order in which those clauses were
+ * given to the SAT solver.
+ * @param dratBinary The DRAT proof from the SAT solver, as a binary stream.
+ */
+ static LratProof fromDratProof(
+ const std::unordered_map<ClauseId, prop::SatClause*>& usedClauses,
+ const std::vector<ClauseId>& clauseOrder,
+ const std::string& dratBinary);
+ /**
+ * @brief Construct an LRAT proof from its textual representation
+ *
+ * @param textualProof the textual encoding of the LRAT proof. See the paper
+ * in the file's header comment.
+ */
+ LratProof(std::istream& textualProof);
+
+ /**
+ * Construct a LRAT proof from an explicit instruction list
+ *
+ * @param instructions
+ */
+ LratProof(std::vector<std::unique_ptr<LratInstruction>>&& instructions)
+ : d_instructions(std::move(instructions))
+ {
+ // Nothing else
+ }
+
+ const std::vector<std::unique_ptr<LratInstruction>>& getInstructions() const
+ {
+ return d_instructions;
+ }
+
+ void outputAsLfsc(std::ostream& o) const;
+
+ private:
+ // The instructions in the proof. Each is a deletion or addition.
+ std::vector<std::unique_ptr<LratInstruction>> d_instructions;
+};
+
+// Prints the LRAT proof in textual format
+std::ostream& operator<<(std::ostream& o, const LratProof& p);
+std::ostream& operator<<(std::ostream& o, const LratInstruction& i);
+
+} // namespace lrat
+} // namespace proof
+} // namespace CVC4
+
+#endif
diff --git a/src/proof/resolution_bitvector_proof.cpp b/src/proof/resolution_bitvector_proof.cpp
index 667d630f8..1db673949 100644
--- a/src/proof/resolution_bitvector_proof.cpp
+++ b/src/proof/resolution_bitvector_proof.cpp
@@ -26,6 +26,7 @@
#include "proof/proof_utils.h"
#include "proof/sat_proof_implementation.h"
#include "prop/bvminisat/bvminisat.h"
+#include "prop/sat_solver_types.h"
#include "theory/bv/bitblast/bitblaster.h"
#include "theory/bv/theory_bv.h"
#include "theory/bv/theory_bv_rewrite_rules.h"
@@ -54,32 +55,22 @@ void ResolutionBitVectorProof::initSatProof(CVC4::BVMinisat::Solver* solver)
d_resolutionProof.reset(new BVSatProof(solver, &d_fakeContext, "bb", true));
}
-theory::TheoryId ResolutionBitVectorProof::getTheoryId()
+void ResolutionBitVectorProof::initCnfProof(prop::CnfStream* cnfStream,
+ context::Context* cnf,
+ prop::SatVariable trueVar,
+ prop::SatVariable falseVar)
{
- return theory::THEORY_BV;
+ Assert(d_resolutionProof != NULL);
+ Assert(d_cnfProof == nullptr);
+ d_cnfProof.reset(new LFSCCnfProof(cnfStream, cnf, "bb"));
+
+ d_cnfProof->registerTrueUnitClause(d_resolutionProof->getTrueUnit());
+ d_cnfProof->registerFalseUnitClause(d_resolutionProof->getFalseUnit());
}
-void ResolutionBitVectorProof::initCnfProof(prop::CnfStream* cnfStream,
- context::Context* cnf)
+void ResolutionBitVectorProof::attachToSatSolver(prop::SatSolver& sat_solver)
{
- Assert(d_resolutionProof != NULL);
- BitVectorProof::initCnfProof(cnfStream, cnf);
-
- // true and false have to be setup in a special way
- Node true_node = NodeManager::currentNM()->mkConst<bool>(true);
- Node false_node = NodeManager::currentNM()->mkConst<bool>(false).notNode();
-
- d_cnfProof->pushCurrentAssertion(true_node);
- d_cnfProof->pushCurrentDefinition(true_node);
- d_cnfProof->registerConvertedClause(d_resolutionProof->getTrueUnit());
- d_cnfProof->popCurrentAssertion();
- d_cnfProof->popCurrentDefinition();
-
- d_cnfProof->pushCurrentAssertion(false_node);
- d_cnfProof->pushCurrentDefinition(false_node);
- d_cnfProof->registerConvertedClause(d_resolutionProof->getFalseUnit());
- d_cnfProof->popCurrentAssertion();
- d_cnfProof->popCurrentDefinition();
+ sat_solver.setResolutionProofLog(this);
}
BVSatProof* ResolutionBitVectorProof::getSatProof()
@@ -258,13 +249,15 @@ void ResolutionBitVectorProof::finalizeConflicts(std::vector<Expr>& conflicts)
}
}
-void LFSCBitVectorProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map)
+void LfscResolutionBitVectorProof::printTheoryLemmaProof(
+ std::vector<Expr>& lemma,
+ std::ostream& os,
+ std::ostream& paren,
+ const ProofLetMap& map)
{
- Debug("pf::bv") << "(pf::bv) LFSCBitVectorProof::printTheoryLemmaProof called"
- << std::endl;
+ Debug("pf::bv")
+ << "(pf::bv) LfscResolutionBitVectorProof::printTheoryLemmaProof called"
+ << std::endl;
Expr conflict = utils::mkSortedExpr(kind::OR, lemma);
Debug("pf::bv") << "\tconflict = " << conflict << std::endl;
@@ -467,7 +460,7 @@ void LFSCBitVectorProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
}
}
-void LFSCBitVectorProof::calculateAtomsInBitblastingProof()
+void LfscResolutionBitVectorProof::calculateAtomsInBitblastingProof()
{
// Collect the input clauses used
IdToSatClause used_lemmas;
@@ -477,9 +470,9 @@ void LFSCBitVectorProof::calculateAtomsInBitblastingProof()
Assert(used_lemmas.empty());
}
-void LFSCBitVectorProof::printResolutionProof(std::ostream& os,
- std::ostream& paren,
- ProofLetMap& letMap)
+void LfscResolutionBitVectorProof::printBBDeclarationAndCnf(std::ostream& os,
+ std::ostream& paren,
+ ProofLetMap& letMap)
{
// print mapping between theory atoms and internal SAT variables
os << std::endl << ";; BB atom mapping\n" << std::endl;
@@ -517,6 +510,16 @@ void LFSCBitVectorProof::printResolutionProof(std::ostream& os,
proof::LFSCProofPrinter::printResolutions(d_resolutionProof.get(), os, paren);
}
-} /* namespace proof */
+void LfscResolutionBitVectorProof::printEmptyClauseProof(std::ostream& os,
+ std::ostream& paren)
+{
+ Assert(options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER,
+ "the BV theory should only be proving bottom directly in the eager "
+ "bitblasting mode");
+ proof::LFSCProofPrinter::printResolutionEmptyClause(
+ d_resolutionProof.get(), os, paren);
+}
+
+} // namespace proof
} /* namespace CVC4 */
diff --git a/src/proof/resolution_bitvector_proof.h b/src/proof/resolution_bitvector_proof.h
index ccb288f6e..6c2ae589f 100644
--- a/src/proof/resolution_bitvector_proof.h
+++ b/src/proof/resolution_bitvector_proof.h
@@ -24,32 +24,16 @@
#include "context/context.h"
#include "expr/expr.h"
#include "proof/bitvector_proof.h"
+#include "proof/sat_proof.h"
#include "proof/theory_proof.h"
#include "prop/bvminisat/core/Solver.h"
+#include "prop/cnf_stream.h"
+#include "prop/sat_solver_types.h"
+#include "theory/bv/bitblast/bitblaster.h"
+#include "theory/bv/theory_bv.h"
namespace CVC4 {
-namespace theory {
-namespace bv {
-class TheoryBV;
-template <class T>
-class TBitblaster;
-} // namespace bv
-} // namespace theory
-
-// TODO(aozdemir) break the sat_solver - resolution_bitvectorproof - cnf_stream
-// header cycle and remove this.
-namespace prop {
-class CnfStream;
-}
-
-} /* namespace CVC4 */
-
-
-namespace CVC4 {
-
-template <class Solver>
-class TSatProof;
typedef TSatProof<CVC4::BVMinisat::Solver> BVSatProof;
namespace proof {
@@ -76,13 +60,7 @@ class ResolutionBitVectorProof : public BitVectorProof
BVSatProof* getSatProof();
- /**
- * Kind of a mess.
- * In eager mode this must be invoked before printing a proof of the empty
- * clause. In lazy mode the behavior is ???
- * TODO(aozdemir) clean this up.
- */
- void finalizeConflicts(std::vector<Expr>& conflicts);
+ void finalizeConflicts(std::vector<Expr>& conflicts) override;
void startBVConflict(CVC4::BVMinisat::Solver::TCRef cr);
void startBVConflict(CVC4::BVMinisat::Solver::TLit lit);
@@ -91,13 +69,14 @@ class ResolutionBitVectorProof : public BitVectorProof
void markAssumptionConflict() { d_isAssumptionConflict = true; }
bool isAssumptionConflict() const { return d_isAssumptionConflict; }
- virtual void printResolutionProof(std::ostream& os,
- std::ostream& paren,
- ProofLetMap& letMap) = 0;
-
- void initCnfProof(prop::CnfStream* cnfStream, context::Context* cnf) override;
+ void initCnfProof(prop::CnfStream* cnfStream,
+ context::Context* cnf,
+ prop::SatVariable trueVar,
+ prop::SatVariable falseVar) override;
protected:
+ void attachToSatSolver(prop::SatSolver& sat_solver) override;
+
context::Context d_fakeContext;
// The CNF formula that results from bit-blasting will need a proof.
@@ -106,13 +85,13 @@ class ResolutionBitVectorProof : public BitVectorProof
bool d_isAssumptionConflict;
- theory::TheoryId getTheoryId() override;
};
-class LFSCBitVectorProof : public ResolutionBitVectorProof
+class LfscResolutionBitVectorProof : public ResolutionBitVectorProof
{
public:
- LFSCBitVectorProof(theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine)
+ LfscResolutionBitVectorProof(theory::bv::TheoryBV* bv,
+ TheoryProofEngine* proofEngine)
: ResolutionBitVectorProof(bv, proofEngine)
{
}
@@ -120,9 +99,10 @@ class LFSCBitVectorProof : public ResolutionBitVectorProof
std::ostream& os,
std::ostream& paren,
const ProofLetMap& map) override;
- void printResolutionProof(std::ostream& os,
- std::ostream& paren,
- ProofLetMap& letMap) override;
+ void printBBDeclarationAndCnf(std::ostream& os,
+ std::ostream& paren,
+ ProofLetMap& letMap) override;
+ void printEmptyClauseProof(std::ostream& os, std::ostream& paren) override;
void calculateAtomsInBitblastingProof() override;
};
diff --git a/src/proof/theory_proof.cpp b/src/proof/theory_proof.cpp
index ee06fbfa0..fe9acfef3 100644
--- a/src/proof/theory_proof.cpp
+++ b/src/proof/theory_proof.cpp
@@ -22,6 +22,7 @@
#include "options/proof_options.h"
#include "proof/arith_proof.h"
#include "proof/array_proof.h"
+#include "proof/clausal_bitvector_proof.h"
#include "proof/clause_id.h"
#include "proof/cnf_proof.h"
#include "proof/proof_manager.h"
@@ -46,7 +47,7 @@
namespace CVC4 {
-using proof::LFSCBitVectorProof;
+using proof::LfscResolutionBitVectorProof;
using proof::ResolutionBitVectorProof;
unsigned CVC4::ProofLetCount::counter = 0;
@@ -80,9 +81,20 @@ void TheoryProofEngine::registerTheory(theory::Theory* th) {
}
if (id == theory::THEORY_BV) {
- auto bv_theory = static_cast<theory::bv::TheoryBV*>(th);
- ResolutionBitVectorProof* bvp = new LFSCBitVectorProof(bv_theory, this);
- d_theoryProofTable[id] = bvp;
+ auto thBv = static_cast<theory::bv::TheoryBV*>(th);
+ if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER
+ && options::bvSatSolver() == theory::bv::SAT_SOLVER_CRYPTOMINISAT)
+ {
+ proof::BitVectorProof* bvp =
+ new proof::LfscClausalBitVectorProof(thBv, this);
+ d_theoryProofTable[id] = bvp;
+ }
+ else
+ {
+ proof::BitVectorProof* bvp =
+ new proof::LfscResolutionBitVectorProof(thBv, this);
+ d_theoryProofTable[id] = bvp;
+ }
return;
}
@@ -105,10 +117,11 @@ void TheoryProofEngine::finishRegisterTheory(theory::Theory* th) {
if (th) {
theory::TheoryId id = th->getId();
if (id == theory::THEORY_BV) {
+ theory::bv::TheoryBV* bv_th = static_cast<theory::bv::TheoryBV*>(th);
Assert(d_theoryProofTable.find(id) != d_theoryProofTable.end());
- ResolutionBitVectorProof* bvp =
- (ResolutionBitVectorProof*)d_theoryProofTable[id];
- ((theory::bv::TheoryBV*)th)->setResolutionProofLog(bvp);
+ proof::BitVectorProof* bvp =
+ static_cast<proof::BitVectorProof*>(d_theoryProofTable[id]);
+ bv_th->setProofLog(bvp);
return;
}
}
@@ -533,9 +546,8 @@ void LFSCTheoryProofEngine::finalizeBvConflicts(const IdToSatClause& lemmas, std
}
}
- ResolutionBitVectorProof* bv = ProofManager::getBitVectorProof();
+ proof::BitVectorProof* bv = ProofManager::getBitVectorProof();
bv->finalizeConflicts(bv_lemmas);
- // bv->printResolutionProof(os, paren, letMap);
}
void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas,
@@ -550,7 +562,7 @@ void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas,
}
// finalizeBvConflicts(lemmas, os, paren, map);
- ProofManager::getBitVectorProof()->printResolutionProof(os, paren, map);
+ ProofManager::getBitVectorProof()->printBBDeclarationAndCnf(os, paren, map);
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
Assert (lemmas.size() == 1);
diff --git a/src/prop/bvminisat/bvminisat.cpp b/src/prop/bvminisat/bvminisat.cpp
index 55710092b..57ef8ef30 100644
--- a/src/prop/bvminisat/bvminisat.cpp
+++ b/src/prop/bvminisat/bvminisat.cpp
@@ -104,7 +104,8 @@ void BVMinisatSatSolver::popAssumption() {
d_minisat->popAssumption();
}
-void BVMinisatSatSolver::setProofLog(proof::ResolutionBitVectorProof* bvp)
+void BVMinisatSatSolver::setResolutionProofLog(
+ proof::ResolutionBitVectorProof* bvp)
{
d_minisat->setProofLog( bvp );
}
diff --git a/src/prop/bvminisat/bvminisat.h b/src/prop/bvminisat/bvminisat.h
index 16489b172..efb90a3f0 100644
--- a/src/prop/bvminisat/bvminisat.h
+++ b/src/prop/bvminisat/bvminisat.h
@@ -119,7 +119,7 @@ public:
void popAssumption() override;
- void setProofLog(proof::ResolutionBitVectorProof* bvp) override;
+ void setResolutionProofLog(proof::ResolutionBitVectorProof* bvp) override;
private:
/* Disable the default constructor. */
diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp
index cdb850ce2..84c315547 100644
--- a/src/prop/cnf_stream.cpp
+++ b/src/prop/cnf_stream.cpp
@@ -79,19 +79,22 @@ void CnfStream::assertClause(TNode node, SatClause& c) {
}
}
- PROOF(if (d_cnfProof) d_cnfProof->pushCurrentDefinition(node););
+ if (PROOF_ON() && d_cnfProof)
+ {
+ d_cnfProof->pushCurrentDefinition(node);
+ }
ClauseId clause_id = d_satSolver->addClause(c, d_removable);
if (clause_id == ClauseIdUndef) return; // nothing to store (no clause was added)
- PROOF
- (
- if (d_cnfProof) {
- Assert (clause_id != ClauseIdError);
- d_cnfProof->registerConvertedClause(clause_id);
- d_cnfProof->popCurrentDefinition();
- }
- );
+ if (PROOF_ON() && d_cnfProof)
+ {
+ if (clause_id != ClauseIdError)
+ {
+ d_cnfProof->registerConvertedClause(clause_id);
+ }
+ d_cnfProof->popCurrentDefinition();
+ };
}
void CnfStream::assertClause(TNode node, SatLiteral a) {
diff --git a/src/prop/cryptominisat.cpp b/src/prop/cryptominisat.cpp
index df5a20791..c04fb8b56 100644
--- a/src/prop/cryptominisat.cpp
+++ b/src/prop/cryptominisat.cpp
@@ -62,10 +62,11 @@ void toInternalClause(SatClause& clause,
CryptoMinisatSolver::CryptoMinisatSolver(StatisticsRegistry* registry,
const std::string& name)
-: d_solver(new CMSat::SATSolver())
-, d_numVariables(0)
-, d_okay(true)
-, d_statistics(registry, name)
+ : d_solver(new CMSat::SATSolver()),
+ d_bvp(nullptr),
+ d_numVariables(0),
+ d_okay(true),
+ d_statistics(registry, name)
{
d_true = newVar();
d_false = newVar();
@@ -117,9 +118,17 @@ ClauseId CryptoMinisatSolver::addClause(SatClause& clause, bool removable){
std::vector<CMSat::Lit> internal_clause;
toInternalClause(clause, internal_clause);
- bool res = d_solver->add_clause(internal_clause);
- d_okay &= res;
- return ClauseIdError;
+ bool nowOkay = d_solver->add_clause(internal_clause);
+ ClauseId freshId = ClauseId(ProofManager::currentPM()->nextId());
+
+ THEORY_PROOF(
+ // If this clause results in a conflict, then `nowOkay` may be false, but
+ // we still need to register this clause as used. Thus, we look at
+ // `d_okay` instead
+ if (d_bvp && d_okay) { d_bvp->registerUsedClause(freshId, clause); })
+
+ d_okay &= nowOkay;
+ return freshId;
}
bool CryptoMinisatSolver::ok() const {
@@ -193,6 +202,12 @@ unsigned CryptoMinisatSolver::getAssertionLevel() const {
return -1;
}
+void CryptoMinisatSolver::setClausalProofLog(proof::ClausalBitVectorProof* bvp)
+{
+ d_bvp = bvp;
+ d_solver->set_drat(&bvp->getDratOstream(), false);
+}
+
// Satistics for CryptoMinisatSolver
CryptoMinisatSolver::Statistics::Statistics(StatisticsRegistry* registry,
diff --git a/src/prop/cryptominisat.h b/src/prop/cryptominisat.h
index c5345cb86..17cc1568c 100644
--- a/src/prop/cryptominisat.h
+++ b/src/prop/cryptominisat.h
@@ -21,6 +21,7 @@
#ifdef CVC4_USE_CRYPTOMINISAT
+#include "proof/clausal_bitvector_proof.h"
#include "prop/sat_solver.h"
// Cryptominisat has name clashes with the other Minisat implementations since
@@ -39,6 +40,7 @@ class CryptoMinisatSolver : public SatSolver {
private:
std::unique_ptr<CMSat::SATSolver> d_solver;
+ proof::ClausalBitVectorProof* d_bvp;
unsigned d_numVariables;
bool d_okay;
SatVariable d_true;
@@ -71,6 +73,7 @@ public:
SatValue modelValue(SatLiteral l) override;
unsigned getAssertionLevel() const override;
+ void setClausalProofLog(proof::ClausalBitVectorProof* bvp) override;
class Statistics {
public:
diff --git a/src/prop/sat_solver.h b/src/prop/sat_solver.h
index 49064c20f..70e46eceb 100644
--- a/src/prop/sat_solver.h
+++ b/src/prop/sat_solver.h
@@ -26,7 +26,6 @@
#include "context/cdlist.h"
#include "context/context.h"
#include "expr/node.h"
-#include "proof/resolution_bitvector_proof.h"
#include "proof/clause_id.h"
#include "prop/sat_solver_types.h"
#include "prop/bv_sat_solver_notify.h"
@@ -34,6 +33,11 @@
namespace CVC4 {
+namespace proof {
+class ClausalBitVectorProof;
+class ResolutionBitVectorProof;
+} // namespace proof
+
namespace prop {
class TheoryProxy;
@@ -97,7 +101,9 @@ public:
/** Check if the solver is in an inconsistent state */
virtual bool ok() const = 0;
- virtual void setProofLog(proof::ResolutionBitVectorProof* bvp) {}
+ virtual void setResolutionProofLog(proof::ResolutionBitVectorProof* bvp) {}
+
+ virtual void setClausalProofLog(proof::ClausalBitVectorProof* drat_proof) {}
};/* class SatSolver */
diff --git a/src/smt/smt_engine.h b/src/smt/smt_engine.h
index 5aa59fad7..e53d1eb55 100644
--- a/src/smt/smt_engine.h
+++ b/src/smt/smt_engine.h
@@ -217,8 +217,8 @@ class CVC4_PUBLIC SmtEngine {
/**
* Whether or not this SmtEngine is fully initialized (post-construction).
* This post-construction initialization is automatically triggered by the
- * use of the SmtEngine; e.g. when setLogic() is called, or the first
- * assertion is made, etc.
+ * use of the SmtEngine; e.g. when the first formula is asserted, a call
+ * to simplify() is issued, a scope is pushed, etc.
*/
bool d_fullyInited;
@@ -457,6 +457,14 @@ class CVC4_PUBLIC SmtEngine {
~SmtEngine();
/**
+ * Return true if this SmtEngine is fully initialized (post-construction).
+ * This post-construction initialization is automatically triggered by the
+ * use of the SmtEngine; e.g. when the first formula is asserted, a call
+ * to simplify() is issued, a scope is pushed, etc.
+ */
+ bool isFullyInited() { return d_fullyInited; }
+
+ /**
* Set the logic of the script.
*/
void setLogic(
diff --git a/src/theory/arith/constraint.cpp b/src/theory/arith/constraint.cpp
index 352ba0f36..297e3de37 100644
--- a/src/theory/arith/constraint.cpp
+++ b/src/theory/arith/constraint.cpp
@@ -499,6 +499,35 @@ bool Constraint::hasFarkasProof() const {
return getProofType() == FarkasAP;
}
+bool Constraint::hasSimpleFarkasProof() const
+{
+ Debug("constraints::hsfp") << "hasSimpleFarkasProof " << this << std::endl;
+ if (!hasFarkasProof())
+ {
+ Debug("constraints::hsfp") << "There is no simple Farkas proof because "
+ "there is no farkas proof."
+ << std::endl;
+ return false;
+ }
+ const ConstraintRule& rule = getConstraintRule();
+ AntecedentId antId = rule.d_antecedentEnd;
+ ConstraintCP antecdent = d_database->getAntecedent(antId);
+ while (antecdent != NullConstraint)
+ {
+ if (antecdent->getProofType() != AssumeAP)
+ {
+ Debug("constraints::hsfp") << "There is no simple Farkas proof b/c there "
+ "is an antecdent w/ rule ";
+ antecdent->getConstraintRule().print(Debug("constraints::hsfp"));
+ Debug("constraints::hsfp") << std::endl;
+ return false;
+ }
+ --antId;
+ antecdent = d_database->getAntecedent(antId);
+ }
+ return true;
+}
+
bool Constraint::hasIntHoleProof() const {
return getProofType() == IntHoleAP;
}
@@ -568,8 +597,9 @@ void ConstraintRule::print(std::ostream& out) const {
out << d_constraint << std::endl;
out << "d_proofType= " << d_proofType << ", " << std::endl;
out << "d_antecedentEnd= "<< d_antecedentEnd << std::endl;
-
- if(d_constraint != NullConstraint){
+
+ if (d_constraint != NullConstraint && d_antecedentEnd != AntecedentIdSentinel)
+ {
const ConstraintDatabase& database = d_constraint->getDatabase();
size_t coeffIterator = (coeffs != RationalVectorCPSentinel) ? coeffs->size()-1 : 0;
@@ -597,7 +627,7 @@ void ConstraintRule::print(std::ostream& out) const {
out << " * (" << *(d_constraint->getNegation()) << ")";
out << " [not d_constraint] " << endl;
}
- out << "}";
+ out << "}";
}
bool Constraint::wellFormedFarkasProof() const {
@@ -1188,6 +1218,8 @@ void Constraint::impliedByIntHole(ConstraintCP a, bool nowInConflict){
Assert(!hasProof());
Assert(negationHasProof() == nowInConflict);
Assert(a->hasProof());
+ Debug("pf::arith") << "impliedByIntHole(" << this << ", " << a << ")"
+ << std::endl;
d_database->d_antecedents.push_back(NullConstraint);
d_database->d_antecedents.push_back(a);
@@ -1339,6 +1371,7 @@ Node Constraint::externalExplainByAssertions(const ConstraintCPVec& b){
}
Node Constraint::externalExplainConflict() const{
+ Debug("pf::arith") << this << std::endl;
Assert(inConflict());
NodeBuilder<> nb(kind::AND);
externalExplainByAssertions(nb);
@@ -1407,6 +1440,13 @@ void Constraint::externalExplain(NodeBuilder<>& nb, AssertionOrder order) const{
Assert(!isAssumption() || assertedToTheTheory());
Assert(!isInternalAssumption());
+ if (Debug.isOn("pf::arith"))
+ {
+ Debug("pf::arith") << "Explaining: " << this << " with rule ";
+ getConstraintRule().print(Debug("pf::arith"));
+ Debug("pf::arith") << std::endl;
+ }
+
if(assertedBefore(order)){
nb << getWitness();
}else if(hasEqualityEngineProof()){
@@ -1417,6 +1457,7 @@ void Constraint::externalExplain(NodeBuilder<>& nb, AssertionOrder order) const{
ConstraintCP antecedent = d_database->d_antecedents[p];
while(antecedent != NullConstraint){
+ Debug("pf::arith") << "Explain " << antecedent << std::endl;
antecedent->externalExplain(nb, order);
--p;
antecedent = d_database->d_antecedents[p];
diff --git a/src/theory/arith/constraint.h b/src/theory/arith/constraint.h
index d411f2d34..51575bb2f 100644
--- a/src/theory/arith/constraint.h
+++ b/src/theory/arith/constraint.h
@@ -258,7 +258,7 @@ struct PerVariableDatabase{
struct ConstraintRule {
ConstraintP d_constraint;
ArithProofType d_proofType;
- AntecedentId d_antecedentEnd;
+ AntecedentId d_antecedentEnd;
/**
* In this comment, we abbreviate ConstraintDatabase::d_antecedents
@@ -266,37 +266,38 @@ struct ConstraintRule {
*
* This list is always empty if proofs are not enabled.
*
- * If proofs are enabled, the proof of constraint c at p in ans[p] of length n is
- * (NullConstraint, ans[p-(n-1)], ... , ans[p-1], ans[p])
- *
- * Farkas' proofs show a contradiction with the negation of c, c_not = c->getNegation().
+ * If proofs are enabled, the proof of constraint c at p in ans[p] of length n
+ * is (NullConstraint, ans[p-(n-1)], ... , ans[p-1], ans[p])
+ *
+ * Farkas' proofs show a contradiction with the negation of c, c_not =
+ * c->getNegation().
*
- * We treat the position for NullConstraint (p-n) as the position for the farkas
- * coefficient for so we pretend c_not is ans[p-n].
- * So this correlation for the constraints we are going to use:
- * (c_not, ans[p-(n-1)], ... , ans[p-1], ans[p])
- * With the coefficients at positions:
- * (fc[0], fc[1)], ... fc[n])
+ * We treat the position for NullConstraint (p-n) as the position for the
+ * farkas coefficient for so we pretend c_not is ans[p-n]. So this correlation
+ * for the constraints we are going to use: (c_not, ans[p-n+(1)], ... ,
+ * ans[p-n+(n-1)], ans[p-n+(n)]) With the coefficients at positions: (fc[0],
+ * fc[1)], ... fc[n])
*
- * The index of the constraints in the proof are {i | i <= 0 <= n] } (with c_not being p-n).
- * Partition the indices into L, U, and E, the lower bounds, the upper bounds and equalities.
+ * The index of the constraints in the proof are {i | i <= 0 <= n] } (with
+ * c_not being p-n). Partition the indices into L, U, and E, the lower bounds,
+ * the upper bounds and equalities.
*
- * We standardize the proofs to be upper bound oriented following the convention:
- * A x <= b
- * with the proof witness of the form
- * (lambda) Ax <= (lambda) b and lambda >= 0.
+ * We standardize the proofs to be upper bound oriented following the
+ * convention: A x <= b with the proof witness of the form (lambda) Ax <=
+ * (lambda) b and lambda >= 0.
*
- * To accomplish this cleanly, the fc coefficients must be negative for lower bounds.
- * The signs of equalities can be either positive or negative.
+ * To accomplish this cleanly, the fc coefficients must be negative for lower
+ * bounds. The signs of equalities can be either positive or negative.
*
* Thus the proof corresponds to (with multiplication over inequalities):
* \sum_{u in U} fc[u] ans[p-n+u] + \sum_{e in E} fc[e] ans[p-n+e]
* + \sum_{l in L} fc[l] ans[p-n+l]
* |= 0 < 0
* where fc[u] > 0, fc[l] < 0, and fc[e] != 0 (i.e. it can be either +/-).
- *
+ *
* There is no requirement that the proof is minimal.
- * We do however use all of the constraints by requiring non-zero coefficients.
+ * We do however use all of the constraints by requiring non-zero
+ * coefficients.
*/
#if IS_PROOFS_BUILD
RationalVectorCP d_farkasCoefficients;
@@ -346,88 +347,10 @@ struct ConstraintRule {
}; /* class ConstraintRule */
class Constraint {
-private:
- /** The ArithVar associated with the constraint. */
- const ArithVar d_variable;
-
- /** The type of the Constraint. */
- const ConstraintType d_type;
-
- /** The DeltaRational value with the constraint. */
- const DeltaRational d_value;
-
- /** A pointer to the associated database for the Constraint. */
- ConstraintDatabase* d_database;
-
- /**
- * The node to be communicated with the TheoryEngine.
- *
- * This is not context dependent, but may be set once.
- *
- * This must be set if the constraint canBePropagated().
- * This must be set if the constraint assertedToTheTheory().
- * Otherwise, this may be null().
- */
- Node d_literal;
-
- /** Pointer to the negation of the Constraint. */
- ConstraintP d_negation;
-
- /**
- * This is true if the associated node can be propagated.
- *
- * This should be enabled if the node has been preregistered.
- *
- * Sat Context Dependent.
- * This is initially false.
- */
- bool d_canBePropagated;
-
- /**
- * This is the order the constraint was asserted to the theory.
- * If this has been set, the node can be used in conflicts.
- * If this is c.d_assertedOrder < d.d_assertedOrder, then c can be used in the
- * explanation of d.
- *
- * This should be set after the literal is dequeued by Theory::get().
- *
- * Sat Context Dependent.
- * This is initially AssertionOrderSentinel.
- */
- AssertionOrder d_assertionOrder;
-
- /**
- * This is guaranteed to be on the fact queue.
- * For example if x + y = x + 1 is on the fact queue, then use this
- */
- TNode d_witness;
-
- /**
- * The position of the constraint in the constraint rule id.
- *
- * Sat Context Dependent.
- * This is initially
- */
- ConstraintRuleID d_crid;
-
-
- /**
- * True if the equality has been split.
- * Only meaningful if ConstraintType == Equality.
- *
- * User Context Dependent.
- * This is initially false.
- */
- bool d_split;
-
- /**
- * Position in sorted constraint set for the variable.
- * Unset if d_type is Disequality.
- */
- SortedConstraintMapIterator d_variablePosition;
friend class ConstraintDatabase;
+ public:
/**
* This begins construction of a minimal constraint.
*
@@ -444,86 +367,6 @@ private:
*/
~Constraint();
- /** Returns true if the constraint has been initialized. */
- bool initialized() const;
-
- /**
- * This initializes the fields that cannot be set in the constructor due to
- * circular dependencies.
- */
- void initialize(ConstraintDatabase* db, SortedConstraintMapIterator v, ConstraintP negation);
-
-
-
- class ConstraintRuleCleanup {
- public:
- inline void operator()(ConstraintRule* crp){
- Assert(crp != NULL);
- ConstraintP constraint = crp->d_constraint;
- Assert(constraint->d_crid != ConstraintRuleIdSentinel);
- constraint->d_crid = ConstraintRuleIdSentinel;
-
- PROOF(if(crp->d_farkasCoefficients != RationalVectorCPSentinel){
- delete crp->d_farkasCoefficients;
- });
- }
- };
-
- class CanBePropagatedCleanup {
- public:
- inline void operator()(ConstraintP* p){
- ConstraintP constraint = *p;
- Assert(constraint->d_canBePropagated);
- constraint->d_canBePropagated = false;
- }
- };
-
- class AssertionOrderCleanup {
- public:
- inline void operator()(ConstraintP* p){
- ConstraintP constraint = *p;
- Assert(constraint->assertedToTheTheory());
- constraint->d_assertionOrder = AssertionOrderSentinel;
- constraint->d_witness = TNode::null();
- Assert(!constraint->assertedToTheTheory());
- }
- };
-
- class SplitCleanup {
- public:
- inline void operator()(ConstraintP* p){
- ConstraintP constraint = *p;
- Assert(constraint->d_split);
- constraint->d_split = false;
- }
- };
-
- /**
- * Returns true if the node is safe to garbage collect.
- * Both it and its negation must have no context dependent data set.
- */
- bool safeToGarbageCollect() const;
-
- /**
- * Returns true if the constraint has no context dependent data set.
- */
- bool contextDependentDataIsSet() const;
-
- /**
- * Returns true if the node correctly corresponds to the constraint that is
- * being set.
- */
- bool sanityChecking(Node n) const;
-
- /** Returns a reference to the map for d_variable. */
- SortedConstraintMap& constraintSet() const;
-
- /** Returns coefficients for the proofs for farkas cancellation. */
- static std::pair<int, int> unateFarkasSigns(ConstraintCP a, ConstraintCP b);
-
-
-public:
-
static ConstraintType constraintTypeOfComparison(const Comparison& cmp);
inline ConstraintType getType() const {
@@ -648,6 +491,26 @@ public:
/** Returns true if the node has a Farkas' proof. */
bool hasFarkasProof() const;
+ /**
+ * @brief Returns whether this constraint is provable using a Farkas
+ * proof that has input assertions as its antecedents.
+ *
+ * An example of a constraint that has a simple Farkas proof:
+ * x <= 0 proven from x + y <= 0 and x - y <= 0.
+ *
+ * An example of a constraint that does not have a simple Farkas proof:
+ * x <= 0 proven from x + y <= 0 and x - y <= 0.5 for integers x, y
+ * (since integer reasoning is also required!).
+ * Another example of a constraint that might be proven without a simple
+ * Farkas proof:
+ * x < 0 proven from not(x == 0) and not(x > 0).
+ *
+ * This could be proven internally by the arithmetic theory using
+ * `TrichotomyAP` as the proof type.
+ *
+ */
+ bool hasSimpleFarkasProof() const;
+
/** Returns true if the node has a int hole proof. */
bool hasIntHoleProof() const;
@@ -735,22 +598,6 @@ public:
*/
Node externalExplainConflict() const;
-private:
- Node externalExplain(AssertionOrder order) const;
-
- /**
- * Returns an explanation of that was assertedBefore(order).
- * The constraint must have a proof.
- * The constraint cannot be selfExplaining().
- *
- * This is the minimum fringe of the implication tree
- * s.t. every constraint is assertedBefore(order) or hasEqualityEngineProof().
- */
- void externalExplain(NodeBuilder<>& nb, AssertionOrder order) const;
-
- static Node externalExplain(const ConstraintCPVec& b, AssertionOrder order);
-
-public:
/** The constraint is known to be true. */
inline bool hasProof() const {
@@ -791,7 +638,6 @@ public:
*/
ConstraintP getFloor();
-
static ConstraintP makeNegation(ArithVar v, ConstraintType t, const DeltaRational& r);
const ValueCollection& getValueCollection() const;
@@ -896,11 +742,109 @@ public:
*/
const ConstraintDatabase& getDatabase() const;
-private:
-
/** Returns the constraint rule at the position. */
const ConstraintRule& getConstraintRule() const;
-
+
+ private:
+ /** Returns true if the constraint has been initialized. */
+ bool initialized() const;
+
+ /**
+ * This initializes the fields that cannot be set in the constructor due to
+ * circular dependencies.
+ */
+ void initialize(ConstraintDatabase* db,
+ SortedConstraintMapIterator v,
+ ConstraintP negation);
+
+ class ConstraintRuleCleanup
+ {
+ public:
+ inline void operator()(ConstraintRule* crp)
+ {
+ Assert(crp != NULL);
+ ConstraintP constraint = crp->d_constraint;
+ Assert(constraint->d_crid != ConstraintRuleIdSentinel);
+ constraint->d_crid = ConstraintRuleIdSentinel;
+
+ PROOF(if (crp->d_farkasCoefficients != RationalVectorCPSentinel) {
+ delete crp->d_farkasCoefficients;
+ });
+ }
+ };
+
+ class CanBePropagatedCleanup
+ {
+ public:
+ inline void operator()(ConstraintP* p)
+ {
+ ConstraintP constraint = *p;
+ Assert(constraint->d_canBePropagated);
+ constraint->d_canBePropagated = false;
+ }
+ };
+
+ class AssertionOrderCleanup
+ {
+ public:
+ inline void operator()(ConstraintP* p)
+ {
+ ConstraintP constraint = *p;
+ Assert(constraint->assertedToTheTheory());
+ constraint->d_assertionOrder = AssertionOrderSentinel;
+ constraint->d_witness = TNode::null();
+ Assert(!constraint->assertedToTheTheory());
+ }
+ };
+
+ class SplitCleanup
+ {
+ public:
+ inline void operator()(ConstraintP* p)
+ {
+ ConstraintP constraint = *p;
+ Assert(constraint->d_split);
+ constraint->d_split = false;
+ }
+ };
+
+ /**
+ * Returns true if the node is safe to garbage collect.
+ * Both it and its negation must have no context dependent data set.
+ */
+ bool safeToGarbageCollect() const;
+
+ /**
+ * Returns true if the constraint has no context dependent data set.
+ */
+ bool contextDependentDataIsSet() const;
+
+ /**
+ * Returns true if the node correctly corresponds to the constraint that is
+ * being set.
+ */
+ bool sanityChecking(Node n) const;
+
+ /** Returns a reference to the map for d_variable. */
+ SortedConstraintMap& constraintSet() const;
+
+ /** Returns coefficients for the proofs for farkas cancellation. */
+ static std::pair<int, int> unateFarkasSigns(ConstraintCP a, ConstraintCP b);
+
+ Node externalExplain(AssertionOrder order) const;
+
+ /**
+ * Returns an explanation of that was assertedBefore(order).
+ * The constraint must have a proof.
+ * The constraint cannot be selfExplaining().
+ *
+ * This is the minimum fringe of the implication tree
+ * s.t. every constraint is assertedBefore(order) or hasEqualityEngineProof().
+ */
+ void externalExplain(NodeBuilder<>& nb, AssertionOrder order) const;
+
+ static Node externalExplain(const ConstraintCPVec& b, AssertionOrder order);
+
inline ArithProofType getProofType() const {
return getConstraintRule().d_proofType;
}
@@ -934,7 +878,85 @@ private:
*/
bool wellFormedFarkasProof() const;
-
+
+ /** The ArithVar associated with the constraint. */
+ const ArithVar d_variable;
+
+ /** The type of the Constraint. */
+ const ConstraintType d_type;
+
+ /** The DeltaRational value with the constraint. */
+ const DeltaRational d_value;
+
+ /** A pointer to the associated database for the Constraint. */
+ ConstraintDatabase* d_database;
+
+ /**
+ * The node to be communicated with the TheoryEngine.
+ *
+ * This is not context dependent, but may be set once.
+ *
+ * This must be set if the constraint canBePropagated().
+ * This must be set if the constraint assertedToTheTheory().
+ * Otherwise, this may be null().
+ */
+ Node d_literal;
+
+ /** Pointer to the negation of the Constraint. */
+ ConstraintP d_negation;
+
+ /**
+ * This is true if the associated node can be propagated.
+ *
+ * This should be enabled if the node has been preregistered.
+ *
+ * Sat Context Dependent.
+ * This is initially false.
+ */
+ bool d_canBePropagated;
+
+ /**
+ * This is the order the constraint was asserted to the theory.
+ * If this has been set, the node can be used in conflicts.
+ * If this is c.d_assertedOrder < d.d_assertedOrder, then c can be used in the
+ * explanation of d.
+ *
+ * This should be set after the literal is dequeued by Theory::get().
+ *
+ * Sat Context Dependent.
+ * This is initially AssertionOrderSentinel.
+ */
+ AssertionOrder d_assertionOrder;
+
+ /**
+ * This is guaranteed to be on the fact queue.
+ * For example if x + y = x + 1 is on the fact queue, then use this
+ */
+ TNode d_witness;
+
+ /**
+ * The position of the constraint in the constraint rule id.
+ *
+ * Sat Context Dependent.
+ * This is initially
+ */
+ ConstraintRuleID d_crid;
+
+ /**
+ * True if the equality has been split.
+ * Only meaningful if ConstraintType == Equality.
+ *
+ * User Context Dependent.
+ * This is initially false.
+ */
+ bool d_split;
+
+ /**
+ * Position in sorted constraint set for the variable.
+ * Unset if d_type is Disequality.
+ */
+ SortedConstraintMapIterator d_variablePosition;
+
}; /* class ConstraintValue */
std::ostream& operator<<(std::ostream& o, const Constraint& c);
diff --git a/src/theory/arith/kinds b/src/theory/arith/kinds
index 3073d0078..95d1aa9c1 100644
--- a/src/theory/arith/kinds
+++ b/src/theory/arith/kinds
@@ -107,6 +107,7 @@ typerule ABS ::CVC4::theory::arith::IntOperatorTypeRule
typerule INTS_DIVISION ::CVC4::theory::arith::IntOperatorTypeRule
typerule INTS_MODULUS ::CVC4::theory::arith::IntOperatorTypeRule
typerule DIVISIBLE ::CVC4::theory::arith::IntUnaryPredicateTypeRule
+typerule DIVISIBLE_OP ::CVC4::theory::arith::DivisibleOpTypeRule
typerule DIVISION_TOTAL ::CVC4::theory::arith::ArithOperatorTypeRule
typerule INTS_DIVISION_TOTAL ::CVC4::theory::arith::IntOperatorTypeRule
diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp
index 89550295a..48d1b0188 100644
--- a/src/theory/arith/theory_arith_private.cpp
+++ b/src/theory/arith/theory_arith_private.cpp
@@ -2138,6 +2138,7 @@ Node flattenAndSort(Node n){
/** Outputs conflicts to the output channel. */
void TheoryArithPrivate::outputConflicts(){
+ Debug("arith::conflict") << "outputting conflicts" << std::endl;
Assert(anyConflict());
static unsigned int conflicts = 0;
@@ -2145,13 +2146,39 @@ void TheoryArithPrivate::outputConflicts(){
Assert(!d_conflicts.empty());
for(size_t i = 0, i_end = d_conflicts.size(); i < i_end; ++i){
ConstraintCP confConstraint = d_conflicts[i];
+ bool hasProof = confConstraint->hasProof();
Assert(confConstraint->inConflict());
+ const ConstraintRule& pf = confConstraint->getConstraintRule();
+ if (Debug.isOn("arith::conflict"))
+ {
+ pf.print(std::cout);
+ std::cout << std::endl;
+ }
Node conflict = confConstraint->externalExplainConflict();
++conflicts;
Debug("arith::conflict") << "d_conflicts[" << i << "] " << conflict
- // << "("<<conflicts<<")"
- << endl;
+ << " has proof: " << hasProof << endl;
+ PROOF(if (d_containing.d_proofRecorder && confConstraint->hasFarkasProof()
+ && pf.d_farkasCoefficients->size()
+ == conflict.getNumChildren()) {
+ // The Farkas coefficients and the children of `conflict` seem to be in
+ // opposite orders... There is some relevant documentation in the
+ // comment for the d_farkasCoefficients field in "constraint.h"
+ //
+ // Anyways, we reverse the children in `conflict` here.
+ NodeBuilder<> conflictInFarkasCoefficientOrder(kind::AND);
+ for (size_t i = 0, nchildren = conflict.getNumChildren(); i < nchildren;
+ ++i)
+ {
+ conflictInFarkasCoefficientOrder
+ << conflict[conflict.getNumChildren() - i - 1];
+ }
+
+ Assert(conflict.getNumChildren() == pf.d_farkasCoefficients->size());
+ d_containing.d_proofRecorder->saveFarkasCoefficients(
+ conflictInFarkasCoefficientOrder, pf.d_farkasCoefficients);
+ })
if(Debug.isOn("arith::normalize::external")){
conflict = flattenAndSort(conflict);
Debug("arith::conflict") << "(normalized to) " << conflict << endl;
@@ -2174,7 +2201,9 @@ void TheoryArithPrivate::outputConflicts(){
(d_containing.d_out)->conflict(bb);
}
}
+
void TheoryArithPrivate::outputLemma(TNode lem) {
+ Debug("arith::lemma") << "Arith Lemma: " << lem << std::endl;
(d_containing.d_out)->lemma(lem);
}
@@ -4809,11 +4838,41 @@ bool TheoryArithPrivate::rowImplicationCanBeApplied(RowIndex ridx, bool rowUp, C
PROOF(d_farkasBuffer.clear());
RationalVectorP coeffs = NULLPROOF(&d_farkasBuffer);
-
+
+ // After invoking `propegateRow`:
+ // * coeffs[0] is for implied
+ // * coeffs[i+1] is for explain[i]
d_linEq.propagateRow(explain, ridx, rowUp, implied, coeffs);
if(d_tableau.getRowLength(ridx) <= options::arithPropAsLemmaLength()){
Node implication = implied->externalImplication(explain);
Node clause = flattenImplication(implication);
+ PROOF(if (d_containing.d_proofRecorder
+ && coeffs != RationalVectorCPSentinel
+ && coeffs->size() == clause.getNumChildren()) {
+ Debug("arith::prop") << "implied : " << implied << std::endl;
+ Debug("arith::prop") << "implication: " << implication << std::endl;
+ Debug("arith::prop") << "coeff len: " << coeffs->size() << std::endl;
+ Debug("arith::prop") << "exp : " << explain << std::endl;
+ Debug("arith::prop") << "clause : " << clause << std::endl;
+ Debug("arith::prop")
+ << "clause len: " << clause.getNumChildren() << std::endl;
+ Debug("arith::prop") << "exp len: " << explain.size() << std::endl;
+ // Using the information from the above comment we assemble a conflict
+ // AND in coefficient order
+ NodeBuilder<> conflictInFarkasCoefficientOrder(kind::AND);
+ conflictInFarkasCoefficientOrder << implication[1].negate();
+ for (const Node& antecedent : implication[0])
+ {
+ Debug("arith::prop") << " ante: " << antecedent << std::endl;
+ conflictInFarkasCoefficientOrder << antecedent;
+ }
+
+ Assert(coeffs != RationalVectorPSentinel);
+ Assert(conflictInFarkasCoefficientOrder.getNumChildren()
+ == coeffs->size());
+ d_containing.d_proofRecorder->saveFarkasCoefficients(
+ conflictInFarkasCoefficientOrder, coeffs);
+ })
outputLemma(clause);
}else{
Assert(!implied->negationHasProof());
diff --git a/src/theory/arith/theory_arith_type_rules.h b/src/theory/arith/theory_arith_type_rules.h
index 2e998010c..bde1730a2 100644
--- a/src/theory/arith/theory_arith_type_rules.h
+++ b/src/theory/arith/theory_arith_type_rules.h
@@ -169,6 +169,18 @@ public:
}
};/* class RealNullaryOperatorTypeRule */
+class DivisibleOpTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::DIVISIBLE_OP);
+ return nodeManager->builtinOperatorType();
+ }
+}; /* class DivisibleOpTypeRule */
+
}/* CVC4::theory::arith namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/bv/bitblast/bitblaster.h b/src/theory/bv/bitblast/bitblaster.h
index 73b4d19c7..b1fc084ed 100644
--- a/src/theory/bv/bitblast/bitblaster.h
+++ b/src/theory/bv/bitblast/bitblaster.h
@@ -24,6 +24,7 @@
#include <vector>
#include "expr/node.h"
+#include "proof/bitvector_proof.h"
#include "prop/bv_sat_solver_notify.h"
#include "prop/sat_solver_types.h"
#include "theory/bv/bitblast/bitblast_strategies_template.h"
@@ -31,6 +32,7 @@
#include "theory/valuation.h"
#include "util/resource_manager.h"
+
namespace CVC4 {
namespace theory {
namespace bv {
@@ -59,6 +61,10 @@ class TBitblaster
// caches and mappings
TermDefMap d_termCache;
ModelCache d_modelCache;
+ // sat solver used for bitblasting and associated CnfStream
+ std::unique_ptr<context::Context> d_nullContext;
+ std::unique_ptr<prop::CnfStream> d_cnfStream;
+ proof::BitVectorProof* d_bvp;
void initAtomBBStrategies();
void initTermBBStrategies();
@@ -69,6 +75,8 @@ class TBitblaster
TermBBStrategy d_termBBStrategies[kind::LAST_KIND];
AtomBBStrategy d_atomBBStrategies[kind::LAST_KIND];
virtual Node getModelFromSatSolver(TNode node, bool fullModel) = 0;
+ virtual prop::SatSolver* getSatSolver() = 0;
+
public:
TBitblaster();
@@ -83,6 +91,8 @@ class TBitblaster
bool hasBBTerm(TNode node) const;
void getBBTerm(TNode node, Bits& bits) const;
virtual void storeBBTerm(TNode term, const Bits& bits);
+ void setProofLog(proof::BitVectorProof* bvp);
+
/**
* Return a constant representing the value of a in the model.
* If fullModel is true set unconstrained bits to 0. If not return
@@ -171,7 +181,12 @@ void TBitblaster<T>::initTermBBStrategies()
}
template <class T>
-TBitblaster<T>::TBitblaster() : d_termCache(), d_modelCache()
+TBitblaster<T>::TBitblaster()
+ : d_termCache(),
+ d_modelCache(),
+ d_nullContext(new context::Context()),
+ d_cnfStream(),
+ d_bvp(nullptr)
{
initAtomBBStrategies();
initTermBBStrategies();
@@ -202,6 +217,20 @@ void TBitblaster<T>::invalidateModelCache()
}
template <class T>
+void TBitblaster<T>::setProofLog(proof::BitVectorProof* bvp)
+{
+ if (THEORY_PROOF_ON())
+ {
+ d_bvp = bvp;
+ prop::SatSolver* satSolver = getSatSolver();
+ bvp->attachToSatSolver(*satSolver);
+ prop::SatVariable t = satSolver->trueVar();
+ prop::SatVariable f = satSolver->falseVar();
+ bvp->initCnfProof(d_cnfStream.get(), d_nullContext.get(), t, f);
+ }
+}
+
+template <class T>
Node TBitblaster<T>::getTermModel(TNode node, bool fullModel)
{
if (d_modelCache.find(node) != d_modelCache.end()) return d_modelCache[node];
diff --git a/src/theory/bv/bitblast/eager_bitblaster.cpp b/src/theory/bv/bitblast/eager_bitblaster.cpp
index 019918c2f..1e557bb64 100644
--- a/src/theory/bv/bitblast/eager_bitblaster.cpp
+++ b/src/theory/bv/bitblast/eager_bitblaster.cpp
@@ -32,11 +32,8 @@ namespace bv {
EagerBitblaster::EagerBitblaster(TheoryBV* theory_bv, context::Context* c)
: TBitblaster<Node>(),
d_context(c),
- d_nullContext(new context::Context()),
d_satSolver(),
d_bitblastingRegistrar(new BitblastingRegistrar(this)),
- d_cnfStream(),
- d_bvp(nullptr),
d_bv(theory_bv),
d_bbAtoms(),
d_variables(),
@@ -268,13 +265,6 @@ bool EagerBitblaster::collectModelInfo(TheoryModel* m, bool fullModel)
return true;
}
-void EagerBitblaster::setResolutionProofLog(
- proof::ResolutionBitVectorProof* bvp)
-{
- THEORY_PROOF(d_bvp = bvp; d_satSolver->setProofLog(bvp);
- bvp->initCnfProof(d_cnfStream.get(), d_nullContext.get());)
-}
-
bool EagerBitblaster::isSharedTerm(TNode node) {
return d_bv->d_sharedTermsSet.find(node) != d_bv->d_sharedTermsSet.end();
}
diff --git a/src/theory/bv/bitblast/eager_bitblaster.h b/src/theory/bv/bitblast/eager_bitblaster.h
index 3299ffc54..1c183b509 100644
--- a/src/theory/bv/bitblast/eager_bitblaster.h
+++ b/src/theory/bv/bitblast/eager_bitblaster.h
@@ -55,19 +55,13 @@ class EagerBitblaster : public TBitblaster<Node>
bool solve();
bool solve(const std::vector<Node>& assumptions);
bool collectModelInfo(TheoryModel* m, bool fullModel);
- void setResolutionProofLog(proof::ResolutionBitVectorProof* bvp);
private:
context::Context* d_context;
- std::unique_ptr<context::Context> d_nullContext;
typedef std::unordered_set<TNode, TNodeHashFunction> TNodeSet;
- // sat solver used for bitblasting and associated CnfStream
std::unique_ptr<prop::SatSolver> d_satSolver;
std::unique_ptr<BitblastingRegistrar> d_bitblastingRegistrar;
- std::unique_ptr<prop::CnfStream> d_cnfStream;
-
- BitVectorProof* d_bvp;
TheoryBV* d_bv;
TNodeSet d_bbAtoms;
@@ -77,6 +71,7 @@ class EagerBitblaster : public TBitblaster<Node>
std::unique_ptr<MinisatEmptyNotify> d_notify;
Node getModelFromSatSolver(TNode a, bool fullModel) override;
+ prop::SatSolver* getSatSolver() override { return d_satSolver.get(); }
bool isSharedTerm(TNode node);
};
diff --git a/src/theory/bv/bitblast/lazy_bitblaster.cpp b/src/theory/bv/bitblast/lazy_bitblaster.cpp
index 529f0373b..2a47c2315 100644
--- a/src/theory/bv/bitblast/lazy_bitblaster.cpp
+++ b/src/theory/bv/bitblast/lazy_bitblaster.cpp
@@ -64,10 +64,8 @@ TLazyBitblaster::TLazyBitblaster(context::Context* c,
bool emptyNotify)
: TBitblaster<Node>(),
d_bv(bv),
- d_bvp(nullptr),
d_ctx(c),
d_nullRegistrar(new prop::NullRegistrar()),
- d_nullContext(new context::Context()),
d_assertedAtoms(new (true) context::CDList<prop::SatLiteral>(c)),
d_explanations(new (true) ExplanationMap(c)),
d_variables(),
@@ -566,11 +564,12 @@ bool TLazyBitblaster::collectModelInfo(TheoryModel* m, bool fullModel)
return true;
}
-void TLazyBitblaster::setProofLog(proof::ResolutionBitVectorProof* bvp)
+void TLazyBitblaster::setProofLog(proof::BitVectorProof* bvp)
{
- d_bvp = bvp;
- d_satSolver->setProofLog( bvp );
- bvp->initCnfProof(d_cnfStream.get(), d_nullContext.get());
+ THEORY_PROOF(d_bvp = bvp; bvp->attachToSatSolver(*d_satSolver);
+ prop::SatVariable t = d_satSolver->trueVar();
+ prop::SatVariable f = d_satSolver->falseVar();
+ bvp->initCnfProof(d_cnfStream.get(), d_nullContext.get(), t, f));
}
void TLazyBitblaster::clearSolver() {
diff --git a/src/theory/bv/bitblast/lazy_bitblaster.h b/src/theory/bv/bitblast/lazy_bitblaster.h
index 1195d3590..9af74d8db 100644
--- a/src/theory/bv/bitblast/lazy_bitblaster.h
+++ b/src/theory/bv/bitblast/lazy_bitblaster.h
@@ -77,7 +77,7 @@ class TLazyBitblaster : public TBitblaster<Node>
* constants to equivalence classes that don't already have them
*/
bool collectModelInfo(TheoryModel* m, bool fullModel);
- void setProofLog(proof::ResolutionBitVectorProof* bvp);
+ void setProofLog(proof::BitVectorProof* bvp);
typedef TNodeSet::const_iterator vars_iterator;
vars_iterator beginVars() { return d_variables.begin(); }
@@ -126,15 +126,11 @@ class TLazyBitblaster : public TBitblaster<Node>
};
TheoryBV* d_bv;
- proof::ResolutionBitVectorProof* d_bvp;
context::Context* d_ctx;
std::unique_ptr<prop::NullRegistrar> d_nullRegistrar;
- std::unique_ptr<context::Context> d_nullContext;
- // sat solver used for bitblasting and associated CnfStream
std::unique_ptr<prop::BVSatSolverInterface> d_satSolver;
std::unique_ptr<prop::BVSatSolverNotify> d_satSolverNotify;
- std::unique_ptr<prop::CnfStream> d_cnfStream;
AssertionList*
d_assertedAtoms; /**< context dependent list storing the atoms
@@ -155,6 +151,7 @@ class TLazyBitblaster : public TBitblaster<Node>
void addAtom(TNode atom);
bool hasValue(TNode a);
Node getModelFromSatSolver(TNode a, bool fullModel) override;
+ prop::SatSolver* getSatSolver() override { return d_satSolver.get(); }
class Statistics
{
diff --git a/src/theory/bv/bv_eager_solver.cpp b/src/theory/bv/bv_eager_solver.cpp
index 119195c4a..336529dfd 100644
--- a/src/theory/bv/bv_eager_solver.cpp
+++ b/src/theory/bv/bv_eager_solver.cpp
@@ -56,7 +56,7 @@ void EagerBitblastSolver::initialize() {
} else {
d_bitblaster.reset(new EagerBitblaster(d_bv, d_context));
THEORY_PROOF(if (d_bvp) {
- d_bitblaster->setResolutionProofLog(d_bvp);
+ d_bitblaster->setProofLog(d_bvp);
d_bvp->setBitblaster(d_bitblaster.get());
});
}
@@ -127,8 +127,7 @@ bool EagerBitblastSolver::collectModelInfo(TheoryModel* m, bool fullModel)
return d_bitblaster->collectModelInfo(m, fullModel);
}
-void EagerBitblastSolver::setResolutionProofLog(
- proof::ResolutionBitVectorProof* bvp)
+void EagerBitblastSolver::setProofLog(proof::BitVectorProof* bvp)
{
d_bvp = bvp;
}
diff --git a/src/theory/bv/bv_eager_solver.h b/src/theory/bv/bv_eager_solver.h
index 7f688b3ae..0b518ca4a 100644
--- a/src/theory/bv/bv_eager_solver.h
+++ b/src/theory/bv/bv_eager_solver.h
@@ -48,7 +48,7 @@ class EagerBitblastSolver {
bool isInitialized();
void initialize();
bool collectModelInfo(theory::TheoryModel* m, bool fullModel);
- void setResolutionProofLog(proof::ResolutionBitVectorProof* bvp);
+ void setProofLog(proof::BitVectorProof* bvp);
private:
context::CDHashSet<Node, NodeHashFunction> d_assertionSet;
@@ -61,7 +61,7 @@ class EagerBitblastSolver {
bool d_useAig;
TheoryBV* d_bv;
- proof::ResolutionBitVectorProof* d_bvp;
+ proof::BitVectorProof* d_bvp;
}; // class EagerBitblastSolver
} // namespace bv
diff --git a/src/theory/bv/bv_subtheory.h b/src/theory/bv/bv_subtheory.h
index 31c542e0b..e2b649841 100644
--- a/src/theory/bv/bv_subtheory.h
+++ b/src/theory/bv/bv_subtheory.h
@@ -26,7 +26,7 @@
namespace CVC4 {
namespace proof {
-class ResolutionBitVectorProof;
+class BitVectorProof;
}
namespace theory {
@@ -93,7 +93,7 @@ class SubtheorySolver {
return res;
}
virtual void assertFact(TNode fact) { d_assertionQueue.push_back(fact); }
- virtual void setProofLog(proof::ResolutionBitVectorProof* bvp) {}
+ virtual void setProofLog(proof::BitVectorProof* bvp) {}
AssertionQueue::const_iterator assertionsBegin() {
return d_assertionQueue.begin();
}
diff --git a/src/theory/bv/bv_subtheory_bitblast.cpp b/src/theory/bv/bv_subtheory_bitblast.cpp
index ff9dd52c2..ceb02af40 100644
--- a/src/theory/bv/bv_subtheory_bitblast.cpp
+++ b/src/theory/bv/bv_subtheory_bitblast.cpp
@@ -276,7 +276,7 @@ void BitblastSolver::setConflict(TNode conflict) {
d_bv->setConflict(final_conflict);
}
-void BitblastSolver::setProofLog(proof::ResolutionBitVectorProof* bvp)
+void BitblastSolver::setProofLog(proof::BitVectorProof* bvp)
{
d_bitblaster->setProofLog( bvp );
bvp->setBitblaster(d_bitblaster.get());
diff --git a/src/theory/bv/bv_subtheory_bitblast.h b/src/theory/bv/bv_subtheory_bitblast.h
index aa2c90c43..e028dbbdc 100644
--- a/src/theory/bv/bv_subtheory_bitblast.h
+++ b/src/theory/bv/bv_subtheory_bitblast.h
@@ -79,7 +79,7 @@ public:
void bitblastQueue();
void setAbstraction(AbstractionModule* module);
uint64_t computeAtomWeight(TNode atom);
- void setProofLog(proof::ResolutionBitVectorProof* bvp) override;
+ void setProofLog(proof::BitVectorProof* bvp) override;
};
} /* namespace CVC4::theory::bv */
diff --git a/src/theory/bv/kinds b/src/theory/bv/kinds
index 66ee02c63..fe451603b 100644
--- a/src/theory/bv/kinds
+++ b/src/theory/bv/kinds
@@ -36,101 +36,118 @@ well-founded BITVECTOR_TYPE \
"(*CVC4::theory::TypeEnumerator(%TYPE%))" \
"theory/type_enumerator.h"
+### non-parameterized operator kinds ------------------------------------------
+
+## concatentation kind
operator BITVECTOR_CONCAT 2: "concatenation of two or more bit-vectors"
+
+## bit-wise kinds
operator BITVECTOR_AND 2: "bitwise and of two or more bit-vectors"
+operator BITVECTOR_COMP 2 "equality comparison of two bit-vectors (returns one bit)"
operator BITVECTOR_OR 2: "bitwise or of two or more bit-vectors"
operator BITVECTOR_XOR 2: "bitwise xor of two or more bit-vectors"
operator BITVECTOR_NOT 1 "bitwise not of a bit-vector"
operator BITVECTOR_NAND 2 "bitwise nand of two bit-vectors"
operator BITVECTOR_NOR 2 "bitwise nor of two bit-vectors"
operator BITVECTOR_XNOR 2 "bitwise xnor of two bit-vectors"
-operator BITVECTOR_COMP 2 "equality comparison of two bit-vectors (returns one bit)"
+
+## arithmetic kinds
operator BITVECTOR_MULT 2: "multiplication of two or more bit-vectors"
+operator BITVECTOR_NEG 1 "unary negation of a bit-vector"
operator BITVECTOR_PLUS 2: "addition of two or more bit-vectors"
operator BITVECTOR_SUB 2 "subtraction of two bit-vectors"
-operator BITVECTOR_NEG 1 "unary negation of a bit-vector"
operator BITVECTOR_UDIV 2 "unsigned division of two bit-vectors, truncating towards 0 (undefined if divisor is 0)"
operator BITVECTOR_UREM 2 "unsigned remainder from truncating division of two bit-vectors (undefined if divisor is 0)"
operator BITVECTOR_SDIV 2 "2's complement signed division"
-operator BITVECTOR_SREM 2 "2's complement signed remainder (sign follows dividend)"
operator BITVECTOR_SMOD 2 "2's complement signed remainder (sign follows divisor)"
+operator BITVECTOR_SREM 2 "2's complement signed remainder (sign follows dividend)"
# total division kinds
operator BITVECTOR_UDIV_TOTAL 2 "unsigned division of two bit-vectors, truncating towards 0 (defined to be the all-ones bit pattern, if divisor is 0)"
operator BITVECTOR_UREM_TOTAL 2 "unsigned remainder from truncating division of two bit-vectors (defined to be equal to the dividend, if divisor is 0)"
-operator BITVECTOR_SHL 2 "bit-vector shift left (the two bit-vector parameters must have same width)"
-operator BITVECTOR_LSHR 2 "bit-vector logical shift right (the two bit-vector parameters must have same width)"
+## shift kinds
operator BITVECTOR_ASHR 2 "bit-vector arithmetic shift right (the two bit-vector parameters must have same width)"
+operator BITVECTOR_LSHR 2 "bit-vector logical shift right (the two bit-vector parameters must have same width)"
+operator BITVECTOR_SHL 2 "bit-vector shift left (the two bit-vector parameters must have same width)"
-operator BITVECTOR_ULT 2 "bit-vector unsigned less than (the two bit-vector parameters must have same width)"
+## inequality kinds
operator BITVECTOR_ULE 2 "bit-vector unsigned less than or equal (the two bit-vector parameters must have same width)"
-operator BITVECTOR_UGT 2 "bit-vector unsigned greater than (the two bit-vector parameters must have same width)"
+operator BITVECTOR_ULT 2 "bit-vector unsigned less than (the two bit-vector parameters must have same width)"
operator BITVECTOR_UGE 2 "bit-vector unsigned greater than or equal (the two bit-vector parameters must have same width)"
-operator BITVECTOR_SLT 2 "bit-vector signed less than (the two bit-vector parameters must have same width)"
+operator BITVECTOR_UGT 2 "bit-vector unsigned greater than (the two bit-vector parameters must have same width)"
operator BITVECTOR_SLE 2 "bit-vector signed less than or equal (the two bit-vector parameters must have same width)"
-operator BITVECTOR_SGT 2 "bit-vector signed greater than (the two bit-vector parameters must have same width)"
+operator BITVECTOR_SLT 2 "bit-vector signed less than (the two bit-vector parameters must have same width)"
operator BITVECTOR_SGE 2 "bit-vector signed greater than or equal (the two bit-vector parameters must have same width)"
-
+operator BITVECTOR_SGT 2 "bit-vector signed greater than (the two bit-vector parameters must have same width)"
+# inequalities with return type bit-vector of size 1
operator BITVECTOR_ULTBV 2 "bit-vector unsigned less than but returns bv of size 1 instead of boolean"
operator BITVECTOR_SLTBV 2 "bit-vector signed less than but returns bv of size 1 instead of boolean"
-operator BITVECTOR_ITE 3 "same semantics as regular ITE, but condition is bv of size 1 instead of Boolean"
-operator BITVECTOR_REDOR 1 "bit-vector redor"
+## reduction kinds
operator BITVECTOR_REDAND 1 "bit-vector redand"
+operator BITVECTOR_REDOR 1 "bit-vector redor"
-operator BITVECTOR_EAGER_ATOM 1 "formula to be treated as a bv atom via eager bit-blasting (internal-only symbol)"
+## if-then-else kind
+operator BITVECTOR_ITE 3 "same semantics as regular ITE, but condition is bv of size 1 instead of Boolean"
+
+## conversion kinds
+operator BITVECTOR_TO_NAT 1 "bit-vector conversion to (nonnegative) integer; parameter is a bit-vector"
+
+## internal kinds
operator BITVECTOR_ACKERMANNIZE_UDIV 1 "term to be treated as a variable; used for eager bit-blasting Ackermann expansion of bvudiv (internal-only symbol)"
operator BITVECTOR_ACKERMANNIZE_UREM 1 "term to be treated as a variable; used for eager bit-blasting Ackermann expansion of bvurem (internal-only symbol)"
+operator BITVECTOR_EAGER_ATOM 1 "formula to be treated as a bv atom via eager bit-blasting (internal-only symbol)"
+
+### parameterized operator kinds ----------------------------------------------
constant BITVECTOR_BITOF_OP \
::CVC4::BitVectorBitOf \
::CVC4::BitVectorBitOfHashFunction \
"util/bitvector.h" \
"operator for the bit-vector boolean bit extract; payload is an instance of the CVC4::BitVectorBitOf class"
+parameterized BITVECTOR_BITOF BITVECTOR_BITOF_OP 1 "bit-vector boolean bit extract; first parameter is a BITVECTOR_BITOF_OP, second is a bit-vector term"
constant BITVECTOR_EXTRACT_OP \
::CVC4::BitVectorExtract \
::CVC4::BitVectorExtractHashFunction \
"util/bitvector.h" \
"operator for the bit-vector extract; payload is an instance of the CVC4::BitVectorExtract class"
+parameterized BITVECTOR_EXTRACT BITVECTOR_EXTRACT_OP 1 "bit-vector extract; first parameter is a BITVECTOR_EXTRACT_OP, second is a bit-vector term"
constant BITVECTOR_REPEAT_OP \
::CVC4::BitVectorRepeat \
"::CVC4::UnsignedHashFunction< ::CVC4::BitVectorRepeat >" \
"util/bitvector.h" \
"operator for the bit-vector repeat; payload is an instance of the CVC4::BitVectorRepeat class"
-
-constant BITVECTOR_ZERO_EXTEND_OP \
- ::CVC4::BitVectorZeroExtend \
- "::CVC4::UnsignedHashFunction< ::CVC4::BitVectorZeroExtend >" \
- "util/bitvector.h" \
- "operator for the bit-vector zero-extend; payload is an instance of the CVC4::BitVectorZeroExtend class"
-
-constant BITVECTOR_SIGN_EXTEND_OP \
- ::CVC4::BitVectorSignExtend \
- "::CVC4::UnsignedHashFunction< ::CVC4::BitVectorSignExtend >" \
- "util/bitvector.h" \
- "operator for the bit-vector sign-extend; payload is an instance of the CVC4::BitVectorSignExtend class"
+parameterized BITVECTOR_REPEAT BITVECTOR_REPEAT_OP 1 "bit-vector repeat; first parameter is a BITVECTOR_REPEAT_OP, second is a bit-vector term"
constant BITVECTOR_ROTATE_LEFT_OP \
::CVC4::BitVectorRotateLeft \
"::CVC4::UnsignedHashFunction< ::CVC4::BitVectorRotateLeft >" \
"util/bitvector.h" \
"operator for the bit-vector rotate left; payload is an instance of the CVC4::BitVectorRotateLeft class"
+parameterized BITVECTOR_ROTATE_LEFT BITVECTOR_ROTATE_LEFT_OP 1 "bit-vector rotate left; first parameter is a BITVECTOR_ROTATE_LEFT_OP, second is a bit-vector term"
constant BITVECTOR_ROTATE_RIGHT_OP \
::CVC4::BitVectorRotateRight \
"::CVC4::UnsignedHashFunction< ::CVC4::BitVectorRotateRight >" \
"util/bitvector.h" \
"operator for the bit-vector rotate right; payload is an instance of the CVC4::BitVectorRotateRight class"
+parameterized BITVECTOR_ROTATE_RIGHT BITVECTOR_ROTATE_RIGHT_OP 1 "bit-vector rotate right; first parameter is a BITVECTOR_ROTATE_RIGHT_OP, second is a bit-vector term"
-parameterized BITVECTOR_BITOF BITVECTOR_BITOF_OP 1 "bit-vector boolean bit extract; first parameter is a BITVECTOR_BITOF_OP, second is a bit-vector term"
-parameterized BITVECTOR_EXTRACT BITVECTOR_EXTRACT_OP 1 "bit-vector extract; first parameter is a BITVECTOR_EXTRACT_OP, second is a bit-vector term"
-parameterized BITVECTOR_REPEAT BITVECTOR_REPEAT_OP 1 "bit-vector repeat; first parameter is a BITVECTOR_REPEAT_OP, second is a bit-vector term"
-parameterized BITVECTOR_ZERO_EXTEND BITVECTOR_ZERO_EXTEND_OP 1 "bit-vector zero-extend; first parameter is a BITVECTOR_ZERO_EXTEND_OP, second is a bit-vector term"
+constant BITVECTOR_SIGN_EXTEND_OP \
+ ::CVC4::BitVectorSignExtend \
+ "::CVC4::UnsignedHashFunction< ::CVC4::BitVectorSignExtend >" \
+ "util/bitvector.h" \
+ "operator for the bit-vector sign-extend; payload is an instance of the CVC4::BitVectorSignExtend class"
parameterized BITVECTOR_SIGN_EXTEND BITVECTOR_SIGN_EXTEND_OP 1 "bit-vector sign-extend; first parameter is a BITVECTOR_SIGN_EXTEND_OP, second is a bit-vector term"
-parameterized BITVECTOR_ROTATE_LEFT BITVECTOR_ROTATE_LEFT_OP 1 "bit-vector rotate left; first parameter is a BITVECTOR_ROTATE_LEFT_OP, second is a bit-vector term"
-parameterized BITVECTOR_ROTATE_RIGHT BITVECTOR_ROTATE_RIGHT_OP 1 "bit-vector rotate right; first parameter is a BITVECTOR_ROTATE_RIGHT_OP, second is a bit-vector term"
+
+constant BITVECTOR_ZERO_EXTEND_OP \
+ ::CVC4::BitVectorZeroExtend \
+ "::CVC4::UnsignedHashFunction< ::CVC4::BitVectorZeroExtend >" \
+ "util/bitvector.h" \
+ "operator for the bit-vector zero-extend; payload is an instance of the CVC4::BitVectorZeroExtend class"
+parameterized BITVECTOR_ZERO_EXTEND BITVECTOR_ZERO_EXTEND_OP 1 "bit-vector zero-extend; first parameter is a BITVECTOR_ZERO_EXTEND_OP, second is a bit-vector term"
constant INT_TO_BITVECTOR_OP \
::CVC4::IntToBitVector \
@@ -138,67 +155,87 @@ constant INT_TO_BITVECTOR_OP \
"util/bitvector.h" \
"operator for the integer conversion to bit-vector; payload is an instance of the CVC4::IntToBitVector class"
parameterized INT_TO_BITVECTOR INT_TO_BITVECTOR_OP 1 "integer conversion to bit-vector; first parameter is an INT_TO_BITVECTOR_OP, second is an integer term"
-operator BITVECTOR_TO_NAT 1 "bit-vector conversion to (nonnegative) integer; parameter is a bit-vector"
+
+### type rules for non-parameterized operator kinds ---------------------------
typerule CONST_BITVECTOR ::CVC4::theory::bv::BitVectorConstantTypeRule
+## concatentation kind
+typerule BITVECTOR_CONCAT ::CVC4::theory::bv::BitVectorConcatTypeRule
+
+## bit-wise kinds
typerule BITVECTOR_AND ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_OR ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_XOR ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_NOT ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_COMP ::CVC4::theory::bv::BitVectorBVPredTypeRule
typerule BITVECTOR_NAND ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_NOR ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_NOT ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_OR ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_XNOR ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_XOR ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+## arithmetic kinds
typerule BITVECTOR_MULT ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_NEG ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_PLUS ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_SUB ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_NEG ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-
typerule BITVECTOR_UDIV ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_UREM ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_UDIV_TOTAL ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_UREM_TOTAL ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_SDIV ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_SREM ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
typerule BITVECTOR_SMOD ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_SHL ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_LSHR ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_SREM ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+# total division kinds
+typerule BITVECTOR_UDIV_TOTAL ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_UREM_TOTAL ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+
+## shift kinds
typerule BITVECTOR_ASHR ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_ROTATE_LEFT ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_ROTATE_RIGHT ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_LSHR ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_SHL ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
-typerule BITVECTOR_ULT ::CVC4::theory::bv::BitVectorPredicateTypeRule
+## inequality kinds
typerule BITVECTOR_ULE ::CVC4::theory::bv::BitVectorPredicateTypeRule
-typerule BITVECTOR_UGT ::CVC4::theory::bv::BitVectorPredicateTypeRule
+typerule BITVECTOR_ULT ::CVC4::theory::bv::BitVectorPredicateTypeRule
typerule BITVECTOR_UGE ::CVC4::theory::bv::BitVectorPredicateTypeRule
-typerule BITVECTOR_SLT ::CVC4::theory::bv::BitVectorPredicateTypeRule
+typerule BITVECTOR_UGT ::CVC4::theory::bv::BitVectorPredicateTypeRule
typerule BITVECTOR_SLE ::CVC4::theory::bv::BitVectorPredicateTypeRule
-typerule BITVECTOR_SGT ::CVC4::theory::bv::BitVectorPredicateTypeRule
+typerule BITVECTOR_SLT ::CVC4::theory::bv::BitVectorPredicateTypeRule
typerule BITVECTOR_SGE ::CVC4::theory::bv::BitVectorPredicateTypeRule
-
-typerule BITVECTOR_COMP ::CVC4::theory::bv::BitVectorBVPredTypeRule
+typerule BITVECTOR_SGT ::CVC4::theory::bv::BitVectorPredicateTypeRule
+# inequalities with return type bit-vector of size 1
typerule BITVECTOR_ULTBV ::CVC4::theory::bv::BitVectorBVPredTypeRule
typerule BITVECTOR_SLTBV ::CVC4::theory::bv::BitVectorBVPredTypeRule
+
+## if-then-else kind
typerule BITVECTOR_ITE ::CVC4::theory::bv::BitVectorITETypeRule
-typerule BITVECTOR_REDOR ::CVC4::theory::bv::BitVectorUnaryPredicateTypeRule
+## reduction kinds
typerule BITVECTOR_REDAND ::CVC4::theory::bv::BitVectorUnaryPredicateTypeRule
+typerule BITVECTOR_REDOR ::CVC4::theory::bv::BitVectorUnaryPredicateTypeRule
+## conversion kinds
+typerule BITVECTOR_TO_NAT ::CVC4::theory::bv::BitVectorConversionTypeRule
-typerule BITVECTOR_EAGER_ATOM ::CVC4::theory::bv::BitVectorEagerAtomTypeRule
+## internal kinds
typerule BITVECTOR_ACKERMANNIZE_UDIV ::CVC4::theory::bv::BitVectorAckermanizationUdivTypeRule
typerule BITVECTOR_ACKERMANNIZE_UREM ::CVC4::theory::bv::BitVectorAckermanizationUremTypeRule
+typerule BITVECTOR_EAGER_ATOM ::CVC4::theory::bv::BitVectorEagerAtomTypeRule
+
+### type rules for parameterized operator kinds -------------------------------
+typerule BITVECTOR_BITOF_OP ::CVC4::theory::bv::BitVectorBitOfOpTypeRule
+typerule BITVECTOR_BITOF ::CVC4::theory::bv::BitVectorBitOfTypeRule
typerule BITVECTOR_EXTRACT_OP ::CVC4::theory::bv::BitVectorExtractOpTypeRule
typerule BITVECTOR_EXTRACT ::CVC4::theory::bv::BitVectorExtractTypeRule
-typerule BITVECTOR_BITOF ::CVC4::theory::bv::BitVectorBitOfTypeRule
-typerule BITVECTOR_CONCAT ::CVC4::theory::bv::BitVectorConcatTypeRule
+typerule BITVECTOR_REPEAT_OP ::CVC4::theory::bv::BitVectorRepeatOpTypeRule
typerule BITVECTOR_REPEAT ::CVC4::theory::bv::BitVectorRepeatTypeRule
-typerule BITVECTOR_ZERO_EXTEND ::CVC4::theory::bv::BitVectorExtendTypeRule
+typerule BITVECTOR_ROTATE_LEFT_OP ::CVC4::theory::bv::BitVectorRotateLeftOpTypeRule
+typerule BITVECTOR_ROTATE_LEFT ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_ROTATE_RIGHT_OP ::CVC4::theory::bv::BitVectorRotateRightOpTypeRule
+typerule BITVECTOR_ROTATE_RIGHT ::CVC4::theory::bv::BitVectorFixedWidthTypeRule
+typerule BITVECTOR_SIGN_EXTEND_OP ::CVC4::theory::bv::BitVectorSignExtendOpTypeRule
typerule BITVECTOR_SIGN_EXTEND ::CVC4::theory::bv::BitVectorExtendTypeRule
-
-typerule BITVECTOR_TO_NAT ::CVC4::theory::bv::BitVectorConversionTypeRule
+typerule BITVECTOR_ZERO_EXTEND_OP ::CVC4::theory::bv::BitVectorZeroExtendOpTypeRule
+typerule BITVECTOR_ZERO_EXTEND ::CVC4::theory::bv::BitVectorExtendTypeRule
typerule INT_TO_BITVECTOR_OP ::CVC4::theory::bv::IntToBitVectorOpTypeRule
typerule INT_TO_BITVECTOR ::CVC4::theory::bv::BitVectorConversionTypeRule
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index 949a3d738..04a6cf52c 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -986,10 +986,10 @@ bool TheoryBV::applyAbstraction(const std::vector<Node>& assertions, std::vector
return changed;
}
-void TheoryBV::setResolutionProofLog(proof::ResolutionBitVectorProof* bvp)
+void TheoryBV::setProofLog(proof::BitVectorProof* bvp)
{
if( options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER ){
- d_eagerSolver->setResolutionProofLog(bvp);
+ d_eagerSolver->setProofLog(bvp);
}else{
for( unsigned i=0; i< d_subtheories.size(); i++ ){
d_subtheories[i]->setProofLog( bvp );
diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h
index afa9f4b4f..3d151cfb1 100644
--- a/src/theory/bv/theory_bv.h
+++ b/src/theory/bv/theory_bv.h
@@ -31,6 +31,14 @@
#include "util/hash.h"
#include "util/statistics_registry.h"
+// Forward declarations, needed because the BV theory and the BV Proof classes
+// are cyclically dependent
+namespace CVC4 {
+namespace proof {
+class BitVectorProof;
+}
+} // namespace CVC4
+
namespace CVC4 {
namespace theory {
namespace bv {
@@ -104,7 +112,7 @@ public:
bool applyAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions);
- void setResolutionProofLog(proof::ResolutionBitVectorProof* bvp);
+ void setProofLog(proof::BitVectorProof* bvp);
private:
diff --git a/src/theory/bv/theory_bv_type_rules.h b/src/theory/bv/theory_bv_type_rules.h
index 817099752..616a03f6b 100644
--- a/src/theory/bv/theory_bv_type_rules.h
+++ b/src/theory/bv/theory_bv_type_rules.h
@@ -2,7 +2,7 @@
/*! \file theory_bv_type_rules.h
** \verbatim
** Top contributors (to current version):
- ** Dejan Jovanovic, Morgan Deters, Tim King
+ ** Aina Niemetz, Dejan Jovanovic, Morgan Deters
** This file is part of the CVC4 project.
** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
** in the top-level source directory) and their institutional affiliations.
@@ -25,90 +25,67 @@ namespace CVC4 {
namespace theory {
namespace bv {
-class BitVectorConstantTypeRule {
- public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- if (check) {
- if (n.getConst<BitVector>().getSize() == 0) {
- throw TypeCheckingExceptionPrivate(n, "constant of size 0");
- }
- }
- return nodeManager->mkBitVectorType(n.getConst<BitVector>().getSize());
- }
-}; /* class BitVectorConstantTypeRule */
+/* -------------------------------------------------------------------------- */
-class BitVectorBitOfTypeRule {
+class CardinalityComputer
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- if (check) {
- BitVectorBitOf info = n.getOperator().getConst<BitVectorBitOf>();
- TypeNode t = n[0].getType(check);
+ inline static Cardinality computeCardinality(TypeNode type)
+ {
+ Assert(type.getKind() == kind::BITVECTOR_TYPE);
- if (!t.isBitVector()) {
- throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
- }
- if (info.bitIndex >= t.getBitVectorSize()) {
- throw TypeCheckingExceptionPrivate(
- n, "extract index is larger than the bitvector size");
- }
+ unsigned size = type.getConst<BitVectorSize>();
+ if (size == 0)
+ {
+ return 0;
}
- return nodeManager->booleanType();
+ Integer i = Integer(2).pow(size);
+ return i;
}
-}; /* class BitVectorBitOfTypeRule */
+}; /* class CardinalityComputer */
-class BitVectorBVPredTypeRule {
- public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- if (check) {
- TypeNode lhs = n[0].getType(check);
- TypeNode rhs = n[1].getType(check);
- if (!lhs.isBitVector() || lhs != rhs) {
- throw TypeCheckingExceptionPrivate(
- n, "expecting bit-vector terms of the same width");
- }
- }
- return nodeManager->mkBitVectorType(1);
- }
-}; /* class BitVectorBVPredTypeRule */
+/* -------------------------------------------------------------------------- */
-class BitVectorITETypeRule {
+class BitVectorConstantTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- Assert(n.getNumChildren() == 3);
- TypeNode thenpart = n[1].getType(check);
- if (check) {
- TypeNode cond = n[0].getType(check);
- if (cond != nodeManager->mkBitVectorType(1)) {
- throw TypeCheckingExceptionPrivate(
- n, "expecting condition to be bit-vector term size 1");
- }
- TypeNode elsepart = n[2].getType(check);
- if (thenpart != elsepart) {
- throw TypeCheckingExceptionPrivate(
- n, "expecting then and else parts to have same type");
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ if (check)
+ {
+ if (n.getConst<BitVector>().getSize() == 0)
+ {
+ throw TypeCheckingExceptionPrivate(n, "constant of size 0");
}
}
- return thenpart;
+ return nodeManager->mkBitVectorType(n.getConst<BitVector>().getSize());
}
-}; /* class BitVectorITETypeRule */
+}; /* class BitVectorConstantTypeRule */
-class BitVectorFixedWidthTypeRule {
+/* -------------------------------------------------------------------------- */
+
+class BitVectorFixedWidthTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
TNode::iterator it = n.begin();
TypeNode t = (*it).getType(check);
- if (check) {
- if (!t.isBitVector()) {
+ if (check)
+ {
+ if (!t.isBitVector())
+ {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms");
}
TNode::iterator it_end = n.end();
- for (++it; it != it_end; ++it) {
- if ((*it).getType(check) != t) {
+ for (++it; it != it_end; ++it)
+ {
+ if ((*it).getType(check) != t)
+ {
throw TypeCheckingExceptionPrivate(
n, "expecting bit-vector terms of the same width");
}
@@ -118,17 +95,25 @@ class BitVectorFixedWidthTypeRule {
}
}; /* class BitVectorFixedWidthTypeRule */
-class BitVectorPredicateTypeRule {
+/* -------------------------------------------------------------------------- */
+
+class BitVectorPredicateTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- if (check) {
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ if (check)
+ {
TypeNode lhsType = n[0].getType(check);
- if (!lhsType.isBitVector()) {
+ if (!lhsType.isBitVector())
+ {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms");
}
TypeNode rhsType = n[1].getType(check);
- if (lhsType != rhsType) {
+ if (lhsType != rhsType)
+ {
throw TypeCheckingExceptionPrivate(
n, "expecting bit-vector terms of the same width");
}
@@ -137,13 +122,18 @@ class BitVectorPredicateTypeRule {
}
}; /* class BitVectorPredicateTypeRule */
-class BitVectorUnaryPredicateTypeRule {
+class BitVectorUnaryPredicateTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- if (check) {
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ if (check)
+ {
TypeNode type = n[0].getType(check);
- if (!type.isBitVector()) {
+ if (!type.isBitVector())
+ {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms");
}
}
@@ -151,68 +141,166 @@ class BitVectorUnaryPredicateTypeRule {
}
}; /* class BitVectorUnaryPredicateTypeRule */
-class BitVectorEagerAtomTypeRule {
+class BitVectorBVPredTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- if (check) {
- TypeNode lhsType = n[0].getType(check);
- if (!lhsType.isBoolean()) {
- throw TypeCheckingExceptionPrivate(n, "expecting boolean term");
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ if (check)
+ {
+ TypeNode lhs = n[0].getType(check);
+ TypeNode rhs = n[1].getType(check);
+ if (!lhs.isBitVector() || lhs != rhs)
+ {
+ throw TypeCheckingExceptionPrivate(
+ n, "expecting bit-vector terms of the same width");
}
}
- return nodeManager->booleanType();
+ return nodeManager->mkBitVectorType(1);
}
-}; /* class BitVectorEagerAtomTypeRule */
+}; /* class BitVectorBVPredTypeRule */
-class BitVectorAckermanizationUdivTypeRule {
+/* -------------------------------------------------------------------------- */
+/* non-parameterized operator kinds */
+/* -------------------------------------------------------------------------- */
+
+class BitVectorConcatTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- TypeNode lhsType = n[0].getType(check);
- if (check) {
- if (!lhsType.isBitVector()) {
- throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ unsigned size = 0;
+ TNode::iterator it = n.begin();
+ TNode::iterator it_end = n.end();
+ for (; it != it_end; ++it)
+ {
+ TypeNode t = (*it).getType(check);
+ // NOTE: We're throwing a type-checking exception here even
+ // when check is false, bc if we don't check that the arguments
+ // are bit-vectors the result type will be inaccurate
+ if (!t.isBitVector())
+ {
+ throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms");
}
+ size += t.getBitVectorSize();
}
- return lhsType;
+ return nodeManager->mkBitVectorType(size);
}
-}; /* class BitVectorAckermanizationUdivTypeRule */
+}; /* class BitVectorConcatTypeRule */
-class BitVectorAckermanizationUremTypeRule {
+class BitVectorITETypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- TypeNode lhsType = n[0].getType(check);
- if (check) {
- if (!lhsType.isBitVector()) {
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getNumChildren() == 3);
+ TypeNode thenpart = n[1].getType(check);
+ if (check)
+ {
+ TypeNode cond = n[0].getType(check);
+ if (cond != nodeManager->mkBitVectorType(1))
+ {
+ throw TypeCheckingExceptionPrivate(
+ n, "expecting condition to be bit-vector term size 1");
+ }
+ TypeNode elsepart = n[2].getType(check);
+ if (thenpart != elsepart)
+ {
+ throw TypeCheckingExceptionPrivate(
+ n, "expecting then and else parts to have same type");
+ }
+ }
+ return thenpart;
+ }
+}; /* class BitVectorITETypeRule */
+
+/* -------------------------------------------------------------------------- */
+/* parameterized operator kinds */
+/* -------------------------------------------------------------------------- */
+
+class BitVectorBitOfOpTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::BITVECTOR_BITOF_OP);
+ return nodeManager->builtinOperatorType();
+ }
+}; /* class BitVectorBitOfOpTypeRule */
+
+class BitVectorBitOfTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ if (check)
+ {
+ BitVectorBitOf info = n.getOperator().getConst<BitVectorBitOf>();
+ TypeNode t = n[0].getType(check);
+
+ if (!t.isBitVector())
+ {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
+ if (info.bitIndex >= t.getBitVectorSize())
+ {
+ throw TypeCheckingExceptionPrivate(
+ n, "extract index is larger than the bitvector size");
+ }
}
- return lhsType;
+ return nodeManager->booleanType();
}
-}; /* class BitVectorAckermanizationUremTypeRule */
+}; /* class BitVectorBitOfTypeRule */
-class BitVectorExtractTypeRule {
+class BitVectorExtractOpTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::BITVECTOR_EXTRACT_OP);
+ return nodeManager->builtinOperatorType();
+ }
+}; /* class BitVectorExtractOpTypeRule */
+
+class BitVectorExtractTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
BitVectorExtract extractInfo = n.getOperator().getConst<BitVectorExtract>();
// NOTE: We're throwing a type-checking exception here even
// if check is false, bc if we allow high < low the resulting
// type will be illegal
- if (extractInfo.high < extractInfo.low) {
+ if (extractInfo.high < extractInfo.low)
+ {
throw TypeCheckingExceptionPrivate(
n, "high extract index is smaller than the low extract index");
}
- if (check) {
+ if (check)
+ {
TypeNode t = n[0].getType(check);
- if (!t.isBitVector()) {
+ if (!t.isBitVector())
+ {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
- if (extractInfo.high >= t.getBitVectorSize()) {
+ if (extractInfo.high >= t.getBitVectorSize())
+ {
throw TypeCheckingExceptionPrivate(
n, "high extract index is bigger than the size of the bit-vector");
}
@@ -221,45 +309,31 @@ class BitVectorExtractTypeRule {
}
}; /* class BitVectorExtractTypeRule */
-class BitVectorExtractOpTypeRule {
+class BitVectorRepeatOpTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- Assert(n.getKind() == kind::BITVECTOR_EXTRACT_OP);
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::BITVECTOR_REPEAT_OP);
return nodeManager->builtinOperatorType();
}
-}; /* class BitVectorExtractOpTypeRule */
-
-class BitVectorConcatTypeRule {
- public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- unsigned size = 0;
- TNode::iterator it = n.begin();
- TNode::iterator it_end = n.end();
- for (; it != it_end; ++it) {
- TypeNode t = (*it).getType(check);
- // NOTE: We're throwing a type-checking exception here even
- // when check is false, bc if we don't check that the arguments
- // are bit-vectors the result type will be inaccurate
- if (!t.isBitVector()) {
- throw TypeCheckingExceptionPrivate(n, "expecting bit-vector terms");
- }
- size += t.getBitVectorSize();
- }
- return nodeManager->mkBitVectorType(size);
- }
-}; /* class BitVectorConcatTypeRule */
+}; /* class BitVectorRepeatOpTypeRule */
-class BitVectorRepeatTypeRule {
+class BitVectorRepeatTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
TypeNode t = n[0].getType(check);
// NOTE: We're throwing a type-checking exception here even
// when check is false, bc if the argument isn't a bit-vector
// the result type will be inaccurate
- if (!t.isBitVector()) {
+ if (!t.isBitVector())
+ {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
unsigned repeatAmount = n.getOperator().getConst<BitVectorRepeat>();
@@ -267,15 +341,67 @@ class BitVectorRepeatTypeRule {
}
}; /* class BitVectorRepeatTypeRule */
-class BitVectorExtendTypeRule {
+class BitVectorRotateLeftOpTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::BITVECTOR_ROTATE_LEFT);
+ return nodeManager->builtinOperatorType();
+ }
+}; /* class BitVectorRotateLeftOpTypeRule */
+
+class BitVectorRotateRightOpTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::BITVECTOR_ROTATE_RIGHT);
+ return nodeManager->builtinOperatorType();
+ }
+}; /* class BitVectorRotateRightOpTypeRule */
+
+class BitVectorSignExtendOpTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::BITVECTOR_SIGN_EXTEND_OP);
+ return nodeManager->builtinOperatorType();
+ }
+}; /* class BitVectorSignExtendOpTypeRule */
+
+class BitVectorZeroExtendOpTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::BITVECTOR_ZERO_EXTEND_OP);
+ return nodeManager->builtinOperatorType();
+ }
+}; /* class BitVectorZeroExtendOpTypeRule */
+
+class BitVectorExtendTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
TypeNode t = n[0].getType(check);
// NOTE: We're throwing a type-checking exception here even
// when check is false, bc if the argument isn't a bit-vector
// the result type will be inaccurate
- if (!t.isBitVector()) {
+ if (!t.isBitVector())
+ {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
unsigned extendAmount =
@@ -286,20 +412,45 @@ class BitVectorExtendTypeRule {
}
}; /* class BitVectorExtendTypeRule */
-class BitVectorConversionTypeRule {
+class IntToBitVectorOpTypeRule
+{
public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
- bool check) {
- if (n.getKind() == kind::BITVECTOR_TO_NAT) {
- if (check && !n[0].getType(check).isBitVector()) {
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ if (n.getKind() == kind::INT_TO_BITVECTOR_OP)
+ {
+ size_t bvSize = n.getConst<IntToBitVector>();
+ return nodeManager->mkFunctionType(nodeManager->integerType(),
+ nodeManager->mkBitVectorType(bvSize));
+ }
+
+ InternalError("bv-conversion typerule invoked for non-bv-conversion kind");
+ }
+}; /* class IntToBitVectorOpTypeRule */
+
+class BitVectorConversionTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ if (n.getKind() == kind::BITVECTOR_TO_NAT)
+ {
+ if (check && !n[0].getType(check).isBitVector())
+ {
throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
}
return nodeManager->integerType();
}
- if (n.getKind() == kind::INT_TO_BITVECTOR) {
+ if (n.getKind() == kind::INT_TO_BITVECTOR)
+ {
size_t bvSize = n.getOperator().getConst<IntToBitVector>();
- if (check && !n[0].getType(check).isInteger()) {
+ if (check && !n[0].getType(check).isInteger())
+ {
throw TypeCheckingExceptionPrivate(n, "expecting integer term");
}
return nodeManager->mkBitVectorType(bvSize);
@@ -309,35 +460,69 @@ class BitVectorConversionTypeRule {
}
}; /* class BitVectorConversionTypeRule */
-class IntToBitVectorOpTypeRule {
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
+/* -------------------------------------------------------------------------- */
+/* internal */
+/* -------------------------------------------------------------------------- */
- if(n.getKind() == kind::INT_TO_BITVECTOR_OP) {
- size_t bvSize = n.getConst<IntToBitVector>();
- return nodeManager->mkFunctionType( nodeManager->integerType(), nodeManager->mkBitVectorType(bvSize) );
+class BitVectorEagerAtomTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ if (check)
+ {
+ TypeNode lhsType = n[0].getType(check);
+ if (!lhsType.isBoolean())
+ {
+ throw TypeCheckingExceptionPrivate(n, "expecting boolean term");
+ }
}
-
- InternalError("bv-conversion typerule invoked for non-bv-conversion kind");
+ return nodeManager->booleanType();
}
-}; /* class IntToBitVectorOpTypeRule */
+}; /* class BitVectorEagerAtomTypeRule */
-class CardinalityComputer {
+class BitVectorAckermanizationUdivTypeRule
+{
public:
- inline static Cardinality computeCardinality(TypeNode type) {
- Assert(type.getKind() == kind::BITVECTOR_TYPE);
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ TypeNode lhsType = n[0].getType(check);
+ if (check)
+ {
+ if (!lhsType.isBitVector())
+ {
+ throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
+ }
+ }
+ return lhsType;
+ }
+}; /* class BitVectorAckermanizationUdivTypeRule */
- unsigned size = type.getConst<BitVectorSize>();
- if (size == 0) {
- return 0;
+class BitVectorAckermanizationUremTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ TypeNode lhsType = n[0].getType(check);
+ if (check)
+ {
+ if (!lhsType.isBitVector())
+ {
+ throw TypeCheckingExceptionPrivate(n, "expecting bit-vector term");
+ }
}
- Integer i = Integer(2).pow(size);
- return i;
+ return lhsType;
}
-}; /* class CardinalityComputer */
+}; /* class BitVectorAckermanizationUremTypeRule */
-} /* CVC4::theory::bv namespace */
-} /* CVC4::theory namespace */
-} /* CVC4 namespace */
+} // namespace bv
+} // namespace theory
+} // namespace CVC4
#endif /* __CVC4__THEORY__BV__THEORY_BV_TYPE_RULES_H */
diff --git a/src/theory/datatypes/datatypes_rewriter.cpp b/src/theory/datatypes/datatypes_rewriter.cpp
index 4469f0fe9..a2458e2eb 100644
--- a/src/theory/datatypes/datatypes_rewriter.cpp
+++ b/src/theory/datatypes/datatypes_rewriter.cpp
@@ -428,7 +428,7 @@ RewriteResponse DatatypesRewriter::rewriteTester(TNode in)
NodeManager::currentNM()->mkConst(result));
}
const Datatype& dt = static_cast<DatatypeType>(in[0].getType().toType()).getDatatype();
- if (dt.getNumConstructors() == 1)
+ if (dt.getNumConstructors() == 1 && !dt.isSygus())
{
// only one constructor, so it must be
Trace("datatypes-rewrite")
diff --git a/src/theory/datatypes/kinds b/src/theory/datatypes/kinds
index b83e9616a..a0b00bcb0 100644
--- a/src/theory/datatypes/kinds
+++ b/src/theory/datatypes/kinds
@@ -91,6 +91,7 @@ constant TUPLE_UPDATE_OP \
"util/tuple.h" \
"operator for a tuple update; payload is an instance of the CVC4::TupleUpdate class"
parameterized TUPLE_UPDATE TUPLE_UPDATE_OP 2 "tuple update; first parameter is a TUPLE_UPDATE_OP (which references an index), second is the tuple, third is the element to store in the tuple at the given index"
+typerule TUPLE_UPDATE_OP ::CVC4::theory::datatypes::TupleUpdateOpTypeRule
typerule TUPLE_UPDATE ::CVC4::theory::datatypes::TupleUpdateTypeRule
constant RECORD_UPDATE_OP \
@@ -99,6 +100,7 @@ constant RECORD_UPDATE_OP \
"expr/record.h" \
"operator for a record update; payload is an instance CVC4::RecordUpdate class"
parameterized RECORD_UPDATE RECORD_UPDATE_OP 2 "record update; first parameter is a RECORD_UPDATE_OP (which references a field), second is a record term to update, third is the element to store in the record in the given field"
+typerule RECORD_UPDATE_OP ::CVC4::theory::datatypes::RecordUpdateOpTypeRule
typerule RECORD_UPDATE ::CVC4::theory::datatypes::RecordUpdateTypeRule
diff --git a/src/theory/datatypes/theory_datatypes_type_rules.h b/src/theory/datatypes/theory_datatypes_type_rules.h
index 140ebe158..8a5849010 100644
--- a/src/theory/datatypes/theory_datatypes_type_rules.h
+++ b/src/theory/datatypes/theory_datatypes_type_rules.h
@@ -273,6 +273,18 @@ struct TupleUpdateTypeRule {
}
}; /* struct TupleUpdateTypeRule */
+class TupleUpdateOpTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::TUPLE_UPDATE_OP);
+ return nodeManager->builtinOperatorType();
+ }
+}; /* class TupleUpdateOpTypeRule */
+
struct RecordUpdateTypeRule {
inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
bool check) {
@@ -298,6 +310,18 @@ struct RecordUpdateTypeRule {
}
}; /* struct RecordUpdateTypeRule */
+class RecordUpdateOpTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ Assert(n.getKind() == kind::RECORD_UPDATE_OP);
+ return nodeManager->builtinOperatorType();
+ }
+}; /* class RecordUpdateOpTypeRule */
+
class DtSizeTypeRule {
public:
inline static TypeNode computeType(NodeManager* nodeManager, TNode n,
diff --git a/src/theory/fp/theory_fp_rewriter.cpp b/src/theory/fp/theory_fp_rewriter.cpp
index f77291a05..21644161e 100644
--- a/src/theory/fp/theory_fp_rewriter.cpp
+++ b/src/theory/fp/theory_fp_rewriter.cpp
@@ -175,8 +175,9 @@ namespace rewrite {
if (node[0] == node[1]) {
return RewriteResponse(REWRITE_DONE, NodeManager::currentNM()->mkConst(true));
} else if (!isPreRewrite && (node[0] > node[1])) {
- Node normal = NodeManager::currentNM()->mkNode(kind::EQUAL,node[1],node[0]);
- return RewriteResponse(REWRITE_DONE, normal);
+ Node normal =
+ NodeManager::currentNM()->mkNode(kind::EQUAL, node[1], node[0]);
+ return RewriteResponse(REWRITE_DONE, normal);
} else {
return RewriteResponse(REWRITE_DONE, node);
}
@@ -191,7 +192,7 @@ namespace rewrite {
(k == kind::FLOATINGPOINT_MIN_TOTAL) || (k == kind::FLOATINGPOINT_MAX_TOTAL));
#endif
if (node[0] == node[1]) {
- return RewriteResponse(REWRITE_DONE, node[0]);
+ return RewriteResponse(REWRITE_AGAIN, node[0]);
} else {
return RewriteResponse(REWRITE_DONE, node);
}
@@ -249,7 +250,7 @@ namespace rewrite {
(childKind == kind::FLOATINGPOINT_ABS)) {
Node rewritten = NodeManager::currentNM()->mkNode(node.getKind(),node[0][0]);
- return RewriteResponse(REWRITE_AGAIN, rewritten);
+ return RewriteResponse(REWRITE_AGAIN_FULL, rewritten);
} else {
return RewriteResponse(REWRITE_DONE, node);
}
@@ -276,8 +277,11 @@ namespace rewrite {
// Lift negation out of the LHS so it can be cancelled out
if (working[0].getKind() == kind::FLOATINGPOINT_NEG) {
NodeManager * nm = NodeManager::currentNM();
- working = nm->mkNode(kind::FLOATINGPOINT_NEG,
- nm->mkNode(kind::FLOATINGPOINT_REM, working[0][0], working[1]));
+ working = nm->mkNode(
+ kind::FLOATINGPOINT_NEG,
+ nm->mkNode(kind::FLOATINGPOINT_REM, working[0][0], working[1]));
+ // in contrast to other rewrites here, this requires rewrite again full
+ return RewriteResponse(REWRITE_AGAIN_FULL, working);
}
return RewriteResponse(REWRITE_DONE, working);
diff --git a/src/theory/strings/theory_strings.cpp b/src/theory/strings/theory_strings.cpp
index c52069a31..cb60b6342 100644
--- a/src/theory/strings/theory_strings.cpp
+++ b/src/theory/strings/theory_strings.cpp
@@ -3083,15 +3083,29 @@ void TheoryStrings::processSimpleNEq( std::vector< std::vector< Node > > &normal
Trace("strings-solve-debug") << "Non-simple Case 2 : must compare strings" << std::endl;
int loop_in_i = -1;
int loop_in_j = -1;
+ ProcessLoopResult plr = ProcessLoopResult::SKIPPED;
if( detectLoop( normal_forms, i, j, index, loop_in_i, loop_in_j, rproc ) ){
if( !isRev ){ //FIXME
getExplanationVectorForPrefixEq( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j, -1, -1, isRev, info.d_ant );
//set info
- if( processLoop( normal_forms, normal_form_src, i, j, loop_in_i!=-1 ? i : j, loop_in_i!=-1 ? j : i, loop_in_i!=-1 ? loop_in_i : loop_in_j, index, info ) ){
+ plr = processLoop(normal_forms,
+ normal_form_src,
+ i,
+ j,
+ loop_in_i != -1 ? i : j,
+ loop_in_i != -1 ? j : i,
+ loop_in_i != -1 ? loop_in_i : loop_in_j,
+ index,
+ info);
+ if (plr == ProcessLoopResult::INFERENCE)
+ {
info_valid = true;
}
}
- }else{
+ }
+
+ if (plr == ProcessLoopResult::SKIPPED)
+ {
//AJR: length entailment here?
if( normal_forms[i][index].getKind() == kind::CONST_STRING || normal_forms[j][index].getKind() == kind::CONST_STRING ){
unsigned const_k = normal_forms[i][index].getKind() == kind::CONST_STRING ? i : j;
@@ -3310,18 +3324,26 @@ bool TheoryStrings::detectLoop( std::vector< std::vector< Node > > &normal_forms
}
//xs(zy)=t(yz)xr
-bool TheoryStrings::processLoop( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
- int i, int j, int loop_n_index, int other_n_index, int loop_index, int index, InferInfo& info ){
- if( options::stringAbortLoop() ){
- std::stringstream ss;
- ss << "Looping word equation encountered." << std::endl;
- throw LogicException(ss.str());
- }
- if (!options::stringProcessLoop())
+TheoryStrings::ProcessLoopResult TheoryStrings::processLoop(
+ const std::vector<std::vector<Node> >& normal_forms,
+ const std::vector<Node>& normal_form_src,
+ int i,
+ int j,
+ int loop_n_index,
+ int other_n_index,
+ int loop_index,
+ int index,
+ InferInfo& info)
+{
+ if (options::stringProcessLoopMode() == ProcessLoopMode::ABORT)
{
- d_out->setIncomplete();
- return false;
+ throw LogicException("Looping word equation encountered.");
+ }
+ else if (options::stringProcessLoopMode() == ProcessLoopMode::NONE)
+ {
+ return ProcessLoopResult::SKIPPED;
}
+
NodeManager* nm = NodeManager::currentNM();
Node conc;
Trace("strings-loop") << "Detected possible loop for "
@@ -3330,12 +3352,12 @@ bool TheoryStrings::processLoop( std::vector< std::vector< Node > > &normal_form
<< std::endl;
Trace("strings-loop") << " ... T(Y.Z)= ";
- std::vector<Node>& veci = normal_forms[loop_n_index];
+ const std::vector<Node>& veci = normal_forms[loop_n_index];
std::vector<Node> vec_t(veci.begin() + index, veci.begin() + loop_index);
Node t_yz = mkConcat(vec_t);
Trace("strings-loop") << " (" << t_yz << ")" << std::endl;
Trace("strings-loop") << " ... S(Z.Y)= ";
- std::vector<Node>& vecoi = normal_forms[other_n_index];
+ const std::vector<Node>& vecoi = normal_forms[other_n_index];
std::vector<Node> vec_s(vecoi.begin() + index + 1, vecoi.end());
Node s_zy = mkConcat(vec_s);
Trace("strings-loop") << s_zy << std::endl;
@@ -3365,7 +3387,7 @@ bool TheoryStrings::processLoop( std::vector< std::vector< Node > > &normal_form
Trace("strings-loop") << "Strings::Loop: tails are different."
<< std::endl;
sendInference(info.d_ant, conc, "Loop Conflict", true);
- return false;
+ return ProcessLoopResult::CONFLICT;
}
}
@@ -3383,7 +3405,7 @@ bool TheoryStrings::processLoop( std::vector< std::vector< Node > > &normal_form
// try to make t equal to empty to avoid loop
info.d_conc = nm->mkNode(kind::OR, split_eq, split_eq.negate());
info.d_id = INFER_LEN_SPLIT_EMP;
- return true;
+ return ProcessLoopResult::INFERENCE;
}
else
{
@@ -3463,6 +3485,15 @@ bool TheoryStrings::processLoop( std::vector< std::vector< Node > > &normal_form
}
else
{
+ if (options::stringProcessLoopMode() == ProcessLoopMode::SIMPLE_ABORT)
+ {
+ throw LogicException("Normal loop breaking not allowed");
+ }
+ else if (options::stringProcessLoopMode() == ProcessLoopMode::SIMPLE)
+ {
+ return ProcessLoopResult::SKIPPED;
+ }
+
Trace("strings-loop") << "Strings::Loop: Normal Loop Breaking."
<< std::endl;
// right
@@ -3504,7 +3535,7 @@ bool TheoryStrings::processLoop( std::vector< std::vector< Node > > &normal_form
info.d_id = INFER_FLOOP;
info.d_nf_pair[0] = normal_form_src[i];
info.d_nf_pair[1] = normal_form_src[j];
- return true;
+ return ProcessLoopResult::INFERENCE;
}
//return true for lemma, false if we succeed
diff --git a/src/theory/strings/theory_strings.h b/src/theory/strings/theory_strings.h
index aa86f1bc1..70e75db54 100644
--- a/src/theory/strings/theory_strings.h
+++ b/src/theory/strings/theory_strings.h
@@ -409,6 +409,7 @@ private:
LENGTH_ONE,
LENGTH_GEQ_ONE
};
+
/** register length
*
* This method is called on non-constant string terms n. It sends a lemma
@@ -520,8 +521,31 @@ private:
void getNormalForms( Node &eqc, std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend );
bool detectLoop( std::vector< std::vector< Node > > &normal_forms, int i, int j, int index, int &loop_in_i, int &loop_in_j, unsigned rproc );
- bool processLoop( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
- int i, int j, int loop_n_index, int other_n_index,int loop_index, int index, InferInfo& info );
+
+ /**
+ * Result of processLoop() below.
+ */
+ enum class ProcessLoopResult
+ {
+ /** Loop processing made an inference */
+ INFERENCE,
+ /** Loop processing detected a conflict */
+ CONFLICT,
+ /** Loop not processed or no loop detected */
+ SKIPPED,
+ };
+
+ ProcessLoopResult processLoop(
+ const std::vector<std::vector<Node> >& normal_forms,
+ const std::vector<Node>& normal_form_src,
+ int i,
+ int j,
+ int loop_n_index,
+ int other_n_index,
+ int loop_index,
+ int index,
+ InferInfo& info);
+
void processNEqc( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend );
void processReverseNEq( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
diff --git a/test/regress/CMakeLists.txt b/test/regress/CMakeLists.txt
index 95e4b8875..e6e28336e 100644
--- a/test/regress/CMakeLists.txt
+++ b/test/regress/CMakeLists.txt
@@ -1640,6 +1640,7 @@ set(regress_1_tests
regress1/sygus/sygus-lambda-fv.sy
regress1/sygus/sygus-uf-ex.sy
regress1/sygus/t8.sy
+ regress1/sygus/temp_input_to_synth_ic-error-121418.sy
regress1/sygus/tl-type-0.sy
regress1/sygus/tl-type-4x.sy
regress1/sygus/tl-type.sy
@@ -1747,6 +1748,7 @@ set(regress_2_tests
regress2/sygus/inv_gen_n_c11.sy
regress2/sygus/lustre-real.sy
regress2/sygus/max2-univ.sy
+ regress2/sygus/min_IC_1.sy
regress2/sygus/mpg_guard1-dd.sy
regress2/sygus/multi-udiv.sy
regress2/sygus/nia-max-square.sy
diff --git a/test/regress/regress1/sygus/temp_input_to_synth_ic-error-121418.sy b/test/regress/regress1/sygus/temp_input_to_synth_ic-error-121418.sy
new file mode 100644
index 000000000..4efd90314
--- /dev/null
+++ b/test/regress/regress1/sygus/temp_input_to_synth_ic-error-121418.sy
@@ -0,0 +1,26 @@
+; REQUIRES: symfpu
+; EXPECT: unsat
+; COMMAND-LINE: --sygus-out=status
+(set-logic ALL)
+(define-sort FP () (_ FloatingPoint 3 5))
+(synth-fun IC ((t FP)) Bool
+ ((Start Bool (
+ true
+ false
+ (fp.isZero StartFP)
+ (ite Start Start Start)
+ ))
+ (StartFP FP (
+ t
+ (fp.sub StartRM StartFP StartFP)
+ (fp.max StartFP StartFP)
+ ))
+ (StartRM RoundingMode
+ (RNE))
+))
+
+(constraint (not (IC (fp #b0 #b110 #b1001) )))
+(constraint (not (IC (fp #b1 #b101 #b1101) )))
+(constraint (not (IC (fp #b1 #b001 #b0110) )))
+(constraint (IC (fp #b0 #b001 #b0001) ))
+(check-synth)
diff --git a/test/regress/regress2/sygus/min_IC_1.sy b/test/regress/regress2/sygus/min_IC_1.sy
new file mode 100644
index 000000000..92e171312
--- /dev/null
+++ b/test/regress/regress2/sygus/min_IC_1.sy
@@ -0,0 +1,25 @@
+; REQUIRES: symfpu
+; EXPECT: unsat
+; COMMAND-LINE: --sygus-out=status
+(set-logic ALL)
+(define-sort FP () (_ FloatingPoint 3 5))
+(define-fun IC ((t FP)) Bool (=> (fp.isInfinite t) (fp.isNegative t)))
+
+(synth-fun simpIC ((t FP)) Bool
+ ((Start Bool (
+ (and Start Start)
+ (not Start)
+
+ (fp.isInfinite StartFP)
+ (fp.isNegative StartFP)
+
+ (ite Start Start Start)
+ ))
+ (StartFP FP (
+ t
+ ))
+))
+
+(declare-var x FP)
+(constraint (= (simpIC x) (IC x)))
+(check-synth)
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index 4ba7205a5..4659f2647 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -89,5 +89,6 @@ add_subdirectory(expr)
add_subdirectory(main)
add_subdirectory(parser)
add_subdirectory(prop)
+add_subdirectory(proof)
add_subdirectory(theory)
add_subdirectory(util)
diff --git a/test/unit/api/CMakeLists.txt b/test/unit/api/CMakeLists.txt
index 8a6be70b9..ca3c59750 100644
--- a/test/unit/api/CMakeLists.txt
+++ b/test/unit/api/CMakeLists.txt
@@ -1,7 +1,8 @@
#-----------------------------------------------------------------------------#
# Add unit tests
+cvc4_add_unit_test_black(datatype_api_black api)
+cvc4_add_unit_test_black(opterm_black api)
cvc4_add_unit_test_black(solver_black api)
cvc4_add_unit_test_black(sort_black api)
cvc4_add_unit_test_black(term_black api)
-cvc4_add_unit_test_black(opterm_black api)
diff --git a/test/unit/api/datatype_api_black.h b/test/unit/api/datatype_api_black.h
new file mode 100644
index 000000000..bca6a35ce
--- /dev/null
+++ b/test/unit/api/datatype_api_black.h
@@ -0,0 +1,57 @@
+/********************* */
+/*! \file datatype_api_black.h
+ ** \verbatim
+ ** 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
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Black box testing of the datatype classes of the C++ API.
+ **
+ ** Black box testing of the datatype classes of the C++ API.
+ **/
+
+#include <cxxtest/TestSuite.h>
+
+#include "api/cvc4cpp.h"
+
+using namespace CVC4::api;
+
+class DatatypeBlack : public CxxTest::TestSuite
+{
+ public:
+ void setUp() override;
+ void tearDown() override;
+
+ void testMkDatatypeSort();
+
+ private:
+ Solver d_solver;
+};
+
+void DatatypeBlack::setUp() {}
+
+void DatatypeBlack::tearDown() {}
+
+void DatatypeBlack::testMkDatatypeSort()
+{
+ DatatypeDecl dtypeSpec("list");
+ DatatypeConstructorDecl cons("cons");
+ DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
+ cons.addSelector(head);
+ dtypeSpec.addConstructor(cons);
+ DatatypeConstructorDecl nil("nil");
+ dtypeSpec.addConstructor(nil);
+ Sort listSort = d_solver.mkDatatypeSort(dtypeSpec);
+ Datatype d = listSort.getDatatype();
+ DatatypeConstructor consConstr = d[0];
+ DatatypeConstructor nilConstr = d[1];
+ TS_ASSERT_THROWS(d[2], CVC4ApiException&);
+ TS_ASSERT(consConstr.isResolved());
+ TS_ASSERT(nilConstr.isResolved());
+ TS_ASSERT_THROWS_NOTHING(consConstr.getConstructorTerm());
+ TS_ASSERT_THROWS_NOTHING(nilConstr.getConstructorTerm());
+}
diff --git a/test/unit/api/solver_black.h b/test/unit/api/solver_black.h
index b0249b8a0..d2226f278 100644
--- a/test/unit/api/solver_black.h
+++ b/test/unit/api/solver_black.h
@@ -1,5 +1,5 @@
/********************* */
-/*! \file api_guards_black.h
+/*! \file solver_black.h
** \verbatim
** Top contributors (to current version):
** Aina Niemetz
@@ -9,14 +9,15 @@
** All rights reserved. See the file COPYING in the top-level source
** directory for licensing information.\endverbatim
**
- ** \brief Black box testing of the guards of the C++ API functions.
+ ** \brief Black box testing of the Solver class of the C++ API.
**
- ** Black box testing of the guards of the C++ API functions.
+ ** Black box testing of the Solver class of the C++ API.
**/
#include <cxxtest/TestSuite.h>
#include "api/cvc4cpp.h"
+#include "base/configuration.h"
using namespace CVC4::api;
@@ -28,320 +29,794 @@ class SolverBlack : public CxxTest::TestSuite
void testGetBooleanSort();
void testGetIntegerSort();
+ void testGetNullSort();
void testGetRealSort();
void testGetRegExpSort();
- void testGetStringSort();
void testGetRoundingmodeSort();
+ void testGetStringSort();
void testMkArraySort();
void testMkBitVectorSort();
void testMkFloatingPointSort();
void testMkDatatypeSort();
void testMkFunctionSort();
+ void testMkOpTerm();
void testMkParamSort();
void testMkPredicateSort();
void testMkRecordSort();
void testMkSetSort();
void testMkSortConstructorSort();
- void testMkUninterpretedSort();
void testMkTupleSort();
+ void testMkUninterpretedSort();
+
+ void testMkAbstractValue();
+ void testMkBitVector();
+ void testMkBoolean();
+ void testMkBoundVar();
+ void testMkEmptySet();
+ void testMkFalse();
+ void testMkFloatingPoint();
+ void testMkNaN();
+ void testMkNegInf();
+ void testMkNegZero();
+ void testMkPi();
+ void testMkPosInf();
+ void testMkPosZero();
+ void testMkReal();
+ void testMkRegexpEmpty();
+ void testMkRegexpSigma();
+ void testMkRoundingMode();
+ void testMkSepNil();
+ void testMkString();
+ void testMkTerm();
+ void testMkTrue();
+ void testMkTuple();
+ void testMkUninterpretedConst();
+ void testMkUniverseSet();
+ void testMkVar();
void testDeclareFun();
void testDefineFun();
void testDefineFunRec();
void testDefineFunsRec();
- void testMkRegexpEmpty();
- void testMkRegexpSigma();
+ void testSetInfo();
+ void testSetLogic();
+ void testSetOption();
private:
- Solver d_solver;
+ std::unique_ptr<Solver> d_solver;
};
-void SolverBlack::setUp() {}
+void SolverBlack::setUp() { d_solver.reset(new Solver()); }
void SolverBlack::tearDown() {}
void SolverBlack::testGetBooleanSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.getBooleanSort());
+ TS_ASSERT_THROWS_NOTHING(d_solver->getBooleanSort());
}
void SolverBlack::testGetIntegerSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.getIntegerSort());
+ TS_ASSERT_THROWS_NOTHING(d_solver->getIntegerSort());
+}
+
+void SolverBlack::testGetNullSort()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver->getNullSort());
}
void SolverBlack::testGetRealSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.getRealSort());
+ TS_ASSERT_THROWS_NOTHING(d_solver->getRealSort());
}
void SolverBlack::testGetRegExpSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.getRegExpSort());
+ TS_ASSERT_THROWS_NOTHING(d_solver->getRegExpSort());
}
void SolverBlack::testGetStringSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.getStringSort());
+ TS_ASSERT_THROWS_NOTHING(d_solver->getStringSort());
}
void SolverBlack::testGetRoundingmodeSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.getRoundingmodeSort());
+ TS_ASSERT_THROWS_NOTHING(d_solver->getRoundingmodeSort());
}
void SolverBlack::testMkArraySort()
{
- Sort boolSort = d_solver.getBooleanSort();
- Sort intSort = d_solver.getIntegerSort();
- Sort realSort = d_solver.getRealSort();
- Sort bvSort = d_solver.mkBitVectorSort(32);
- Sort fpSort = d_solver.mkFloatingPointSort(3, 5);
- TS_ASSERT_THROWS_NOTHING(d_solver.mkArraySort(boolSort, boolSort));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkArraySort(intSort, intSort));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkArraySort(realSort, realSort));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkArraySort(bvSort, bvSort));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkArraySort(fpSort, fpSort));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkArraySort(boolSort, intSort));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkArraySort(realSort, bvSort));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkArraySort(bvSort, fpSort));
+ Sort boolSort = d_solver->getBooleanSort();
+ Sort intSort = d_solver->getIntegerSort();
+ Sort realSort = d_solver->getRealSort();
+ Sort bvSort = d_solver->mkBitVectorSort(32);
+ Sort fpSort = d_solver->mkFloatingPointSort(3, 5);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkArraySort(boolSort, boolSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkArraySort(intSort, intSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkArraySort(realSort, realSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkArraySort(bvSort, bvSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkArraySort(fpSort, fpSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkArraySort(boolSort, intSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkArraySort(realSort, bvSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkArraySort(bvSort, fpSort));
}
void SolverBlack::testMkBitVectorSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkBitVectorSort(32));
- TS_ASSERT_THROWS(d_solver.mkBitVectorSort(0), CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBitVectorSort(32));
+ TS_ASSERT_THROWS(d_solver->mkBitVectorSort(0), CVC4ApiException&);
}
void SolverBlack::testMkFloatingPointSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkFloatingPointSort(4, 8));
- TS_ASSERT_THROWS(d_solver.mkFloatingPointSort(0, 8), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.mkFloatingPointSort(4, 0), CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkFloatingPointSort(4, 8));
+ TS_ASSERT_THROWS(d_solver->mkFloatingPointSort(0, 8), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkFloatingPointSort(4, 0), CVC4ApiException&);
}
void SolverBlack::testMkDatatypeSort()
{
DatatypeDecl dtypeSpec("list");
DatatypeConstructorDecl cons("cons");
- DatatypeSelectorDecl head("head", d_solver.getIntegerSort());
+ DatatypeSelectorDecl head("head", d_solver->getIntegerSort());
cons.addSelector(head);
dtypeSpec.addConstructor(cons);
DatatypeConstructorDecl nil("nil");
dtypeSpec.addConstructor(nil);
- TS_ASSERT_THROWS_NOTHING(d_solver.mkDatatypeSort(dtypeSpec));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkDatatypeSort(dtypeSpec));
DatatypeDecl throwsDtypeSpec("list");
- TS_ASSERT_THROWS(d_solver.mkDatatypeSort(throwsDtypeSpec), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkDatatypeSort(throwsDtypeSpec),
+ CVC4ApiException&);
}
void SolverBlack::testMkFunctionSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkFunctionSort(
- d_solver.mkUninterpretedSort("u"), d_solver.getIntegerSort()));
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS(d_solver.mkFunctionSort(funSort, d_solver.getIntegerSort()),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.mkFunctionSort(d_solver.getIntegerSort(), funSort),
- CVC4ApiException&);
- TS_ASSERT_THROWS_NOTHING(d_solver.mkFunctionSort(
- {d_solver.mkUninterpretedSort("u"), d_solver.getIntegerSort()},
- d_solver.getIntegerSort()));
- Sort funSort2 = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkFunctionSort(
+ d_solver->mkUninterpretedSort("u"), d_solver->getIntegerSort()));
+ Sort funSort = d_solver->mkFunctionSort(d_solver->mkUninterpretedSort("u"),
+ d_solver->getIntegerSort());
TS_ASSERT_THROWS(
- d_solver.mkFunctionSort({funSort2, d_solver.mkUninterpretedSort("u")},
- d_solver.getIntegerSort()),
+ d_solver->mkFunctionSort(funSort, d_solver->getIntegerSort()),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(
+ d_solver->mkFunctionSort(d_solver->getIntegerSort(), funSort),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkFunctionSort(
+ {d_solver->mkUninterpretedSort("u"), d_solver->getIntegerSort()},
+ d_solver->getIntegerSort()));
+ Sort funSort2 = d_solver->mkFunctionSort(d_solver->mkUninterpretedSort("u"),
+ d_solver->getIntegerSort());
+ TS_ASSERT_THROWS(
+ d_solver->mkFunctionSort({funSort2, d_solver->mkUninterpretedSort("u")},
+ d_solver->getIntegerSort()),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(
+ d_solver->mkFunctionSort(
+ {d_solver->getIntegerSort(), d_solver->mkUninterpretedSort("u")},
+ funSort2),
CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.mkFunctionSort({d_solver.getIntegerSort(),
- d_solver.mkUninterpretedSort("u")},
- funSort2),
- CVC4ApiException&);
}
void SolverBlack::testMkParamSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkParamSort("T"));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkParamSort(""));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkParamSort("T"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkParamSort(""));
}
void SolverBlack::testMkPredicateSort()
{
TS_ASSERT_THROWS_NOTHING(
- d_solver.mkPredicateSort({d_solver.getIntegerSort()}));
- TS_ASSERT_THROWS(d_solver.mkPredicateSort({}), CVC4ApiException&);
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
+ d_solver->mkPredicateSort({d_solver->getIntegerSort()}));
+ TS_ASSERT_THROWS(d_solver->mkPredicateSort({}), CVC4ApiException&);
+ Sort funSort = d_solver->mkFunctionSort(d_solver->mkUninterpretedSort("u"),
+ d_solver->getIntegerSort());
TS_ASSERT_THROWS(
- d_solver.mkPredicateSort({d_solver.getIntegerSort(), funSort}),
+ d_solver->mkPredicateSort({d_solver->getIntegerSort(), funSort}),
CVC4ApiException&);
}
void SolverBlack::testMkRecordSort()
{
std::vector<std::pair<std::string, Sort>> fields = {
- std::make_pair("b", d_solver.getBooleanSort()),
- std::make_pair("bv", d_solver.mkBitVectorSort(8)),
- std::make_pair("i", d_solver.getIntegerSort())};
+ std::make_pair("b", d_solver->getBooleanSort()),
+ std::make_pair("bv", d_solver->mkBitVectorSort(8)),
+ std::make_pair("i", d_solver->getIntegerSort())};
std::vector<std::pair<std::string, Sort>> empty;
- TS_ASSERT_THROWS_NOTHING(d_solver.mkRecordSort(fields));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkRecordSort(empty));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkRecordSort(fields));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkRecordSort(empty));
}
void SolverBlack::testMkSetSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkSetSort(d_solver.getBooleanSort()));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkSetSort(d_solver.getIntegerSort()));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkSetSort(d_solver.mkBitVectorSort(4)));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkSetSort(d_solver->getBooleanSort()));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkSetSort(d_solver->getIntegerSort()));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkSetSort(d_solver->mkBitVectorSort(4)));
}
void SolverBlack::testMkUninterpretedSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkUninterpretedSort("u"));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkUninterpretedSort(""));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkUninterpretedSort("u"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkUninterpretedSort(""));
}
void SolverBlack::testMkSortConstructorSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkSortConstructorSort("s", 2));
- TS_ASSERT_THROWS_NOTHING(d_solver.mkSortConstructorSort("", 2));
- TS_ASSERT_THROWS(d_solver.mkSortConstructorSort("", 0), CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkSortConstructorSort("s", 2));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkSortConstructorSort("", 2));
+ TS_ASSERT_THROWS(d_solver->mkSortConstructorSort("", 0), CVC4ApiException&);
}
void SolverBlack::testMkTupleSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver.mkTupleSort({d_solver.getIntegerSort()}));
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS(d_solver.mkTupleSort({d_solver.getIntegerSort(), funSort}),
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTupleSort({d_solver->getIntegerSort()}));
+ Sort funSort = d_solver->mkFunctionSort(d_solver->mkUninterpretedSort("u"),
+ d_solver->getIntegerSort());
+ TS_ASSERT_THROWS(d_solver->mkTupleSort({d_solver->getIntegerSort(), funSort}),
+ CVC4ApiException&);
+}
+
+void SolverBlack::testMkBitVector()
+{
+ uint32_t size0 = 0, size1 = 8, size2 = 32, val1 = 2;
+ uint64_t val2 = 2;
+ TS_ASSERT_THROWS(d_solver->mkBitVector(size0, val1), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkBitVector(size0, val2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkBitVector("", 2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkBitVector("10", 3), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkBitVector("20", 2), CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBitVector(size1, val1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBitVector(size2, val2));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBitVector("1010", 2));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBitVector("1010", 16));
+ TS_ASSERT_THROWS(d_solver->mkBitVector(8, "101010101", 2), CVC4ApiException&);
+ TS_ASSERT_EQUALS(d_solver->mkBitVector(8, "01010101", 2).toString(),
+ "0bin01010101");
+ TS_ASSERT_EQUALS(d_solver->mkBitVector(8, "F", 16).toString(),
+ "0bin00001111");
+}
+
+void SolverBlack::testMkBoundVar()
+{
+ Sort boolSort = d_solver->getBooleanSort();
+ Sort intSort = d_solver->getIntegerSort();
+ Sort funSort = d_solver->mkFunctionSort(intSort, boolSort);
+ TS_ASSERT_THROWS(d_solver->mkBoundVar(Sort()), CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBoundVar(boolSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBoundVar(funSort));
+ TS_ASSERT_THROWS(d_solver->mkBoundVar("a", Sort()), CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBoundVar(std::string("b"), boolSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBoundVar("", funSort));
+}
+
+void SolverBlack::testMkBoolean()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBoolean(true));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkBoolean(false));
+}
+
+void SolverBlack::testMkRoundingMode()
+{
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver->mkRoundingMode(RoundingMode::ROUND_TOWARD_ZERO));
+}
+
+void SolverBlack::testMkUninterpretedConst()
+{
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver->mkUninterpretedConst(d_solver->getBooleanSort(), 1));
+ TS_ASSERT_THROWS(d_solver->mkUninterpretedConst(Sort(), 1),
+ CVC4ApiException&);
+}
+
+void SolverBlack::testMkAbstractValue()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkAbstractValue(std::string("1")));
+ TS_ASSERT_THROWS(d_solver->mkAbstractValue(std::string("0")),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkAbstractValue(std::string("-1")),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkAbstractValue(std::string("1.2")),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkAbstractValue("1/2"), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkAbstractValue("asdf"), CVC4ApiException&);
+
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkAbstractValue((uint32_t)1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkAbstractValue((int32_t)1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkAbstractValue((uint64_t)1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkAbstractValue((int64_t)1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkAbstractValue((int32_t)-1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkAbstractValue((int64_t)-1));
+ TS_ASSERT_THROWS(d_solver->mkAbstractValue(0), CVC4ApiException&);
+}
+
+void SolverBlack::testMkFloatingPoint()
+{
+ Term t1 = d_solver->mkBitVector(8);
+ Term t2 = d_solver->mkBitVector(4);
+ Term t3 = d_solver->mkReal(2);
+ if (CVC4::Configuration::isBuiltWithSymFPU())
+ {
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkFloatingPoint(3, 5, t1));
+ }
+ else
+ {
+ TS_ASSERT_THROWS(d_solver->mkFloatingPoint(3, 5, t1), CVC4ApiException&);
+ }
+ TS_ASSERT_THROWS(d_solver->mkFloatingPoint(0, 5, Term()), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkFloatingPoint(0, 5, t1), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkFloatingPoint(3, 0, t1), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkFloatingPoint(3, 5, t2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkFloatingPoint(3, 5, t2), CVC4ApiException&);
+}
+
+void SolverBlack::testMkEmptySet()
+{
+ TS_ASSERT_THROWS(d_solver->mkEmptySet(d_solver->getBooleanSort()),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkEmptySet(Sort()));
+}
+
+void SolverBlack::testMkFalse()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkFalse());
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkFalse());
+}
+
+void SolverBlack::testMkNaN()
+{
+ if (CVC4::Configuration::isBuiltWithSymFPU())
+ {
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkNaN(3, 5));
+ }
+ else
+ {
+ TS_ASSERT_THROWS(d_solver->mkNaN(3, 5), CVC4ApiException&);
+ }
+}
+
+void SolverBlack::testMkNegZero()
+{
+ if (CVC4::Configuration::isBuiltWithSymFPU())
+ {
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkNegZero(3, 5));
+ }
+ else
+ {
+ TS_ASSERT_THROWS(d_solver->mkNegZero(3, 5), CVC4ApiException&);
+ }
+}
+
+void SolverBlack::testMkNegInf()
+{
+ if (CVC4::Configuration::isBuiltWithSymFPU())
+ {
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkNegInf(3, 5));
+ }
+ else
+ {
+ TS_ASSERT_THROWS(d_solver->mkNegInf(3, 5), CVC4ApiException&);
+ }
+}
+
+void SolverBlack::testMkPosInf()
+{
+ if (CVC4::Configuration::isBuiltWithSymFPU())
+ {
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkPosInf(3, 5));
+ }
+ else
+ {
+ TS_ASSERT_THROWS(d_solver->mkPosInf(3, 5), CVC4ApiException&);
+ }
+}
+
+void SolverBlack::testMkPosZero()
+{
+ if (CVC4::Configuration::isBuiltWithSymFPU())
+ {
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkPosZero(3, 5));
+ }
+ else
+ {
+ TS_ASSERT_THROWS(d_solver->mkPosZero(3, 5), CVC4ApiException&);
+ }
+}
+
+void SolverBlack::testMkOpTerm()
+{
+ // mkOpTerm(Kind kind, Kind k)
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkOpTerm(CHAIN_OP, EQUAL));
+ TS_ASSERT_THROWS(d_solver->mkOpTerm(BITVECTOR_EXTRACT_OP, EQUAL),
+ CVC4ApiException&);
+
+ // mkOpTerm(Kind kind, const std::string& arg)
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkOpTerm(RECORD_UPDATE_OP, "asdf"));
+ TS_ASSERT_THROWS(d_solver->mkOpTerm(BITVECTOR_EXTRACT_OP, "asdf"),
+ CVC4ApiException&);
+
+ // mkOpTerm(Kind kind, uint32_t arg)
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkOpTerm(DIVISIBLE_OP, 1));
+ TS_ASSERT_THROWS(d_solver->mkOpTerm(BITVECTOR_EXTRACT_OP, 1),
+ CVC4ApiException&);
+
+ // mkOpTerm(Kind kind, uint32_t arg1, uint32_t arg2)
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkOpTerm(BITVECTOR_EXTRACT_OP, 1, 1));
+ TS_ASSERT_THROWS(d_solver->mkOpTerm(DIVISIBLE_OP, 1, 2), CVC4ApiException&);
+}
+
+void SolverBlack::testMkPi() { TS_ASSERT_THROWS_NOTHING(d_solver->mkPi()); }
+
+void SolverBlack::testMkReal()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal("123"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal("1.23"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal("1/23"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal("12/3"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(".2"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal("2."));
+ TS_ASSERT_THROWS(d_solver->mkReal(nullptr), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal(""), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal("asdf"), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal("1.2/3"), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal("."), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal("/"), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal("2/"), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal("/2"), CVC4ApiException&);
+
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(std::string("123")));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(std::string("1.23")));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(std::string("1/23")));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(std::string("12/3")));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(std::string(".2")));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(std::string("2.")));
+ TS_ASSERT_THROWS(d_solver->mkReal(std::string("")), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal(std::string("asdf")), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal(std::string("1.2/3")), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal(std::string(".")), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal(std::string("/")), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal(std::string("2/")), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkReal(std::string("/2")), CVC4ApiException&);
+
+ int32_t val1 = 1;
+ int64_t val2 = -1;
+ uint32_t val3 = 1;
+ uint64_t val4 = -1;
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(val1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(val2));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(val3));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(val4));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(val4));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(val1, val1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(val2, val2));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(val3, val3));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkReal(val4, val4));
+}
+
+void SolverBlack::testMkRegexpEmpty()
+{
+ Sort strSort = d_solver->getStringSort();
+ Term s = d_solver->mkVar("s", strSort);
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver->mkTerm(STRING_IN_REGEXP, s, d_solver->mkRegexpEmpty()));
+}
+
+void SolverBlack::testMkRegexpSigma()
+{
+ Sort strSort = d_solver->getStringSort();
+ Term s = d_solver->mkVar("s", strSort);
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver->mkTerm(STRING_IN_REGEXP, s, d_solver->mkRegexpSigma()));
+}
+
+void SolverBlack::testMkSepNil()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkSepNil(d_solver->getBooleanSort()));
+ TS_ASSERT_THROWS(d_solver->mkSepNil(Sort()), CVC4ApiException&);
+}
+
+void SolverBlack::testMkString()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkString(""));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkString("asdfasdf"));
+ TS_ASSERT_EQUALS(d_solver->mkString("asdf\\nasdf").toString(),
+ "\"asdf\\\\nasdf\"");
+ TS_ASSERT_EQUALS(d_solver->mkString("asdf\\nasdf", true).toString(),
+ "\"asdf\\nasdf\"");
+}
+
+void SolverBlack::testMkTerm()
+{
+ Sort bv32 = d_solver->mkBitVectorSort(32);
+ Term a = d_solver->mkVar("a", bv32);
+ Term b = d_solver->mkVar("b", bv32);
+ std::vector<Term> v1 = {a, b};
+ std::vector<Term> v2 = {a, Term()};
+ std::vector<Term> v3 = {a, d_solver->mkTrue()};
+ std::vector<Term> v4 = {d_solver->mkReal(1), d_solver->mkReal(2)};
+ std::vector<Term> v5 = {d_solver->mkReal(1), Term()};
+ OpTerm opterm1 = d_solver->mkOpTerm(BITVECTOR_EXTRACT_OP, 2, 1);
+ OpTerm opterm2 = d_solver->mkOpTerm(DIVISIBLE_OP, 1);
+ OpTerm opterm3 = d_solver->mkOpTerm(CHAIN_OP, EQUAL);
+
+ // mkTerm(Kind kind) const
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(PI));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(REGEXP_EMPTY));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(REGEXP_SIGMA));
+ TS_ASSERT_THROWS(d_solver->mkTerm(CONST_BITVECTOR), CVC4ApiException&);
+
+ // mkTerm(Kind kind, Sort sort) const
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver->mkTerm(SEP_NIL, d_solver->getBooleanSort()));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(SEP_NIL, Sort()));
+
+ // mkTerm(Kind kind, Term child) const
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(NOT, d_solver->mkTrue()));
+ TS_ASSERT_THROWS(d_solver->mkTerm(NOT, Term()), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkTerm(NOT, a), CVC4ApiException&);
+
+ // mkTerm(Kind kind, Term child1, Term child2) const
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(EQUAL, a, b));
+ TS_ASSERT_THROWS(d_solver->mkTerm(EQUAL, Term(), b), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkTerm(EQUAL, a, Term()), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkTerm(EQUAL, a, d_solver->mkTrue()),
+ CVC4ApiException&);
+
+ // mkTerm(Kind kind, Term child1, Term child2, Term child3) const
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(
+ ITE, d_solver->mkTrue(), d_solver->mkTrue(), d_solver->mkTrue()));
+ TS_ASSERT_THROWS(
+ d_solver->mkTerm(ITE, Term(), d_solver->mkTrue(), d_solver->mkTrue()),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(
+ d_solver->mkTerm(ITE, d_solver->mkTrue(), Term(), d_solver->mkTrue()),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(
+ d_solver->mkTerm(ITE, d_solver->mkTrue(), d_solver->mkTrue(), Term()),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(
+ d_solver->mkTerm(ITE, d_solver->mkTrue(), d_solver->mkTrue(), b),
+ CVC4ApiException&);
+
+ // mkTerm(Kind kind, const std::vector<Term>& children) const
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(EQUAL, v1));
+ TS_ASSERT_THROWS(d_solver->mkTerm(EQUAL, v2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkTerm(EQUAL, v3), CVC4ApiException&);
+
+ // mkTerm(OpTerm opTerm, Term child) const
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(opterm1, a));
+ TS_ASSERT_THROWS(d_solver->mkTerm(opterm2, a), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkTerm(opterm1, Term()), CVC4ApiException&);
+
+ // mkTerm(OpTerm opTerm, Term child1, Term child2) const
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver->mkTerm(opterm3, d_solver->mkReal(1), d_solver->mkReal(2)));
+ TS_ASSERT_THROWS(d_solver->mkTerm(opterm1, a, b), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkTerm(opterm3, d_solver->mkReal(1), Term()),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkTerm(opterm3, Term(), d_solver->mkReal(1)),
+ CVC4ApiException&);
+
+ // mkTerm(OpTerm opTerm, Term child1, Term child2, Term child3) const
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(
+ opterm3, d_solver->mkReal(1), d_solver->mkReal(1), d_solver->mkReal(2)));
+ TS_ASSERT_THROWS(d_solver->mkTerm(opterm1, a, b, a), CVC4ApiException&);
+ TS_ASSERT_THROWS(
+ d_solver->mkTerm(
+ opterm3, d_solver->mkReal(1), d_solver->mkReal(1), Term()),
+ CVC4ApiException&);
+
+ // mkTerm(OpTerm opTerm, const std::vector<Term>& children) const
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTerm(opterm3, v4));
+ TS_ASSERT_THROWS(d_solver->mkTerm(opterm3, v5), CVC4ApiException&);
+}
+
+void SolverBlack::testMkTrue()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTrue());
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTrue());
+}
+
+void SolverBlack::testMkTuple()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkTuple(
+ {d_solver->mkBitVectorSort(3)}, {d_solver->mkBitVector("101", 2)}));
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver->mkTuple({d_solver->getRealSort()}, {d_solver->mkReal("5")}));
+
+ TS_ASSERT_THROWS(d_solver->mkTuple({}, {d_solver->mkBitVector("101", 2)}),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkTuple({d_solver->mkBitVectorSort(4)},
+ {d_solver->mkBitVector("101", 2)}),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->mkTuple({d_solver->getIntegerSort()},
+ {d_solver->mkReal("5.3")}),
CVC4ApiException&);
}
+void SolverBlack::testMkUniverseSet()
+{
+ TS_ASSERT_THROWS(d_solver->mkUniverseSet(Sort()), CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkUniverseSet(d_solver->getBooleanSort()));
+}
+
+void SolverBlack::testMkVar()
+{
+ Sort boolSort = d_solver->getBooleanSort();
+ Sort intSort = d_solver->getIntegerSort();
+ Sort funSort = d_solver->mkFunctionSort(intSort, boolSort);
+ TS_ASSERT_THROWS(d_solver->mkVar(Sort()), CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkVar(boolSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkVar(funSort));
+ TS_ASSERT_THROWS(d_solver->mkVar("a", Sort()), CVC4ApiException&);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkVar(std::string("b"), boolSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkVar("", funSort));
+}
+
void SolverBlack::testDeclareFun()
{
- Sort bvSort = d_solver.mkBitVectorSort(32);
- Sort funSort = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- TS_ASSERT_THROWS_NOTHING(d_solver.declareFun("f1", bvSort));
- TS_ASSERT_THROWS_NOTHING(d_solver.declareFun("f2", funSort));
+ Sort bvSort = d_solver->mkBitVectorSort(32);
+ Sort funSort = d_solver->mkFunctionSort(d_solver->mkUninterpretedSort("u"),
+ d_solver->getIntegerSort());
+ TS_ASSERT_THROWS_NOTHING(d_solver->declareFun("f1", bvSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->declareFun("f2", funSort));
TS_ASSERT_THROWS_NOTHING(
- d_solver.declareFun("f3", {bvSort, d_solver.getIntegerSort()}, bvSort));
- TS_ASSERT_THROWS(d_solver.declareFun("f4", {bvSort, funSort}, bvSort),
+ d_solver->declareFun("f3", {bvSort, d_solver->getIntegerSort()}, bvSort));
+ TS_ASSERT_THROWS(d_solver->declareFun("f4", {bvSort, funSort}, bvSort),
CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.declareFun("f5", {bvSort, bvSort}, funSort),
+ TS_ASSERT_THROWS(d_solver->declareFun("f5", {bvSort, bvSort}, funSort),
CVC4ApiException&);
}
void SolverBlack::testDefineFun()
{
- Sort bvSort = d_solver.mkBitVectorSort(32);
- Sort funSort1 = d_solver.mkFunctionSort({bvSort, bvSort}, bvSort);
- Sort funSort2 = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- Term b1 = d_solver.mkBoundVar("b1", bvSort);
- Term b11 = d_solver.mkBoundVar("b1", bvSort);
- Term b2 = d_solver.mkBoundVar("b2", d_solver.getIntegerSort());
- Term b3 = d_solver.mkBoundVar("b3", funSort2);
- Term v1 = d_solver.mkBoundVar("v1", bvSort);
- Term v2 = d_solver.mkBoundVar("v2", d_solver.getIntegerSort());
- Term v3 = d_solver.mkVar("v3", funSort2);
- Term f1 = d_solver.declareFun("f1", funSort1);
- Term f2 = d_solver.declareFun("f2", funSort2);
- Term f3 = d_solver.declareFun("f3", bvSort);
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFun("f", {}, bvSort, v1));
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFun("ff", {b1, b2}, bvSort, v1));
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFun(f1, {b1, b11}, v1));
- TS_ASSERT_THROWS(d_solver.defineFun("fff", {b1}, bvSort, v3),
+ Sort bvSort = d_solver->mkBitVectorSort(32);
+ Sort funSort1 = d_solver->mkFunctionSort({bvSort, bvSort}, bvSort);
+ Sort funSort2 = d_solver->mkFunctionSort(d_solver->mkUninterpretedSort("u"),
+ d_solver->getIntegerSort());
+ Term b1 = d_solver->mkBoundVar("b1", bvSort);
+ Term b11 = d_solver->mkBoundVar("b1", bvSort);
+ Term b2 = d_solver->mkBoundVar("b2", d_solver->getIntegerSort());
+ Term b3 = d_solver->mkBoundVar("b3", funSort2);
+ Term v1 = d_solver->mkBoundVar("v1", bvSort);
+ Term v2 = d_solver->mkBoundVar("v2", d_solver->getIntegerSort());
+ Term v3 = d_solver->mkVar("v3", funSort2);
+ Term f1 = d_solver->declareFun("f1", funSort1);
+ Term f2 = d_solver->declareFun("f2", funSort2);
+ Term f3 = d_solver->declareFun("f3", bvSort);
+ TS_ASSERT_THROWS_NOTHING(d_solver->defineFun("f", {}, bvSort, v1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->defineFun("ff", {b1, b2}, bvSort, v1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->defineFun(f1, {b1, b11}, v1));
+ TS_ASSERT_THROWS(d_solver->defineFun("fff", {b1}, bvSort, v3),
CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun("ffff", {b1}, funSort2, v3),
+ TS_ASSERT_THROWS(d_solver->defineFun("ffff", {b1}, funSort2, v3),
CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun("fffff", {b1, b3}, bvSort, v1),
+ TS_ASSERT_THROWS(d_solver->defineFun("fffff", {b1, b3}, bvSort, v1),
CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun(f1, {b1}, v1), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun(f1, {b1, b11}, v2), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun(f1, {b1, b11}, v3), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun(f2, {b1}, v2), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFun(f3, {b1}, v1), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->defineFun(f1, {b1}, v1), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->defineFun(f1, {b1, b11}, v2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->defineFun(f1, {b1, b11}, v3), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->defineFun(f2, {b1}, v2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->defineFun(f3, {b1}, v1), CVC4ApiException&);
}
void SolverBlack::testDefineFunRec()
{
- Sort bvSort = d_solver.mkBitVectorSort(32);
- Sort funSort1 = d_solver.mkFunctionSort({bvSort, bvSort}, bvSort);
- Sort funSort2 = d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"),
- d_solver.getIntegerSort());
- Term b1 = d_solver.mkBoundVar("b1", bvSort);
- Term b11 = d_solver.mkBoundVar("b1", bvSort);
- Term b2 = d_solver.mkBoundVar("b2", d_solver.getIntegerSort());
- Term b3 = d_solver.mkBoundVar("b3", funSort2);
- Term v1 = d_solver.mkBoundVar("v1", bvSort);
- Term v2 = d_solver.mkBoundVar("v2", d_solver.getIntegerSort());
- Term v3 = d_solver.mkVar("v3", funSort2);
- Term f1 = d_solver.declareFun("f1", funSort1);
- Term f2 = d_solver.declareFun("f2", funSort2);
- Term f3 = d_solver.declareFun("f3", bvSort);
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFunRec("f", {}, bvSort, v1));
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFunRec("ff", {b1, b2}, bvSort, v1));
- TS_ASSERT_THROWS_NOTHING(d_solver.defineFunRec(f1, {b1, b11}, v1));
- TS_ASSERT_THROWS(d_solver.defineFunRec("fff", {b1}, bvSort, v3),
+ Sort bvSort = d_solver->mkBitVectorSort(32);
+ Sort funSort1 = d_solver->mkFunctionSort({bvSort, bvSort}, bvSort);
+ Sort funSort2 = d_solver->mkFunctionSort(d_solver->mkUninterpretedSort("u"),
+ d_solver->getIntegerSort());
+ Term b1 = d_solver->mkBoundVar("b1", bvSort);
+ Term b11 = d_solver->mkBoundVar("b1", bvSort);
+ Term b2 = d_solver->mkBoundVar("b2", d_solver->getIntegerSort());
+ Term b3 = d_solver->mkBoundVar("b3", funSort2);
+ Term v1 = d_solver->mkBoundVar("v1", bvSort);
+ Term v2 = d_solver->mkBoundVar("v2", d_solver->getIntegerSort());
+ Term v3 = d_solver->mkVar("v3", funSort2);
+ Term f1 = d_solver->declareFun("f1", funSort1);
+ Term f2 = d_solver->declareFun("f2", funSort2);
+ Term f3 = d_solver->declareFun("f3", bvSort);
+ TS_ASSERT_THROWS_NOTHING(d_solver->defineFunRec("f", {}, bvSort, v1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->defineFunRec("ff", {b1, b2}, bvSort, v1));
+ TS_ASSERT_THROWS_NOTHING(d_solver->defineFunRec(f1, {b1, b11}, v1));
+ TS_ASSERT_THROWS(d_solver->defineFunRec("fff", {b1}, bvSort, v3),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->defineFunRec("ffff", {b1}, funSort2, v3),
CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec("ffff", {b1}, funSort2, v3),
+ TS_ASSERT_THROWS(d_solver->defineFunRec("fffff", {b1, b3}, bvSort, v1),
CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec("fffff", {b1, b3}, bvSort, v1),
+ TS_ASSERT_THROWS(d_solver->defineFunRec(f1, {b1}, v1), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->defineFunRec(f1, {b1, b11}, v2),
CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec(f1, {b1}, v1), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec(f1, {b1, b11}, v2), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec(f1, {b1, b11}, v3), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec(f2, {b1}, v2), CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunRec(f3, {b1}, v1), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->defineFunRec(f1, {b1, b11}, v3),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->defineFunRec(f2, {b1}, v2), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->defineFunRec(f3, {b1}, v1), CVC4ApiException&);
}
void SolverBlack::testDefineFunsRec()
{
- Sort uSort = d_solver.mkUninterpretedSort("u");
- Sort bvSort = d_solver.mkBitVectorSort(32);
- Sort funSort1 = d_solver.mkFunctionSort({bvSort, bvSort}, bvSort);
- Sort funSort2 = d_solver.mkFunctionSort(uSort, d_solver.getIntegerSort());
- Term b1 = d_solver.mkBoundVar("b1", bvSort);
- Term b11 = d_solver.mkBoundVar("b1", bvSort);
- Term b2 = d_solver.mkBoundVar("b2", d_solver.getIntegerSort());
- Term b3 = d_solver.mkBoundVar("b3", funSort2);
- Term b4 = d_solver.mkBoundVar("b4", uSort);
- Term v1 = d_solver.mkBoundVar("v1", bvSort);
- Term v2 = d_solver.mkBoundVar("v2", d_solver.getIntegerSort());
- Term v3 = d_solver.mkVar("v3", funSort2);
- Term v4 = d_solver.mkVar("v4", uSort);
- Term f1 = d_solver.declareFun("f1", funSort1);
- Term f2 = d_solver.declareFun("f2", funSort2);
- Term f3 = d_solver.declareFun("f3", bvSort);
+ Sort uSort = d_solver->mkUninterpretedSort("u");
+ Sort bvSort = d_solver->mkBitVectorSort(32);
+ Sort funSort1 = d_solver->mkFunctionSort({bvSort, bvSort}, bvSort);
+ Sort funSort2 = d_solver->mkFunctionSort(uSort, d_solver->getIntegerSort());
+ Term b1 = d_solver->mkBoundVar("b1", bvSort);
+ Term b11 = d_solver->mkBoundVar("b1", bvSort);
+ Term b2 = d_solver->mkBoundVar("b2", d_solver->getIntegerSort());
+ Term b3 = d_solver->mkBoundVar("b3", funSort2);
+ Term b4 = d_solver->mkBoundVar("b4", uSort);
+ Term v1 = d_solver->mkBoundVar("v1", bvSort);
+ Term v2 = d_solver->mkBoundVar("v2", d_solver->getIntegerSort());
+ Term v3 = d_solver->mkVar("v3", funSort2);
+ Term v4 = d_solver->mkVar("v4", uSort);
+ Term f1 = d_solver->declareFun("f1", funSort1);
+ Term f2 = d_solver->declareFun("f2", funSort2);
+ Term f3 = d_solver->declareFun("f3", bvSort);
TS_ASSERT_THROWS_NOTHING(
- d_solver.defineFunsRec({f1, f2}, {{b1, b11}, {b4}}, {v1, v2}));
+ d_solver->defineFunsRec({f1, f2}, {{b1, b11}, {b4}}, {v1, v2}));
TS_ASSERT_THROWS(
- d_solver.defineFunsRec({f1, f3}, {{b1, b11}, {b4}}, {v1, v2}),
+ d_solver->defineFunsRec({f1, f3}, {{b1, b11}, {b4}}, {v1, v2}),
CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunsRec({f1, f2}, {{b1}, {b4}}, {v1, v2}),
- CVC4ApiException&);
- TS_ASSERT_THROWS(d_solver.defineFunsRec({f1, f2}, {{b1, b2}, {b4}}, {v1, v2}),
+ TS_ASSERT_THROWS(d_solver->defineFunsRec({f1, f2}, {{b1}, {b4}}, {v1, v2}),
CVC4ApiException&);
TS_ASSERT_THROWS(
- d_solver.defineFunsRec({f1, f2}, {{b1, b11}, {b4}}, {v1, v4}),
+ d_solver->defineFunsRec({f1, f2}, {{b1, b2}, {b4}}, {v1, v2}),
+ CVC4ApiException&);
+ TS_ASSERT_THROWS(
+ d_solver->defineFunsRec({f1, f2}, {{b1, b11}, {b4}}, {v1, v4}),
CVC4ApiException&);
}
-void SolverBlack::testMkRegexpEmpty()
+void SolverBlack::testSetInfo()
{
- Sort strSort = d_solver.getStringSort();
- Term s = d_solver.mkVar("s", strSort);
- TS_ASSERT_THROWS_NOTHING(
- d_solver.mkTerm(STRING_IN_REGEXP, s, d_solver.mkRegexpEmpty()));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("cvc4-logic", "QF_BV"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("cvc4_logic", "QF_BV"));
+ TS_ASSERT_THROWS(d_solver->setInfo("cvc4-lagic", "QF_BV"), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->setInfo("cvc2-logic", "QF_BV"), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->setInfo("cvc4-logic", "asdf"), CVC4ApiException&);
+
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("source", "asdf"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("category", "asdf"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("difficulty", "asdf"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("filename", "asdf"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("license", "asdf"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("name", "asdf"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("notes", "asdf"));
+
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("smt-lib-version", "2"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("smt-lib-version", "2.0"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("smt-lib-version", "2.5"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("smt-lib-version", "2.6"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("smt-lib-version", "2.6.1"));
+ TS_ASSERT_THROWS(d_solver->setInfo("smt-lib-version", ".0"),
+ CVC4ApiException&);
+
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("status", "sat"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("status", "unsat"));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setInfo("status", "unknown"));
+ TS_ASSERT_THROWS(d_solver->setInfo("status", "asdf"), CVC4ApiException&);
+
+ d_solver->assertFormula(d_solver->mkTrue());
+ TS_ASSERT_THROWS(d_solver->setInfo("cvc4-logic", "QF_BV"), CVC4ApiException&);
+ TS_ASSERT_THROWS(d_solver->setInfo("cvc4_logic", "QF_BV"), CVC4ApiException&);
}
-void SolverBlack::testMkRegexpSigma()
+void SolverBlack::testSetLogic()
{
- Sort strSort = d_solver.getStringSort();
- Term s = d_solver.mkVar("s", strSort);
- TS_ASSERT_THROWS_NOTHING(
- d_solver.mkTerm(STRING_IN_REGEXP, s, d_solver.mkRegexpSigma()));
+ TS_ASSERT_THROWS_NOTHING(d_solver->setLogic("AUFLIRA"));
+ TS_ASSERT_THROWS(d_solver->setLogic("AF_BV"), CVC4ApiException&);
+ d_solver->assertFormula(d_solver->mkTrue());
+ TS_ASSERT_THROWS(d_solver->setLogic("AUFLIRA"), CVC4ApiException&);
+}
+
+void SolverBlack::testSetOption()
+{
+ TS_ASSERT_THROWS_NOTHING(d_solver->setOption("bv-sat-solver", "minisat"));
+ TS_ASSERT_THROWS(d_solver->setOption("bv-sat-solver", "1"),
+ CVC4ApiException&);
+ d_solver->assertFormula(d_solver->mkTrue());
+ TS_ASSERT_THROWS(d_solver->setOption("bv-sat-solver", "minisat"),
+ CVC4ApiException&);
}
diff --git a/test/unit/api/term_black.h b/test/unit/api/term_black.h
index ae1dfe7ba..a7f735651 100644
--- a/test/unit/api/term_black.h
+++ b/test/unit/api/term_black.h
@@ -77,7 +77,7 @@ void TermBlack::testGetKind()
Term p = d_solver.mkVar("p", funSort2);
TS_ASSERT_THROWS_NOTHING(p.getKind());
- Term zero = d_solver.mkInteger(0);
+ Term zero = d_solver.mkReal(0);
TS_ASSERT_THROWS_NOTHING(zero.getKind());
Term f_x = d_solver.mkTerm(APPLY_UF, f, x);
@@ -116,7 +116,7 @@ void TermBlack::testGetSort()
TS_ASSERT_THROWS_NOTHING(p.getSort());
TS_ASSERT(p.getSort() == funSort2);
- Term zero = d_solver.mkInteger(0);
+ Term zero = d_solver.mkReal(0);
TS_ASSERT_THROWS_NOTHING(zero.getSort());
TS_ASSERT(zero.getSort() == intSort);
@@ -161,7 +161,7 @@ void TermBlack::testNotTerm()
TS_ASSERT_THROWS(f.notTerm(), CVC4ApiException&);
Term p = d_solver.mkVar("p", funSort2);
TS_ASSERT_THROWS(p.notTerm(), CVC4ApiException&);
- Term zero = d_solver.mkInteger(0);
+ Term zero = d_solver.mkReal(0);
TS_ASSERT_THROWS(zero.notTerm(), CVC4ApiException&);
Term f_x = d_solver.mkTerm(APPLY_UF, f, x);
TS_ASSERT_THROWS(f_x.notTerm(), CVC4ApiException&);
@@ -195,7 +195,7 @@ void TermBlack::testAndTerm()
TS_ASSERT_THROWS(p.andTerm(x), CVC4ApiException&);
TS_ASSERT_THROWS(p.andTerm(f), CVC4ApiException&);
TS_ASSERT_THROWS(p.andTerm(p), CVC4ApiException&);
- Term zero = d_solver.mkInteger(0);
+ Term zero = d_solver.mkReal(0);
TS_ASSERT_THROWS(zero.andTerm(b), CVC4ApiException&);
TS_ASSERT_THROWS(zero.andTerm(x), CVC4ApiException&);
TS_ASSERT_THROWS(zero.andTerm(f), CVC4ApiException&);
@@ -259,7 +259,7 @@ void TermBlack::testOrTerm()
TS_ASSERT_THROWS(p.orTerm(x), CVC4ApiException&);
TS_ASSERT_THROWS(p.orTerm(f), CVC4ApiException&);
TS_ASSERT_THROWS(p.orTerm(p), CVC4ApiException&);
- Term zero = d_solver.mkInteger(0);
+ Term zero = d_solver.mkReal(0);
TS_ASSERT_THROWS(zero.orTerm(b), CVC4ApiException&);
TS_ASSERT_THROWS(zero.orTerm(x), CVC4ApiException&);
TS_ASSERT_THROWS(zero.orTerm(f), CVC4ApiException&);
@@ -323,7 +323,7 @@ void TermBlack::testXorTerm()
TS_ASSERT_THROWS(p.xorTerm(x), CVC4ApiException&);
TS_ASSERT_THROWS(p.xorTerm(f), CVC4ApiException&);
TS_ASSERT_THROWS(p.xorTerm(p), CVC4ApiException&);
- Term zero = d_solver.mkInteger(0);
+ Term zero = d_solver.mkReal(0);
TS_ASSERT_THROWS(zero.xorTerm(b), CVC4ApiException&);
TS_ASSERT_THROWS(zero.xorTerm(x), CVC4ApiException&);
TS_ASSERT_THROWS(zero.xorTerm(f), CVC4ApiException&);
@@ -387,7 +387,7 @@ void TermBlack::testEqTerm()
TS_ASSERT_THROWS(p.eqTerm(x), CVC4ApiException&);
TS_ASSERT_THROWS(p.eqTerm(f), CVC4ApiException&);
TS_ASSERT_THROWS_NOTHING(p.eqTerm(p));
- Term zero = d_solver.mkInteger(0);
+ Term zero = d_solver.mkReal(0);
TS_ASSERT_THROWS(zero.eqTerm(b), CVC4ApiException&);
TS_ASSERT_THROWS(zero.eqTerm(x), CVC4ApiException&);
TS_ASSERT_THROWS(zero.eqTerm(f), CVC4ApiException&);
@@ -451,7 +451,7 @@ void TermBlack::testImpTerm()
TS_ASSERT_THROWS(p.impTerm(x), CVC4ApiException&);
TS_ASSERT_THROWS(p.impTerm(f), CVC4ApiException&);
TS_ASSERT_THROWS(p.impTerm(p), CVC4ApiException&);
- Term zero = d_solver.mkInteger(0);
+ Term zero = d_solver.mkReal(0);
TS_ASSERT_THROWS(zero.impTerm(b), CVC4ApiException&);
TS_ASSERT_THROWS(zero.impTerm(x), CVC4ApiException&);
TS_ASSERT_THROWS(zero.impTerm(f), CVC4ApiException&);
@@ -515,7 +515,7 @@ void TermBlack::testIteTerm()
Term p = d_solver.mkVar("p", funSort2);
TS_ASSERT_THROWS(p.iteTerm(b, b), CVC4ApiException&);
TS_ASSERT_THROWS(p.iteTerm(x, b), CVC4ApiException&);
- Term zero = d_solver.mkInteger(0);
+ Term zero = d_solver.mkReal(0);
TS_ASSERT_THROWS(zero.iteTerm(x, x), CVC4ApiException&);
TS_ASSERT_THROWS(zero.iteTerm(x, b), CVC4ApiException&);
Term f_x = d_solver.mkTerm(APPLY_UF, f, x);
diff --git a/test/unit/proof/CMakeLists.txt b/test/unit/proof/CMakeLists.txt
new file mode 100644
index 000000000..00c893bdb
--- /dev/null
+++ b/test/unit/proof/CMakeLists.txt
@@ -0,0 +1,6 @@
+#-----------------------------------------------------------------------------#
+# Add unit tests
+
+cvc4_add_unit_test_black(drat_proof_black proof)
+cvc4_add_unit_test_black(lrat_proof_black proof)
+cvc4_add_unit_test_black(lfsc_proof_printer_black proof)
diff --git a/test/unit/proof/drat_proof_black.h b/test/unit/proof/drat_proof_black.h
new file mode 100644
index 000000000..63c8839b9
--- /dev/null
+++ b/test/unit/proof/drat_proof_black.h
@@ -0,0 +1,187 @@
+/********************* */
+/*! \file drat_proof_black.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Alex Ozdemir
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Black box testing of the DRAT proof class
+ **
+ ** In particular, tests DRAT binary parsing.
+ **/
+
+#include <cxxtest/TestSuite.h>
+
+#include <cctype>
+
+#include "proof/drat/drat_proof.h"
+
+using namespace CVC4::proof::drat;
+
+class DratProofBlack : public CxxTest::TestSuite
+{
+ public:
+ void setUp() override {}
+ void tearDown() override {}
+
+ void testParseOneAdd();
+ void testParseOneMediumAdd();
+ void testParseOneBigAdd();
+ void testParseLiteralIsTooBig();
+ void testParseLiteralOverflow();
+ void testParseClauseOverflow();
+
+ void testParseTwo();
+
+ void testOutputTwoAsText();
+ void testOutputTwoAsLfsc();
+};
+
+void DratProofBlack::testParseOneAdd()
+{
+ // a 1;
+ std::string input("a\x02\x00", 3);
+ DratProof proof = DratProof::fromBinary(input);
+
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_kind, ADDITION);
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause.size(), 1);
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause[0],
+ SatLiteral(0, false));
+}
+
+void DratProofBlack::testParseOneMediumAdd()
+{
+ // a -255;
+ std::string input("a\xff\x01\x00", 4);
+ DratProof proof = DratProof::fromBinary(input);
+
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_kind, ADDITION);
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause.size(), 1);
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause[0],
+ SatLiteral(126, true));
+}
+
+void DratProofBlack::testParseOneBigAdd()
+{
+ // a -2199023255551;
+ std::string input("a\xff\xff\xff\xff\xff\x7f\x00", 8);
+ DratProof proof = DratProof::fromBinary(input);
+
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_kind, ADDITION);
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause.size(), 1);
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause[0],
+ SatLiteral(2199023255550, true));
+}
+
+void DratProofBlack::testParseLiteralIsTooBig()
+{
+ std::string input("a\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00",
+ 14);
+ TS_ASSERT_THROWS(DratProof::fromBinary(input), InvalidDratProofException);
+}
+
+void DratProofBlack::testParseLiteralOverflow()
+{
+ std::string input("a\x80", 2);
+ TS_ASSERT_THROWS(DratProof::fromBinary(input), InvalidDratProofException);
+}
+
+void DratProofBlack::testParseClauseOverflow()
+{
+ std::string input("a\x80\x01", 3);
+ TS_ASSERT_THROWS(DratProof::fromBinary(input), InvalidDratProofException);
+}
+
+void DratProofBlack::testParseTwo()
+{
+ // d -63 -8193
+ // 129 -8191
+ std::string input("\x64\x7f\x83\x80\x01\x00\x61\x82\x02\xff\x7f\x00", 12);
+ DratProof proof = DratProof::fromBinary(input);
+
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_kind, DELETION);
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause.size(), 2);
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause[0],
+ SatLiteral(62, true));
+ TS_ASSERT_EQUALS(proof.getInstructions()[0].d_clause[1],
+ SatLiteral(8192, true));
+
+ TS_ASSERT_EQUALS(proof.getInstructions()[1].d_kind, ADDITION);
+ TS_ASSERT_EQUALS(proof.getInstructions()[1].d_clause.size(), 2);
+ TS_ASSERT_EQUALS(proof.getInstructions()[1].d_clause[0],
+ SatLiteral(128, false));
+ TS_ASSERT_EQUALS(proof.getInstructions()[1].d_clause[1],
+ SatLiteral(8190, true));
+}
+
+void DratProofBlack::testOutputTwoAsText()
+{
+ // d -63 -8193
+ // 129 -8191
+ std::string input("\x64\x7f\x83\x80\x01\x00\x61\x82\x02\xff\x7f\x00", 12);
+ DratProof proof = DratProof::fromBinary(input);
+
+ std::ostringstream output;
+ proof.outputAsText(output);
+
+ std::istringstream tokens(output.str());
+ std::string token;
+
+ tokens >> token;
+ TS_ASSERT_EQUALS(token, "d");
+
+ tokens >> token;
+ TS_ASSERT_EQUALS(token, "-63");
+
+ tokens >> token;
+ TS_ASSERT_EQUALS(token, "-8193");
+
+ tokens >> token;
+ TS_ASSERT_EQUALS(token, "0");
+
+ tokens >> token;
+ TS_ASSERT_EQUALS(token, "129");
+
+ tokens >> token;
+ TS_ASSERT_EQUALS(token, "-8191");
+
+ tokens >> token;
+ TS_ASSERT_EQUALS(token, "0");
+}
+
+void DratProofBlack::testOutputTwoAsLfsc()
+{
+ // d -63 -8193
+ // 129 -8191
+ std::string input("\x64\x7f\x83\x80\x01\x00\x61\x82\x02\xff\x7f\x00", 12);
+ DratProof proof = DratProof::fromBinary(input);
+ std::ostringstream lfsc;
+ proof.outputAsLfsc(lfsc, 2);
+ std::ostringstream lfscWithoutWhitespace;
+ for (char c : lfsc.str())
+ {
+ if (!std::isspace(c))
+ {
+ lfscWithoutWhitespace << c;
+ }
+ }
+ std::string expectedLfsc =
+ "(DRATProofd (clc (neg .v62) (clc (neg .v8192) cln))"
+ "(DRATProofa (clc (pos .v128) (clc (neg .v8190) cln))"
+ "DRATProofn))";
+ std::ostringstream expectedLfscWithoutWhitespace;
+ for (char c : expectedLfsc)
+ {
+ if (!std::isspace(c))
+ {
+ expectedLfscWithoutWhitespace << c;
+ }
+ }
+
+ TS_ASSERT_EQUALS(lfscWithoutWhitespace.str(),
+ expectedLfscWithoutWhitespace.str());
+}
diff --git a/test/unit/proof/lfsc_proof_printer_black.h b/test/unit/proof/lfsc_proof_printer_black.h
new file mode 100644
index 000000000..27372b62d
--- /dev/null
+++ b/test/unit/proof/lfsc_proof_printer_black.h
@@ -0,0 +1,118 @@
+/********************* */
+/*! \file lfsc_proof_printer_black.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Alex Ozdemir
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Black box testing of LFSC proof printing
+ **/
+
+#include <cxxtest/TestSuite.h>
+
+#include "proof/lfsc_proof_printer.h"
+#include "prop/sat_solver_types.h"
+#include "proof/clause_id.h"
+
+using namespace CVC4::proof;
+using namespace CVC4::prop;
+
+class LfscProofPrinterBlack : public CxxTest::TestSuite
+{
+ public:
+ void setUp() override {}
+ void tearDown() override {}
+
+ void testPrintClause();
+ void testPrintSatInputProof();
+ void testPrintCMapProof();
+};
+
+void LfscProofPrinterBlack::testPrintClause()
+{
+ SatClause clause{
+ SatLiteral(0, false), SatLiteral(1, true), SatLiteral(3, false)};
+ std::ostringstream lfsc;
+
+ LFSCProofPrinter::printSatClause(clause, lfsc, "");
+
+ std::string expectedLfsc =
+ "(clc (pos .v0) "
+ "(clc (neg .v1) "
+ "(clc (pos .v3) "
+ "cln)))";
+
+ TS_ASSERT_EQUALS(lfsc.str(), expectedLfsc);
+}
+
+void LfscProofPrinterBlack::testPrintSatInputProof()
+{
+ std::vector<CVC4::ClauseId> ids{2, 40, 3};
+ std::ostringstream lfsc;
+
+ LFSCProofPrinter::printSatInputProof(ids, lfsc, "");
+
+ std::string expectedLfsc =
+ "(cnfc_proof _ _ _ .pb2 "
+ "(cnfc_proof _ _ _ .pb40 "
+ "(cnfc_proof _ _ _ .pb3 "
+ "cnfn_proof)))";
+
+ std::ostringstream lfscWithoutWhitespace;
+ for (char c : lfsc.str())
+ {
+ if (!std::isspace(c))
+ {
+ lfscWithoutWhitespace << c;
+ }
+ }
+ std::ostringstream expectedLfscWithoutWhitespace;
+ for (char c : expectedLfsc)
+ {
+ if (!std::isspace(c))
+ {
+ expectedLfscWithoutWhitespace << c;
+ }
+ }
+
+ TS_ASSERT_EQUALS(lfscWithoutWhitespace.str(),
+ expectedLfscWithoutWhitespace.str());
+}
+
+void LfscProofPrinterBlack::testPrintCMapProof()
+{
+ std::vector<CVC4::ClauseId> ids{2, 40, 3};
+ std::ostringstream lfsc;
+
+ LFSCProofPrinter::printCMapProof(ids, lfsc, "");
+
+ std::string expectedLfsc =
+ "(CMapc_proof 1 _ _ _ .pb2 "
+ "(CMapc_proof 2 _ _ _ .pb40 "
+ "(CMapc_proof 3 _ _ _ .pb3 "
+ "CMapn_proof)))";
+
+ std::ostringstream lfscWithoutWhitespace;
+ for (char c : lfsc.str())
+ {
+ if (!std::isspace(c))
+ {
+ lfscWithoutWhitespace << c;
+ }
+ }
+ std::ostringstream expectedLfscWithoutWhitespace;
+ for (char c : expectedLfsc)
+ {
+ if (!std::isspace(c))
+ {
+ expectedLfscWithoutWhitespace << c;
+ }
+ }
+
+ TS_ASSERT_EQUALS(lfscWithoutWhitespace.str(),
+ expectedLfscWithoutWhitespace.str());
+}
diff --git a/test/unit/proof/lrat_proof_black.h b/test/unit/proof/lrat_proof_black.h
new file mode 100644
index 000000000..49d18ac53
--- /dev/null
+++ b/test/unit/proof/lrat_proof_black.h
@@ -0,0 +1,113 @@
+/********************* */
+/*! \file lrat_proof_black.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 Black box testing of the LRAT proof class
+ **
+ ** In particular, tests LRAT LFSC output.
+ **/
+
+#include <cxxtest/TestSuite.h>
+
+#include <algorithm>
+#include <cctype>
+#include <iostream>
+#include <iterator>
+
+#include "proof/lrat/lrat_proof.h"
+#include "prop/sat_solver_types.h"
+
+using namespace CVC4::proof::lrat;
+using namespace CVC4::prop;
+
+class LfscProofBlack : public CxxTest::TestSuite
+{
+ public:
+ void setUp() override {}
+ void tearDown() override {}
+
+ void testOutputAsLfsc();
+};
+
+/**
+ * Creates a new stream with whitespace removed.
+ *
+ * @param s the source string
+ *
+ * @return a string without whitespace
+ */
+std::string filterWhitespace(const std::string& s)
+{
+ std::string out;
+ std::copy_if(s.cbegin(), s.cend(), std::inserter(out, out.end()), [](char c) {
+ return !std::isspace(c);
+ });
+ return out;
+}
+
+void LfscProofBlack::testOutputAsLfsc()
+{
+ std::vector<std::unique_ptr<LratInstruction>> instructions;
+
+ // 6 d 1 2
+ std::vector<ClauseIdx> clausesToDelete{1, 2};
+ std::unique_ptr<LratDeletion> deletion = std::unique_ptr<LratDeletion>(
+ new LratDeletion(6, std::move(clausesToDelete)));
+ instructions.push_back(std::move(deletion));
+
+ // 7 1 2 0 5 2 0
+ std::vector<SatLiteral> firstAddedClause{SatLiteral(1, false),
+ SatLiteral(2, false)};
+ LratUPTrace firstTrace{5, 2};
+ std::vector<std::pair<ClauseIdx, LratUPTrace>> firstHints;
+ std::unique_ptr<LratAddition> add1 =
+ std::unique_ptr<LratAddition>(new LratAddition(
+ 7, std::move(firstAddedClause), std::move(firstTrace), firstHints));
+ instructions.push_back(std::move(add1));
+
+ // 8 2 0 -1 3 -5 2 0
+ std::vector<SatLiteral> secondAddedClause{SatLiteral(2, false)};
+ LratUPTrace secondTrace;
+ std::vector<std::pair<ClauseIdx, LratUPTrace>> secondHints;
+ LratUPTrace secondHints0Trace{3};
+ secondHints.emplace_back(1, secondHints0Trace);
+ LratUPTrace secondHints1Trace{2};
+ secondHints.emplace_back(5, secondHints1Trace);
+ std::unique_ptr<LratAddition> add2 = std::unique_ptr<LratAddition>(
+ new LratAddition(8,
+ std::move(secondAddedClause),
+ std::move(secondTrace),
+ secondHints));
+ instructions.push_back(std::move(add2));
+
+ LratProof proof(std::move(instructions));
+
+ std::ostringstream lfsc;
+ proof.outputAsLfsc(lfsc);
+
+ // 6 d 1 2
+ // 7 1 2 0 5 2 0
+ // 8 2 0 -1 3 -5 2 0
+ std::string expectedLfsc =
+ "(LRATProofd (CIListc 1 (CIListc 2 CIListn)) "
+ "(LRATProofa 7 "
+ " (clc (pos bb.v1) (clc (pos bb.v2) cln))"
+ " (Tracec 5 (Tracec 2 Tracen))"
+ " RATHintsn "
+ "(LRATProofa 8 "
+ " (clc (pos bb.v2) cln)"
+ " Tracen "
+ " (RATHintsc 1 (Tracec 3 Tracen)"
+ " (RATHintsc 5 (Tracec 2 Tracen)"
+ " RATHintsn)) "
+ "LRATProofn)))";
+
+ TS_ASSERT_EQUALS(filterWhitespace(lfsc.str()), filterWhitespace(expectedLfsc));
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback