summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml6
-rw-r--r--CMakeLists.txt3
-rw-r--r--NEWS2
-rw-r--r--cmake/CVC4Config.cmake.in5
-rw-r--r--cmake/ConfigCompetition.cmake10
-rw-r--r--cmake/Helpers.cmake6
-rwxr-xr-xcontrib/get-cryptominisat2
-rwxr-xr-xcontrib/get-glpk-cut-log13
-rw-r--r--contrib/glpk-cut-log.patch1528
-rw-r--r--examples/api/python/CMakeLists.txt15
-rw-r--r--examples/api/python/exceptions.py34
-rwxr-xr-xexamples/api/python/floating_point.py9
-rw-r--r--examples/api/python/sygus-fun.py6
-rw-r--r--proofs/signatures/drat.plf2
-rw-r--r--proofs/signatures/lrat.plf12
-rw-r--r--proofs/signatures/th_lira.plf4
-rw-r--r--src/CMakeLists.txt52
-rw-r--r--src/api/cvc4cpp.cpp35
-rw-r--r--src/api/cvc4cpp.h21
-rw-r--r--src/api/python/cvc4.pxd13
-rw-r--r--src/api/python/cvc4.pxi60
-rw-r--r--src/expr/CMakeLists.txt4
-rw-r--r--src/expr/expr_manager_template.cpp6
-rw-r--r--src/expr/expr_manager_template.h6
-rw-r--r--src/expr/expr_template.cpp6
-rw-r--r--src/expr/expr_template.h8
-rw-r--r--src/expr/kind_template.cpp3
-rw-r--r--src/expr/kind_template.h3
-rw-r--r--src/expr/metakind_template.h2
-rwxr-xr-xsrc/expr/mkexpr15
-rwxr-xr-xsrc/expr/mkkind26
-rwxr-xr-xsrc/expr/mkmetakind8
-rw-r--r--src/expr/proof_rule.cpp6
-rw-r--r--src/expr/proof_rule.h53
-rw-r--r--src/expr/term_conversion_proof_generator.cpp351
-rw-r--r--src/expr/term_conversion_proof_generator.h70
-rw-r--r--src/expr/type_checker_template.cpp8
-rw-r--r--src/expr/type_properties_template.h10
-rwxr-xr-xsrc/fix-install-headers.sh3
-rw-r--r--src/options/bv_options.toml38
-rw-r--r--src/options/options.h2
-rw-r--r--src/options/options_public_functions.cpp8
-rw-r--r--src/options/proof_options.toml35
-rw-r--r--src/options/smt_options.toml22
-rw-r--r--src/parser/cvc/Cvc.g2
-rw-r--r--src/parser/smt2/smt2.cpp2
-rw-r--r--src/preprocessing/assertion_pipeline.cpp20
-rw-r--r--src/preprocessing/passes/ackermann.cpp16
-rw-r--r--src/preprocessing/passes/ite_simp.cpp3
-rw-r--r--src/preprocessing/passes/miplib_trick.cpp14
-rw-r--r--src/preprocessing/passes/non_clausal_simp.cpp21
-rw-r--r--src/preprocessing/passes/quantifier_macros.cpp45
-rw-r--r--src/printer/ast/ast_printer.cpp3
-rw-r--r--src/printer/ast/ast_printer.h2
-rw-r--r--src/printer/cvc/cvc_printer.cpp30
-rw-r--r--src/printer/cvc/cvc_printer.h2
-rw-r--r--src/printer/printer.cpp8
-rw-r--r--src/printer/printer.h6
-rw-r--r--src/printer/smt2/smt2_printer.cpp31
-rw-r--r--src/printer/smt2/smt2_printer.h4
-rw-r--r--src/printer/tptp/tptp_printer.cpp13
-rw-r--r--src/printer/tptp/tptp_printer.h2
-rw-r--r--src/proof/arith_proof.cpp1207
-rw-r--r--src/proof/arith_proof.h217
-rw-r--r--src/proof/arith_proof_recorder.cpp89
-rw-r--r--src/proof/arith_proof_recorder.h107
-rw-r--r--src/proof/array_proof.cpp1350
-rw-r--r--src/proof/array_proof.h121
-rw-r--r--src/proof/bitvector_proof.cpp792
-rw-r--r--src/proof/bitvector_proof.h280
-rw-r--r--src/proof/clausal_bitvector_proof.cpp412
-rw-r--r--src/proof/clausal_bitvector_proof.h189
-rw-r--r--src/proof/clause_id.h7
-rw-r--r--src/proof/cnf_proof.cpp863
-rw-r--r--src/proof/cnf_proof.h134
-rw-r--r--src/proof/dimacs.cpp120
-rw-r--r--src/proof/dimacs.h69
-rw-r--r--src/proof/drat/drat_proof.cpp291
-rw-r--r--src/proof/drat/drat_proof.h140
-rw-r--r--src/proof/er/er_proof.cpp399
-rw-r--r--src/proof/er/er_proof.h218
-rw-r--r--src/proof/lemma_proof.cpp254
-rw-r--r--src/proof/lemma_proof.h115
-rw-r--r--src/proof/lfsc_proof_printer.cpp217
-rw-r--r--src/proof/lfsc_proof_printer.h154
-rw-r--r--src/proof/lrat/lrat_proof.cpp343
-rw-r--r--src/proof/lrat/lrat_proof.h184
-rw-r--r--src/proof/proof.h70
-rw-r--r--src/proof/proof_manager.cpp1032
-rw-r--r--src/proof/proof_manager.h317
-rw-r--r--src/proof/proof_output_channel.cpp102
-rw-r--r--src/proof/proof_output_channel.h79
-rw-r--r--src/proof/proof_utils.cpp126
-rw-r--r--src/proof/proof_utils.h229
-rw-r--r--src/proof/resolution_bitvector_proof.cpp523
-rw-r--r--src/proof/resolution_bitvector_proof.h113
-rw-r--r--src/proof/sat_proof.h1
-rw-r--r--src/proof/sat_proof_implementation.h21
-rw-r--r--src/proof/simplify_boolean_node.cpp183
-rw-r--r--src/proof/skolemization_manager.cpp69
-rw-r--r--src/proof/skolemization_manager.h55
-rw-r--r--src/proof/theory_proof.cpp1756
-rw-r--r--src/proof/theory_proof.h510
-rw-r--r--src/proof/uf_proof.cpp759
-rw-r--r--src/proof/uf_proof.h106
-rw-r--r--src/prop/bvminisat/bvminisat.cpp34
-rw-r--r--src/prop/bvminisat/bvminisat.h9
-rw-r--r--src/prop/bvminisat/core/Solver.cc403
-rw-r--r--src/prop/bvminisat/core/Solver.h50
-rw-r--r--src/prop/bvminisat/core/SolverTypes.h49
-rw-r--r--src/prop/bvminisat/simp/SimpSolver.cc57
-rw-r--r--src/prop/bvminisat/simp/SimpSolver.h2
-rw-r--r--src/prop/cadical.cpp1
-rw-r--r--src/prop/cnf_stream.cpp60
-rw-r--r--src/prop/cnf_stream.h14
-rw-r--r--src/prop/cryptominisat.cpp44
-rw-r--r--src/prop/cryptominisat.h3
-rw-r--r--src/prop/kissat.cpp1
-rw-r--r--src/prop/minisat/core/Solver.cc313
-rw-r--r--src/prop/minisat/core/Solver.h6
-rw-r--r--src/prop/minisat/core/SolverTypes.h64
-rw-r--r--src/prop/minisat/minisat.cpp2
-rw-r--r--src/prop/minisat/simp/SimpSolver.cc98
-rw-r--r--src/prop/minisat/simp/SimpSolver.h2
-rw-r--r--src/prop/prop_engine.cpp23
-rw-r--r--src/prop/prop_engine.h6
-rw-r--r--src/prop/sat_solver.h12
-rw-r--r--src/prop/theory_proxy.cpp20
-rw-r--r--src/smt/assertions.cpp26
-rw-r--r--src/smt/assertions.h3
-rw-r--r--src/smt/command.cpp39
-rw-r--r--src/smt/command.h8
-rw-r--r--src/smt/dump.h16
-rw-r--r--src/smt/dump_manager.cpp16
-rw-r--r--src/smt/dump_manager.h14
-rw-r--r--src/smt/listeners.cpp19
-rw-r--r--src/smt/model.cpp4
-rw-r--r--src/smt/model.h4
-rw-r--r--src/smt/node_command.cpp180
-rw-r--r--src/smt/node_command.h157
-rw-r--r--src/smt/process_assertions.cpp11
-rw-r--r--src/smt/set_defaults.cpp139
-rw-r--r--src/smt/smt_engine.cpp106
-rw-r--r--src/smt/smt_engine.h18
-rw-r--r--src/smt/smt_engine_scope.cpp1
-rw-r--r--src/smt/smt_engine_stats.cpp6
-rw-r--r--src/smt/smt_engine_stats.h4
-rw-r--r--src/smt/smt_solver.cpp8
-rw-r--r--src/smt/sygus_solver.h2
-rw-r--r--src/smt/term_formula_removal.cpp32
-rw-r--r--src/theory/arith/arith_lemma.cpp (renamed from src/proof/simplify_boolean_node.h)25
-rw-r--r--src/theory/arith/arith_lemma.h61
-rw-r--r--src/theory/arith/callbacks.cpp29
-rw-r--r--src/theory/arith/constraint.cpp114
-rw-r--r--src/theory/arith/constraint.h48
-rw-r--r--src/theory/arith/inference_manager.cpp144
-rw-r--r--src/theory/arith/inference_manager.h116
-rw-r--r--src/theory/arith/linear_equality.cpp24
-rw-r--r--src/theory/arith/nl/cad_solver.cpp2
-rw-r--r--src/theory/arith/nl/nl_lemma_utils.cpp12
-rw-r--r--src/theory/arith/nl/nl_lemma_utils.h30
-rw-r--r--src/theory/arith/nl/nl_model.cpp3
-rw-r--r--src/theory/arith/nl/nl_solver.cpp2
-rw-r--r--src/theory/arith/nl/nonlinear_extension.cpp23
-rw-r--r--src/theory/arith/nl/nonlinear_extension.h5
-rw-r--r--src/theory/arith/nl/transcendental_solver.cpp4
-rw-r--r--src/theory/arith/proof_macros.h34
-rw-r--r--src/theory/arith/theory_arith.cpp1
-rw-r--r--src/theory/arith/theory_arith.h11
-rw-r--r--src/theory/arith/theory_arith_private.cpp105
-rw-r--r--src/theory/arrays/array_proof_reconstruction.cpp199
-rw-r--r--src/theory/arrays/array_proof_reconstruction.h59
-rw-r--r--src/theory/arrays/static_fact_manager.cpp170
-rw-r--r--src/theory/arrays/static_fact_manager.h116
-rw-r--r--src/theory/arrays/theory_arrays.cpp438
-rw-r--r--src/theory/arrays/theory_arrays.h47
-rw-r--r--src/theory/builtin/proof_checker.cpp68
-rw-r--r--src/theory/builtin/proof_checker.h40
-rw-r--r--src/theory/bv/bitblast/aig_bitblaster.h6
-rw-r--r--src/theory/bv/bitblast/bitblaster.h21
-rw-r--r--src/theory/bv/bitblast/eager_bitblaster.cpp19
-rw-r--r--src/theory/bv/bitblast/eager_bitblaster.h2
-rw-r--r--src/theory/bv/bitblast/lazy_bitblaster.cpp22
-rw-r--r--src/theory/bv/bitblast/lazy_bitblaster.h1
-rw-r--r--src/theory/bv/bv_eager_solver.cpp12
-rw-r--r--src/theory/bv/bv_eager_solver.h3
-rw-r--r--src/theory/bv/bv_subtheory.h9
-rw-r--r--src/theory/bv/bv_subtheory_algebraic.cpp3
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.cpp7
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.h5
-rw-r--r--src/theory/bv/bv_subtheory_core.cpp3
-rw-r--r--src/theory/bv/theory_bv.cpp57
-rw-r--r--src/theory/bv/theory_bv.h17
-rw-r--r--src/theory/combination_engine.cpp2
-rw-r--r--src/theory/datatypes/inference_manager.cpp126
-rw-r--r--src/theory/datatypes/inference_manager.h95
-rw-r--r--src/theory/datatypes/theory_datatypes.cpp387
-rw-r--r--src/theory/datatypes/theory_datatypes.h61
-rw-r--r--src/theory/engine_output_channel.cpp153
-rw-r--r--src/theory/engine_output_channel.h4
-rw-r--r--src/theory/ext_theory.h1
-rw-r--r--src/theory/fp/theory_fp.cpp3
-rw-r--r--src/theory/inference_manager_buffered.cpp67
-rw-r--r--src/theory/inference_manager_buffered.h69
-rw-r--r--src/theory/logic_info.cpp8
-rwxr-xr-xsrc/theory/mkrewriter4
-rwxr-xr-xsrc/theory/mktheorytraits9
-rw-r--r--src/theory/output_channel.cpp5
-rw-r--r--src/theory/output_channel.h16
-rw-r--r--src/theory/quantifiers/fun_def_process.cpp36
-rw-r--r--src/theory/quantifiers/instantiate.cpp32
-rw-r--r--src/theory/quantifiers/instantiate.h15
-rw-r--r--src/theory/quantifiers_engine.cpp21
-rw-r--r--src/theory/quantifiers_engine.h4
-rw-r--r--src/theory/rewriter.cpp20
-rw-r--r--src/theory/rewriter.h9
-rw-r--r--src/theory/sets/theory_sets.cpp46
-rw-r--r--src/theory/sets/theory_sets.h20
-rw-r--r--src/theory/sets/theory_sets_private.cpp211
-rw-r--r--src/theory/sets/theory_sets_private.h17
-rw-r--r--src/theory/sort_inference.cpp1
-rw-r--r--src/theory/strings/inference_manager.cpp111
-rw-r--r--src/theory/strings/inference_manager.h35
-rw-r--r--src/theory/strings/theory_strings.cpp123
-rw-r--r--src/theory/strings/theory_strings.h28
-rw-r--r--src/theory/strings/theory_strings_preprocess.cpp6
-rw-r--r--src/theory/theory.cpp36
-rw-r--r--src/theory/theory.h63
-rw-r--r--src/theory/theory_engine.cpp241
-rw-r--r--src/theory/theory_engine.h26
-rw-r--r--src/theory/theory_inference.cpp63
-rw-r--r--src/theory/theory_inference.h106
-rw-r--r--src/theory/theory_inference_manager.cpp185
-rw-r--r--src/theory/theory_inference_manager.h170
-rw-r--r--src/theory/theory_test_utils.h8
-rw-r--r--src/theory/theory_traits_template.h2
-rw-r--r--src/theory/type_enumerator_template.cpp2
-rw-r--r--src/theory/uf/eq_proof.cpp32
-rw-r--r--src/theory/uf/eq_proof.h25
-rw-r--r--src/theory/uf/equality_engine.cpp167
-rw-r--r--src/theory/uf/equality_engine.h32
-rw-r--r--src/theory/uf/equality_engine_types.h32
-rw-r--r--src/theory/uf/ho_extension.cpp19
-rw-r--r--src/theory/uf/ho_extension.h7
-rw-r--r--src/theory/uf/proof_checker.cpp30
-rw-r--r--src/theory/uf/theory_uf.cpp65
-rw-r--r--src/theory/uf/theory_uf.h17
-rw-r--r--src/theory/uf/theory_uf_rewriter.h1
-rw-r--r--src/util/CMakeLists.txt1
-rw-r--r--src/util/proof.h44
-rw-r--r--src/util/string.cpp6
-rw-r--r--src/util/string.h4
-rw-r--r--test/regress/CMakeLists.txt4
-rw-r--r--test/regress/regress0/arrays/bug4957.smt26
-rw-r--r--test/regress/regress0/bug217.smt21
-rw-r--r--test/regress/regress0/options/invalid_option_inc_proofs.smt26
-rw-r--r--test/regress/regress1/bv/bench_38.delta.smt22
-rw-r--r--test/regress/regress1/non-fatal-errors.smt24
-rw-r--r--test/regress/regress1/quantifiers/dump-inst-proof.smt28
-rw-r--r--test/regress/regress1/quantifiers/issue3481-unsat1.smt22
-rw-r--r--test/regress/regress1/quantifiers/issue3481.smt22
-rw-r--r--test/unit/CMakeLists.txt1
-rw-r--r--test/unit/api/python/test_datatype_api.py171
-rw-r--r--test/unit/api/python/test_sort.py30
-rw-r--r--test/unit/api/python/test_term.py11
-rw-r--r--test/unit/api/solver_black.h65
-rw-r--r--test/unit/proof/CMakeLists.txt7
-rw-r--r--test/unit/proof/drat_proof_black.h187
-rw-r--r--test/unit/proof/er_proof_black.h464
-rw-r--r--test/unit/proof/lfsc_proof_printer_black.h118
-rw-r--r--test/unit/proof/lrat_proof_black.h97
-rw-r--r--test/unit/proof/utils.h34
-rw-r--r--test/unit/prop/cnf_stream_white.h60
-rw-r--r--test/unit/theory/theory_engine_white.h7
-rw-r--r--test/unit/theory/theory_white.h9
275 files changed, 5953 insertions, 19753 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 00fa15bc5..d7909b961 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -90,12 +90,12 @@ jobs:
python3 -m pip install pexpect
echo "::add-path::/usr/local/opt/ccache/libexec"
- # Note: We install Cython with sudo since cmake can't find Cython otherwise.
- name: Install Cython
if: matrix.python-bindings && runner.os == 'Linux'
run: |
- sudo python3 -m pip install \
- Cython==0.29 --install-option="--no-cython-compile"
+ python3 -m pip install \
+ Cython==0.29.* --install-option="--no-cython-compile"
+ echo "::add-path::$(python3 -m site --user-base)/bin"
- name: Install Cython (macOS)
if: matrix.python-bindings && runner.os == 'macOS'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5b1d1e292..06e9c44f6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -571,6 +571,7 @@ add_subdirectory(src)
add_subdirectory(test)
if(BUILD_BINDINGS_PYTHON)
+ set(BUILD_BINDINGS_PYTHON_VERSION ${PYTHON_VERSION_MAJOR})
add_subdirectory(src/api/python)
endif()
@@ -767,7 +768,7 @@ message("")
if(GPL_LIBS)
message(
- "CVC4 license : GPLv3 (due to optional libraries; see below)"
+ "CVC4 license : ${Yellow}GPLv3 (due to optional libraries; see below)${ResetColor}"
"\n"
"\n"
"Please note that CVC4 will be built against the following GPLed libraries:"
diff --git a/NEWS b/NEWS
index f74fe2631..d3e519c9b 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,8 @@ Changes:
BSD-licensed Editline. Compiling with `--best` now enables Editline, instead
of Readline. Without selecting optional GPL components, Editline-enabled CVC4
builds will be BSD licensed.
+* The `competition` build type includes the dependencies used for SMT-COMP by
+ default. Note that this makes this build type produce GPL-licensed binaries.
Changes since 1.7
=================
diff --git a/cmake/CVC4Config.cmake.in b/cmake/CVC4Config.cmake.in
index 76535762d..7f6a80995 100644
--- a/cmake/CVC4Config.cmake.in
+++ b/cmake/CVC4Config.cmake.in
@@ -1,7 +1,8 @@
@PACKAGE_INIT@
-set(CVC4_BINDINGS_JAVA @BUILD_SWIG_BINDINGS_JAVA@)
-set(CVC4_BINDINGS_PYTHON @BUILD_SWIG_BINDINGS_PYTHON@)
+set(CVC4_BINDINGS_JAVA @BUILD_BINDINGS_JAVA@)
+set(CVC4_BINDINGS_PYTHON @BUILD_BINDINGS_PYTHON@)
+set(CVC4_BINDINGS_PYTHON_VERSION @BUILD_BINDINGS_PYTHON_VERSION@)
if(NOT TARGET CVC4::cvc4)
include(${CMAKE_CURRENT_LIST_DIR}/CVC4Targets.cmake)
diff --git a/cmake/ConfigCompetition.cmake b/cmake/ConfigCompetition.cmake
index e18d2b2f1..d7188f60a 100644
--- a/cmake/ConfigCompetition.cmake
+++ b/cmake/ConfigCompetition.cmake
@@ -22,3 +22,13 @@ cvc4_set_option(ENABLE_MUZZLE ON)
# enable_shared=no
cvc4_set_option(ENABLE_SHARED OFF)
cvc4_set_option(ENABLE_UNIT_TESTING OFF)
+
+# By default, we include all dependencies in our competition build that are
+# required to achieve the best performance
+set(ENABLE_GPL ON)
+cvc4_set_option(USE_CADICAL ON)
+cvc4_set_option(USE_CLN ON)
+cvc4_set_option(USE_CRYPTOMINISAT ON)
+cvc4_set_option(USE_EDITLINE OFF)
+cvc4_set_option(USE_GLPK ON)
+cvc4_set_option(USE_SYMFPU ON)
diff --git a/cmake/Helpers.cmake b/cmake/Helpers.cmake
index 692e32900..79c8f7bf2 100644
--- a/cmake/Helpers.cmake
+++ b/cmake/Helpers.cmake
@@ -1,6 +1,12 @@
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
+if(NOT WIN32)
+ string(ASCII 27 Esc)
+ set(Yellow "${Esc}[33m")
+ set(ResetColor "${Esc}[m")
+endif()
+
# Add a C flag to the global list of C flags.
macro(add_c_flag flag)
if(CMAKE_C_FLAGS)
diff --git a/contrib/get-cryptominisat b/contrib/get-cryptominisat
index 2b85e1a91..476d1ff10 100755
--- a/contrib/get-cryptominisat
+++ b/contrib/get-cryptominisat
@@ -3,7 +3,7 @@
source "$(dirname "$0")/get-script-header.sh"
CMS_DIR="$DEPS_DIR/cryptominisat5"
-version="5.6.3"
+version="5.8.0"
check_dep_dir "$CMS_DIR"
setup_dep \
diff --git a/contrib/get-glpk-cut-log b/contrib/get-glpk-cut-log
index 16acf97ae..951e10620 100755
--- a/contrib/get-glpk-cut-log
+++ b/contrib/get-glpk-cut-log
@@ -2,15 +2,24 @@
#
source "$(dirname "$0")/get-script-header.sh"
+# get the full path to the contrib dir; needs to be the full path so we can
+# refer the patch from within the 'glpk-cut-log' build directory
+contrib_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd -P)"
+
+# Get the full path the patch we wish to apply
+patch_file=${contrib_dir}/glpk-cut-log.patch
+
GLPK_DIR="$DEPS_DIR/glpk-cut-log"
-commit=b420454e732f4b3d229c552ef7cd46fec75fe65c
+version="4.52"
check_dep_dir "$GLPK_DIR"
setup_dep \
- "https://github.com/timothy-king/glpk-cut-log/archive/$commit.tar.gz" \
+ "https://ftp.gnu.org/gnu/glpk/glpk-${version}.tar.gz" \
"$GLPK_DIR"
cd "$GLPK_DIR"
+patch -p1 < ${patch_file}
+
libtoolize
aclocal
autoheader
diff --git a/contrib/glpk-cut-log.patch b/contrib/glpk-cut-log.patch
new file mode 100644
index 000000000..9ef01886c
--- /dev/null
+++ b/contrib/glpk-cut-log.patch
@@ -0,0 +1,1528 @@
+@@ This patch is taken from https://github.com/timothy-king/glpk-cut-log and
+@@ has the following license:
+@@
+@@ GLPK is free software: you can redistribute it and/or modify it under the
+@@ terms of the GNU General Public License as published by the Free Software
+@@ Foundation, either version 3 of the License, or (at your option) any later
+@@ version.
+@@
+From cf84e3855d8c5676557daaca434b42b2fc17dc29 Mon Sep 17 00:00:00 2001
+From: Tim King <taking@cs.nyu.edu>
+Date: Sat, 14 Dec 2013 16:03:35 -0500
+Subject: [PATCH] Adding a function for returning the iteration count.
+
+Adding GLP_ICUTADDED callback:
+- Adds a new callback location that is called after every cut is added to the pool.
+- During this callback users can request a copy of this cut and query what kind of cut it is.
+- GMI cuts also support returning what row in the tableau it came from. Users can use this to replay how the cut was generated.
+
+Logging MIR Cuts
+- Changed the IOSAUX to be defined as a linear sum of input rows.
+ This is visible from the interface
+- Logging the multipliers used to create the aggregate row in MIR.
+- Logging the delta selected by final successful cmir_sep call.
+- Logging the cset selected by final successful cmir_sep call.
+- The delta and cset are not yet user visible.
+
+The extra mir logging information is now user visible.
+
+Adding GLP_ICUTSELECT callback:
+- ios_process_cuts marks the cuts as selected after turning the cut into a row.
+- This callback happens after ios_process_cuts marks and before the pool is
+ cleared by ios_clear_pool.
+
+Cleaning up the git directory to not track autogenerated files.
+
+Branch logging
+- Adds to the integer interface a callback function for when branches are made.
+ This is called after branch_on.
+- Added a public function glp_ios_branch_log.
+ This returns the structural variable for the branch as well as the value
+ branched on, and the ids of the nodes for the down and up branches.
+ If both branches are infeasible, the ids are -1 for both dn and up.
+ If one branch is infeasible (and no branch is done), this returns -1 for
+ the infeasible branch and the current node id for the up branch.
+- Each node now has a unique ordinal associated with it.
+- Added a public function to convert the id of an active node to the unique
+ node ordinal.
+- Added a callback for when a node is closed due to being linearly infeasible.
+
+Improved the mir cut logging facilities to now include:
+- the rid id used for virtual lower/upper bound selection,
+- and the subst map,
+- Changed the size of the cset array to be the same as the new arrays (m+n)
+- Fixed a bug in returning the cset selected.
+
+Fixing a bug selecting the correct branch.
+
+Added a callback for tracking row deletion.
+
+Adding notes to node freeze and revive functions.
+
+Commenting out a few debugging printfs for gomory cuts.
+
+Changing an overly aggressive assert in MIR generate when an assignment is outside of the bounds to skipping the application of the mir rule.
+
+Removing some printfs.
+
+Weakening assert to a failure.
+
+Adding a stability failure limit to simplex.
+
+Updating the installation instructions.
+
+---
+diff --git a/configure.ac b/configure.ac
+index 0141a8a..ffb9ae4 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1,7 +1,7 @@
+ dnl Process this file with autoconf to produce a configure script
+
+ AC_INIT([GLPK], [4.52], [bug-glpk@gnu.org])
+-
++AM_INIT_AUTOMAKE([subdir-objects])
+ AC_CONFIG_SRCDIR([src/glpk.h])
+
+ AC_CONFIG_MACRO_DIR([m4])
+diff --git a/src/Makefile.am b/src/Makefile.am
+index b39efa6..2a025bc 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -20,7 +20,10 @@ libglpk_la_LDFLAGS = \
+ -version-info 36:0:1 \
+ -export-symbols-regex '^glp_*'
+
++
++# all of the cut log sources are listed first
+ libglpk_la_SOURCES = \
++cutlog01.c \
+ glpapi01.c \
+ glpapi02.c \
+ glpapi03.c \
+diff --git a/src/cutlog01.c b/src/cutlog01.c
+new file mode 100644
+index 0000000..9a85bb7
+--- /dev/null
++++ b/src/cutlog01.c
+@@ -0,0 +1,452 @@
++/* cutlog01.c (api extension routines) */
++
++
++#include "glpapi.h"
++#include "glpios.h"
++
++int glp_get_it_cnt(glp_prob *P){
++ if(P == NULL){
++ return 0;
++ }else{
++ return P->it_cnt;
++ }
++}
++
++int glp_ios_get_cut(glp_tree *T, int i, int* ind, double* val, int* klass, int* type, double* rhs){
++ xassert(T != NULL);
++
++ IOSCUT* cut;
++ int len;
++ IOSAIJ* aij;
++ glp_prob* prob;
++
++ if (T->reason != GLP_ICUTADDED){
++ xerror("glp_ios_get_cut: not called during cut added.\n");
++ }
++ cut = ios_find_row(T->local, i);
++ if ( cut == NULL ) {
++ xerror("glp_ios_get_cut: called with an invalid index.");
++ }
++ len = 0;
++ for(len = 0, aij = cut->ptr; aij != NULL; aij = aij->next)
++ {
++ len++;
++ if(ind != NULL){ ind[len] = aij->j; }
++ if(val != NULL){ val[len] = aij->val; }
++ }
++ if(klass != NULL){ *klass = cut->klass; }
++ if(type != NULL){ *type = cut->type; }
++ if(rhs != NULL){ *rhs = cut->rhs; }
++ return len;
++}
++
++
++IOSAUX *ios_create_aux(int n, const int rows[], const double coeffs[]){
++ IOSAUX *aux;
++ int i;
++ aux = xmalloc(sizeof(IOSAUX));
++ aux->nrows = n;
++ aux->rows = xcalloc(1+n, sizeof(int));
++ aux->mult = xcalloc(1+n, sizeof(double));
++ aux->selected = -1;
++ aux->mir_cset = NULL;
++
++ for ( i = 1; i <= n; i++)
++ { aux->rows[i] = rows[i];
++ aux->mult[i] = coeffs[i];
++ }
++
++ return aux;
++}
++
++void ios_delete_aux(IOSAUX *aux){
++ xassert(aux != NULL);
++ xfree(aux->rows);
++ xfree(aux->mult);
++ if( aux->mir_cset != NULL ){
++ xfree(aux->mir_cset);
++ xfree(aux->mir_subst);
++ xfree(aux->mir_vlb_rows);
++ xfree(aux->mir_vub_rows);
++ }
++ xfree(aux);
++ return;
++}
++
++static void cut_set_aux(IOSCUT *cut, int n,
++ const int rows[], const double coeffs[]){
++ int i;
++ xassert( cut != NULL );
++ if( cut->aux != NULL ) {
++ ios_delete_aux(cut-> aux);
++ }
++
++ cut->aux = ios_create_aux(n, rows, coeffs);
++ xassert( cut->aux->nrows == n );
++}
++
++static void cut_set_aux_mir(IOSAUX *aux, double delta, int m, int n,
++ const char cset[], const char subst[],
++ const int vlbrs[], const int vubrs[]){
++ int i;
++ xassert( aux != NULL );
++ if ( aux->mir_cset != NULL )
++ { xfree(aux->mir_cset);
++ xfree(aux->mir_subst);
++ xfree(aux->mir_vlb_rows);
++ xfree(aux->mir_vub_rows);
++ }
++
++ aux->mir_cset = xcalloc(1+n+m, sizeof(char));
++ aux->mir_subst = xcalloc(1+n+m, sizeof(char));
++ aux->mir_vlb_rows = xcalloc(1+n+m, sizeof(int));
++ aux->mir_vub_rows = xcalloc(1+n+m, sizeof(int));
++
++ for ( i = 1; i <= n+m; i++)
++ { aux->mir_cset[i] = cset[i];
++ aux->mir_subst[i] = subst[i];
++ aux->mir_vlb_rows[i] = vlbrs[i];
++ aux->mir_vub_rows[i] = vubrs[i];
++ }
++
++ aux->mir_delta = delta;
++}
++
++void ios_cut_set_aux_mir(glp_tree *T, int ord, double delta,
++ const char cset[], const char subst[],
++ const int vlbrs[], const int vubrs[]){
++ int m, n;
++ IOSCUT *cut;
++ glp_prob *mip;
++ mip = T->mip;
++ m = mip->m;
++ n = mip->n;
++ cut = ios_find_row(T->local, ord);
++ xassert(cut != NULL);
++ cut_set_aux_mir(cut->aux, delta, m, n, cset, subst, vlbrs, vubrs);
++}
++
++void ios_cut_set_single_aux(glp_tree *T, int ord, int j){
++ IOSCUT *cut;
++ cut = ios_find_row(T->local, ord);
++ xassert(cut != NULL);
++
++ /* set up arrays */
++ int ind[1+1];
++ double coeffs[1+1];
++ ind[1] = j;
++ coeffs[1] = +1.0;
++
++ /* call general procedure */
++ cut_set_aux(cut, 1, ind, coeffs);
++}
++
++void ios_cut_set_aux(glp_tree *T, int ord, int n,
++ const int rows[], const double coeffs[]){
++ IOSCUT *cut;
++ cut = ios_find_row(T->local, ord);
++ xassert(cut != NULL);
++ cut_set_aux(cut, n, rows, coeffs);
++}
++
++int glp_ios_cut_get_aux_nrows(glp_tree *tree, int ord){
++ IOSCUT *cut;
++ IOSAUX *aux;
++ if (tree->reason != GLP_ICUTADDED){
++ xerror("glp_ios_cut_get_aux_nrows: not called during cut added.\n");
++ }
++ cut = ios_find_row(tree->local, ord);
++ if ( cut == NULL ){
++ xerror("glp_ios_cut_get_aux_nrows: not called on a valid cut.\n");
++ }
++ aux = cut->aux;
++ return (aux == NULL) ? 0 : aux->nrows;
++}
++
++void glp_ios_cut_get_aux_rows(glp_tree *tree, int ord,
++ int rows[], double coeffs[]){
++ IOSCUT *cut;
++ IOSAUX *aux;
++ int j, nrows;
++ if (tree->reason != GLP_ICUTADDED){
++ xerror("glp_ios_cut_get_aux_rows: not called during cut added.\n");
++ }
++ cut = ios_find_row(tree->local, ord);
++ if ( cut == NULL ){
++ xerror("glp_ios_cut_get_aux_rows: not called on a valid cut.\n");
++ }
++ aux = cut->aux;
++ if( aux != NULL ){
++ nrows = aux->nrows;
++ for ( j = 1; j <= nrows; j++ )
++ { if ( rows != NULL ) { rows[j] = aux->rows[j]; }
++ if ( coeffs != NULL ) { coeffs[j] = aux->mult[j]; }
++ }
++ }
++ return;
++}
++
++
++void glp_ios_cut_get_mir_subst(glp_tree *tree, int ord, char subst[]);
++/* gets mir cut substition information. */
++void glp_ios_cut_get_mir_virtual_rows(glp_tree *tree, int ord,
++ int vlb[], int vub[]);
++/* gets mir cut virtual bounds rows. */
++
++void glp_ios_cut_get_mir_cset(glp_tree *tree, int ord, char *cset){
++ glp_prob *mip;
++ IOSCUT *cut;
++ IOSAUX *aux;
++ int j, n, m;
++ if ( tree->reason != GLP_ICUTADDED ){
++ xerror("glp_ios_cut_get_aux_mir: not called during cut added.\n");
++ }
++ cut = ios_find_row(tree->local, ord);
++ if ( cut == NULL ){
++ xerror("glp_ios_cut_get_aux_mir: not called on a cut.\n");
++ }
++ if ( cut->klass != GLP_RF_MIR ){
++ xerror("glp_ios_cut_get_aux_mir: not called on a mir cut.\n");
++ }
++ aux = cut->aux;
++ mip = tree->mip;
++ m = mip->m;
++ n = mip->n;
++
++ if( cset != NULL ){
++ for ( j=1; j <= n+m; j++ ){
++ cset[j] = (aux->mir_cset == NULL) ? 0 : aux->mir_cset[j];
++ }
++ }
++}
++void glp_ios_cut_get_mir_subst(glp_tree *tree, int ord, char *subst){
++ glp_prob *mip;
++ IOSCUT *cut;
++ IOSAUX *aux;
++ int j, n, m;
++ if ( tree->reason != GLP_ICUTADDED ){
++ xerror("glp_ios_cut_get_aux_mir: not called during cut added.\n");
++ }
++ cut = ios_find_row(tree->local, ord);
++ if ( cut == NULL ){
++ xerror("glp_ios_cut_get_aux_mir: not called on a cut.\n");
++ }
++ if ( cut->klass != GLP_RF_MIR ){
++ xerror("glp_ios_cut_get_aux_mir: not called on a mir cut.\n");
++ }
++ aux = cut->aux;
++ mip = tree->mip;
++ m = mip->m;
++ n = mip->n;
++
++ if( subst != NULL ){
++ for ( j=1; j <= n+m; j++ ){
++ subst[j] = (aux->mir_subst == NULL) ? 0 : aux->mir_subst[j];
++ }
++ }
++}
++void glp_ios_cut_get_mir_virtual_rows(glp_tree *tree, int ord, int vlb_rows[], int vub_rows[]){
++ glp_prob *mip;
++ IOSCUT *cut;
++ IOSAUX *aux;
++ int j, n, m;
++ if ( tree->reason != GLP_ICUTADDED ){
++ xerror("glp_ios_cut_get_aux_mir: not called during cut added.\n");
++ }
++ cut = ios_find_row(tree->local, ord);
++ if ( cut == NULL ){
++ xerror("glp_ios_cut_get_aux_mir: not called on a cut.\n");
++ }
++ if ( cut->klass != GLP_RF_MIR ){
++ xerror("glp_ios_cut_get_aux_mir: not called on a mir cut.\n");
++ }
++ aux = cut->aux;
++ mip = tree->mip;
++ m = mip->m;
++ n = mip->n;
++
++ for ( j=1; j <= n+m; j++ ){
++ vlb_rows[j] = (aux->mir_vlb_rows == NULL) ? 0 : aux->mir_vlb_rows[j];
++ vub_rows[j] = (aux->mir_vub_rows == NULL) ? 0 : aux->mir_vub_rows[j];
++ }
++}
++double glp_ios_cut_get_mir_delta(glp_tree *tree, int ord){
++ glp_prob *mip;
++ IOSCUT *cut;
++ IOSAUX *aux;
++ int j, n, m;
++ if ( tree->reason != GLP_ICUTADDED ){
++ xerror("glp_ios_cut_get_aux_mir: not called during cut added.\n");
++ }
++ cut = ios_find_row(tree->local, ord);
++ if ( cut == NULL ){
++ xerror("glp_ios_cut_get_aux_mir: not called on a cut.\n");
++ }
++ if ( cut->klass != GLP_RF_MIR ){
++ xerror("glp_ios_cut_get_aux_mir: not called on a mir cut.\n");
++ }
++ aux = cut->aux;
++ return aux->mir_delta;
++}
++
++
++void ios_cut_set_selected(IOSCUT *cut, int sel){
++#ifdef CUT_DEBUG
++ static int i = 0;
++ ++i;
++ printf("ios_cut_set_selected: %d %d %p\n", i, sel, cut);
++#endif
++
++ IOSAUX *aux;
++ aux = cut->aux;
++ if ( aux != NULL ){
++ aux->selected = sel;
++ }
++}
++
++int glp_ios_selected_cuts(glp_tree *tree, int ords[], int sel[]){
++ int len, j, N, s;
++ IOSPOOL* pool;
++ IOSCUT* cut;
++ IOSAUX* aux;
++ if ( tree == NULL ){
++ xerror("glp_ios_selected_cuts: not called with a valid tree.\n");
++ }
++ if ( tree->reason != GLP_ICUTSELECT ){
++ xerror("glp_ios_selected_cuts: not called during cut selected.\n");
++ }
++
++ pool = tree->local;
++ if ( pool == NULL ){
++ xerror("glp_ios_selected_cuts: called on a malformed tree.\n");
++ }
++
++ for (len = 0, j = 1, cut = pool->head; cut != NULL; cut = cut->next, j++)
++ { aux = cut->aux;
++#ifdef CUT_DEBUG
++ printf("glp_ios_selected_cuts: %d %p\n", j, cut);
++#endif
++ if ( aux != NULL )
++ { s = aux->selected;
++ if ( s >= 0 )
++ { len++;
++ if (ords != NULL) { ords[len] = j; }
++ if (sel != NULL) { sel[len] = s; }
++ }
++ }
++ }
++ return len;
++}
++
++int glp_ios_branch_log(glp_tree *tree, double *br_val, int* parent, int* dn, int* up){
++ IOSNPD *node;
++ int br_result, br_var;
++ int p, d, u;
++ double v;
++ glp_prob *mip;
++ if ( tree == NULL ){
++ xerror("glp_ios_branch_log: not called with a valid tree \n");
++ }
++ if ( tree->reason != GLP_LI_BRANCH ){
++ xerror("glp_ios_branch_log: not called during GLP_LI_BRANCH \n");
++ }
++ mip = tree->mip;
++ if ( mip == NULL ){
++ xerror("glp_ios_branch_log: not called with a valid tree\n");
++ }
++ br_result = tree->br_result;
++ br_var = tree->br_var;
++ switch(br_result){
++ case 0:
++ p = tree->br_node;
++ node = tree->slot[p].node;
++ break;
++ case 1:
++ case 2:
++ node = tree->curr;
++ p = node->p;
++ break;
++ default:
++ xerror("glp_ios_branch_log: br_result is not properly set \n");
++ }
++ if( node == NULL ){
++ xerror("glp_ios_branch_log: not called with a valid tree \n");
++ }
++ switch(br_result){
++ case 0:
++ v = node->br_val;
++ d = tree->dn_child;
++ u = tree->up_child;
++ break;
++ case 1:
++ v = mip->col[br_var]->prim;
++ if(tree->br_to_up){
++ d = -1;
++ u = p;
++ }else{
++ d = p;
++ u = -1;
++ }
++ break;
++ case 2:
++ v = mip->col[br_var]->prim;
++ d = -1;
++ u = -1;
++ break;
++ default:
++ xerror("glp_ios_branch_log: not called with a valid tree \n");
++ }
++
++ if(br_val != NULL){ *br_val = v; }
++ if(parent != NULL){ *parent = p; }
++ if(dn != NULL){ *dn = d; }
++ if(up != NULL){ *up = u; }
++
++ return br_var;
++}
++
++int glp_ios_node_ord(glp_tree *tree, int p){
++ IOSNPD *node;
++ if ( tree == NULL ){
++ xerror("glp_ios_node_ord: not called with a valid tree.\n");
++ }
++ if (!(1 <= p && p <= tree->nslots)){
++ xerror("glp_ios_node_ord: not called with a valid p.\n");
++ }
++ node = tree->slot[p].node;
++ return node->ord;
++}
++
++void ios_cb_rows_deleted(glp_tree *T, int n, const int* rows){
++ if (T->parm->cb_func != NULL)
++ {
++ xassert(T->reason == 0);
++ xassert(T->deleting_rows == NULL);
++ xassert(T->num_deleting_rows == 0);
++ T->num_deleting_rows = n;
++ T->deleting_rows = rows;
++
++ T->reason = GLP_LI_DELROW;
++ T->parm->cb_func(T, T->parm->cb_info);
++ T->reason = 0;
++ T->num_deleting_rows = 0;
++ T->deleting_rows = NULL;
++ }
++}
++
++int glp_ios_rows_deleted(glp_tree *tree, int* rows){
++ if ( tree == NULL ){
++ xerror("glp_ios_rows_deleted: not called with a valid tree.\n");
++ }
++ if ( tree->reason != GLP_LI_DELROW ){
++ xerror("glp_ios_rows_deleted: not called with a valid reason.\n");
++ }
++
++ int j;
++ if(rows != NULL){
++ for(j=1; j <= tree->num_deleting_rows; j++){
++ rows[j] = tree->deleting_rows[j];
++ }
++ }
++ return tree->num_deleting_rows;
++}
+diff --git a/src/glpapi06.c b/src/glpapi06.c
+index 743d6be..05d0498 100644
+--- a/src/glpapi06.c
++++ b/src/glpapi06.c
+@@ -488,6 +488,7 @@ void glp_init_smcp(glp_smcp *parm)
+ parm->out_frq = 500;
+ parm->out_dly = 0;
+ parm->presolve = GLP_OFF;
++ parm->stability_lmt = 200;
+ return;
+ }
+
+diff --git a/src/glpapi13.c b/src/glpapi13.c
+index 926dda4..55adf44 100644
+--- a/src/glpapi13.c
++++ b/src/glpapi13.c
+@@ -453,8 +453,14 @@ void glp_ios_row_attr(glp_tree *tree, int i, glp_attr *attr)
+
+ int glp_ios_pool_size(glp_tree *tree)
+ { /* determine current size of the cut pool */
+- if (tree->reason != GLP_ICUTGEN)
+- xerror("glp_ios_pool_size: operation not allowed\n");
++ switch(tree->reason)
++ { case GLP_ICUTGEN:
++ case GLP_ICUTADDED:
++ case GLP_ICUTSELECT:
++ break;
++ default:
++ xerror("glp_ios_pool_size: operation not allowed\n");
++ }
+ xassert(tree->local != NULL);
+ return tree->local->size;
+ }
+diff --git a/src/glpios.h b/src/glpios.h
+index 9e2d6b2..3b31901 100644
+--- a/src/glpios.h
++++ b/src/glpios.h
+@@ -36,6 +36,9 @@ typedef struct IOSAIJ IOSAIJ;
+ typedef struct IOSPOOL IOSPOOL;
+ typedef struct IOSCUT IOSCUT;
+
++
++typedef struct IOSAUX IOSAUX;
++
+ struct glp_tree
+ { /* branch-and-bound tree */
+ int magic;
+@@ -217,6 +220,19 @@ struct glp_tree
+ GLP_NO_BRNCH - use general selection technique */
+ int child;
+ /* subproblem reference number corresponding to br_sel */
++
++ /* start of cut log extras */
++ int br_result;
++ int br_to_up;
++ int br_node;
++ /* subproblem reference number for the just branched node.*/
++ int dn_child;
++ /* subproblem reference number for the just created down node */
++ int up_child;
++ /* subproblem reference number for the just created up node */
++
++ const int* deleting_rows;
++ int num_deleting_rows;
+ };
+
+ struct IOSLOT
+@@ -229,6 +245,8 @@ struct IOSLOT
+
+ struct IOSNPD
+ { /* node subproblem descriptor */
++ int ord;
++ /* this is a unique ordinal for each subproblem */
+ int p;
+ /* subproblem reference number (it is the index to corresponding
+ slot, i.e. slot[p] points to this descriptor) */
+@@ -393,12 +411,51 @@ struct IOSCUT
+ GLP_FX: sum a[j] * x[j] = b */
+ double rhs;
+ /* cut right-hand side */
++
++ IOSAUX *aux;
++ /* cut auxillary source information */
++
+ IOSCUT *prev;
+ /* pointer to previous cut */
+ IOSCUT *next;
+ /* pointer to next cut */
+ };
+
++struct IOSAUX
++{
++ /* aux (auxillary source information for each cut)
++ * Each cut operates on a sum of rows
++ * Each cut operates on a row that can be described using
++ * a current row or a previous cut.
++ * To generalize, we assume each row is a sum of two rows:
++ * row[r]* r_mult + pool[c] * c_mult
++ */
++ int nrows;
++ int *rows;
++ double *mult;
++
++ int selected;
++ /* when < 0 this has not yet been turned into a row
++ when >=0 this is the id of the row added. */
++
++ double mir_delta;
++ /* the delta selected by a mir cut */
++
++ char *mir_cset;
++ /* complimented set */
++ /* if this is NULL, it is implicitly all 0s */
++
++ char *mir_subst;
++ /* the substition vectors */
++
++ int *mir_vlb_rows;
++ /* the substition vectors */
++
++ int *mir_vub_rows;
++ /* the substition vectors */
++};
++
++
+ #define ios_create_tree _glp_ios_create_tree
+ glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm);
+ /* create branch-and-bound tree */
+@@ -615,6 +672,31 @@ int ios_choose_node(glp_tree *T);
+ int ios_choose_var(glp_tree *T, int *next);
+ /* select variable to branch on */
+
++/* functions added to retrieve information */
++IOSAUX *ios_create_aux(int n, const int rows[], const double coeffs[]);
++/* creates an aux with n rows */
++
++void ios_delete_aux(IOSAUX *aux);
++/* deletes an aux */
++
++void ios_cut_set_single_aux(glp_tree *T, int ord, int j);
++/* sets the aux of row ord to be a single row j */
++
++
++void ios_cut_set_aux(glp_tree *T, int ord, int n,
++ const int rows[], const double coeffs[]);
++/* sets an arbitrary aux sum */
++
++void ios_cut_set_aux_mir(glp_tree *T, int ord, double delta,
++ const char cset[], const char subst[],
++ const int vlbrs[], const int vubrs[]);
++/* sets the extra mir information */
++
++void ios_cut_set_selected(IOSCUT *cut, int i);
++/* the cut has been added as row i */
++
++void ios_cb_rows_deleted(glp_tree *T, int n, const int* rows);
++
+ #endif
+
+ /* eof */
+diff --git a/src/glpios01.c b/src/glpios01.c
+index 70798fd..d9e5703 100644
+--- a/src/glpios01.c
++++ b/src/glpios01.c
+@@ -159,6 +159,16 @@ glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm)
+ tree->stop = 0;
+ /* create the root subproblem, which initially is identical to
+ the original MIP */
++
++ tree->br_result = 0;
++ tree->br_to_up = 0;
++ tree->br_node = 0;
++ tree->dn_child = 0;
++ tree->up_child = 0;
++
++ tree->deleting_rows = NULL;
++ tree->num_deleting_rows = 0;
++
+ new_node(tree, NULL);
+ return tree;
+ }
+@@ -278,6 +288,7 @@ void ios_revive_node(glp_tree *tree, int p)
+ double *val;
+ ind = xcalloc(1+n, sizeof(int));
+ val = xcalloc(1+n, sizeof(double));
++ /* maintains the row order during revival */
+ for (r = node->r_ptr; r != NULL; r = r->next)
+ { i = glp_add_rows(mip, 1);
+ glp_set_row_name(mip, i, r->name);
+@@ -457,6 +468,13 @@ void ios_freeze_node(glp_tree *tree)
+ double *val;
+ ind = xcalloc(1+n, sizeof(int));
+ val = xcalloc(1+n, sizeof(double));
++ /* Added rows are stored in the same order!
++ * This is done by 2 reversals.
++ * - Going from i = m down pred_m.
++ * - Storing the list by a stack "push"
++ * node->r_ptr = r;
++ * r->next = node->r_ptr;
++ */
+ for (i = m; i > pred_m; i--)
+ { GLPROW *row = mip->row[i];
+ IOSROW *r;
+@@ -501,6 +519,8 @@ void ios_freeze_node(glp_tree *tree)
+ xassert(nrs > 0);
+ num = xcalloc(1+nrs, sizeof(int));
+ for (i = 1; i <= nrs; i++) num[i] = root_m + i;
++ /* To not call ios_cb_rows_deleted here.
++ These rows have been saved earlier. */
+ glp_del_rows(mip, nrs, num);
+ xfree(num);
+ }
+@@ -636,6 +656,9 @@ static IOSNPD *new_node(glp_tree *tree, IOSNPD *parent)
+ tree->a_cnt++;
+ tree->n_cnt++;
+ tree->t_cnt++;
++
++ node->ord = tree->t_cnt;
++
+ /* increase the number of child subproblems */
+ if (parent == NULL)
+ xassert(p == 1);
+@@ -818,6 +841,8 @@ void ios_delete_tree(glp_tree *tree)
+ xassert(nrs > 0);
+ num = xcalloc(1+nrs, sizeof(int));
+ for (i = 1; i <= nrs; i++) num[i] = tree->orig_m + i;
++ /* Do not call ios_cb_rows_deleted here.
++ This does not help log information. */
+ glp_del_rows(mip, nrs, num);
+ xfree(num);
+ }
+@@ -1417,6 +1442,7 @@ int ios_add_row(glp_tree *tree, IOSPOOL *pool,
+ cut->rhs = rhs;
+ cut->prev = pool->tail;
+ cut->next = NULL;
++ cut->aux = NULL;
+ if (cut->prev == NULL)
+ pool->head = cut;
+ else
+@@ -1517,6 +1543,11 @@ void ios_del_row(glp_tree *tree, IOSPOOL *pool, int i)
+ cut->ptr = aij->next;
+ dmp_free_atom(tree->pool, aij, sizeof(IOSAIJ));
+ }
++
++ if (cut->aux != NULL){
++ ios_delete_aux(cut->aux);
++ }
++
+ dmp_free_atom(tree->pool, cut, sizeof(IOSCUT));
+ pool->size--;
+ return;
+@@ -1535,6 +1566,10 @@ void ios_clear_pool(glp_tree *tree, IOSPOOL *pool)
+ cut->ptr = aij->next;
+ dmp_free_atom(tree->pool, aij, sizeof(IOSAIJ));
+ }
++
++ if (cut->aux != NULL){
++ ios_delete_aux(cut->aux);
++ }
+ dmp_free_atom(tree->pool, cut, sizeof(IOSCUT));
+ }
+ pool->size = 0;
+diff --git a/src/glpios03.c b/src/glpios03.c
+index 80d701b..03e9208 100644
+--- a/src/glpios03.c
++++ b/src/glpios03.c
+@@ -358,12 +358,12 @@ static void fix_by_red_cost(glp_tree *T)
+ * 2 - both branches are hopeless and have been pruned; new subproblem
+ * selection is needed to continue the search. */
+
+-static int branch_on(glp_tree *T, int j, int next)
++static int branch_on(glp_tree *T, int j, int next, int clone[], int* to_up)
+ { glp_prob *mip = T->mip;
+ IOSNPD *node;
+ int m = mip->m;
+ int n = mip->n;
+- int type, dn_type, up_type, dn_bad, up_bad, p, ret, clone[1+2];
++ int type, dn_type, up_type, dn_bad, up_bad, p, ret;
+ double lb, ub, beta, new_ub, new_lb, dn_lp, up_lp, dn_bnd, up_bnd;
+ /* determine bounds and value of x[j] in optimal solution to LP
+ relaxation of the current subproblem */
+@@ -431,6 +431,7 @@ static int branch_on(glp_tree *T, int j, int next)
+ else
+ xassert(mip != mip);
+ ret = 1;
++ *to_up = 0; /* up is bad. Do not go to up. */
+ goto done;
+ }
+ else if (dn_bad)
+@@ -449,6 +450,7 @@ static int branch_on(glp_tree *T, int j, int next)
+ else
+ xassert(mip != mip);
+ ret = 1;
++ *to_up = 1; /* down is bad. Go to up. */
+ goto done;
+ }
+ /* both down- and up-branches seem to be hopeful */
+@@ -702,7 +704,8 @@ static void remove_cuts(glp_tree *T)
+ }
+ }
+ if (cnt > 0)
+- { glp_del_rows(T->mip, cnt, num);
++ { ios_cb_rows_deleted(T, cnt, num);
++ glp_del_rows(T->mip, cnt, num);
+ #if 0
+ xprintf("%d inactive cut(s) removed\n", cnt);
+ #endif
+@@ -784,6 +787,7 @@ static void display_cut_info(glp_tree *T)
+
+ int ios_driver(glp_tree *T)
+ { int p, curr_p, p_stat, d_stat, ret;
++ int branch_clones[1 + 2];
+ #if 1 /* carry out to glp_tree */
+ int pred_p = 0;
+ /* if the current subproblem has been just created due to
+@@ -1010,6 +1014,12 @@ more: /* minor loop starts here */
+ if (T->parm->msg_lev >= GLP_MSG_DBG)
+ xprintf("LP relaxation has no feasible solution\n");
+ /* prune the branch */
++ if (T->parm->cb_func != NULL)
++ { xassert(T->reason == 0);
++ T->reason = GLP_LI_CLOSE;
++ T->parm->cb_func(T, T->parm->cb_info);
++ T->reason = 0;
++ }
+ goto fath;
+ }
+ else
+@@ -1219,6 +1229,14 @@ more: /* minor loop starts here */
+ ios_process_cuts(T);
+ T->reason = 0;
+ }
++ /* if the local cut pool is not empty and the callback func is there,
++ this gives the callback the chance to see what was selected. */
++ if (T->parm->cb_func != NULL && T->local->size > 0)
++ { xassert(T->reason == 0);
++ T->reason = GLP_ICUTSELECT;
++ T->parm->cb_func(T, T->parm->cb_info);
++ T->reason = 0;
++ }
+ /* clear the local cut pool */
+ ios_clear_pool(T, T->local);
+ /* perform re-optimization, if necessary */
+@@ -1255,7 +1273,34 @@ more: /* minor loop starts here */
+ T->br_var = ios_choose_var(T, &T->br_sel);
+ /* perform actual branching */
+ curr_p = T->curr->p;
+- ret = branch_on(T, T->br_var, T->br_sel);
++ xassert(T->br_to_up == 0);
++ ret = branch_on(T, T->br_var, T->br_sel, branch_clones, &T->br_to_up);
++ if (T->parm->cb_func != NULL)
++ { xassert(T->reason == 0);
++ xassert(T->br_node == 0);
++ xassert(T->dn_child == 0);
++ xassert(T->up_child == 0);
++ // record a branch here
++ T->reason = GLP_LI_BRANCH;
++ // at this point T->br_var is the branching variable
++ T->br_node = curr_p;
++ T->br_result = ret;
++ if(ret == 0){
++ T->dn_child = branch_clones[1];
++ T->up_child = branch_clones[2];
++ }
++ T->parm->cb_func(T, T->parm->cb_info);
++ T->reason = 0;
++ T->br_node = 0;
++ T->dn_child = 0;
++ T->up_child = 0;
++ if (T->stop)
++ { ret = GLP_ESTOP;
++ goto done;
++ }
++ }
++ T->br_to_up = 0;
++
+ T->br_var = T->br_sel = 0;
+ if (ret == 0)
+ { /* both branches have been created */
+diff --git a/src/glpios05.c b/src/glpios05.c
+index b9322b9..caf69d7 100644
+--- a/src/glpios05.c
++++ b/src/glpios05.c
+@@ -65,6 +65,9 @@ static void gen_cut(glp_tree *tree, struct worka *worka, int j)
+ double *phi = worka->phi;
+ int i, k, len, kind, stat;
+ double lb, ub, alfa, beta, ksi, phi1, rhs;
++ int input_j;
++ input_j = j;
++
+ /* compute row of the simplex tableau, which (row) corresponds
+ to specified basic variable xB[i] = x[m+j]; see (23) */
+ len = glp_eval_tab_row(mip, m+j, ind, val);
+@@ -73,6 +76,7 @@ static void gen_cut(glp_tree *tree, struct worka *worka, int j)
+ if it would be computed with formula (27); it is assumed that
+ beta[i] is fractional enough */
+ beta = mip->col[j]->prim;
++
+ /* compute cut coefficients phi and right-hand side rho, which
+ correspond to formula (30); dense format is used, because rows
+ of the simplex tableau is usually dense */
+@@ -104,6 +108,7 @@ static void gen_cut(glp_tree *tree, struct worka *worka, int j)
+ xassert(stat != GLP_BS);
+ /* determine row coefficient ksi[i,j] at xN[j]; see (23) */
+ ksi = val[j];
++ /* printf("%d %4.15f ", k, ksi); */
+ /* if ksi[i,j] is too large in the magnitude, do not generate
+ the cut */
+ if (fabs(ksi) > 1e+05) goto fini;
+@@ -135,6 +140,7 @@ static void gen_cut(glp_tree *tree, struct worka *worka, int j)
+ /* y[j] is integer */
+ if (fabs(alfa - floor(alfa + 0.5)) < 1e-10)
+ { /* alfa[i,j] is close to nearest integer; skip it */
++ /* printf("(skip)"); */
+ goto skip;
+ }
+ else if (f(alfa) <= f(beta))
+@@ -170,6 +176,13 @@ static void gen_cut(glp_tree *tree, struct worka *worka, int j)
+ }
+ skip: ;
+ }
++ /* printf("\n"); */
++ /* for (i = 1; i <= m+n; i++) */
++ /* { */
++ /* printf("%i %f, ", i, phi[i]); */
++ /* } */
++ /* printf("\n"); */
++
+ /* now the cut has the form sum_k phi[k] * x[k] >= rho, where cut
+ coefficients are stored in the array phi in dense format;
+ x[1,...,m] are auxiliary variables, x[m+1,...,m+n] are struc-
+@@ -218,8 +231,20 @@ skip: ;
+ ios_add_cut_row(tree, pool, GLP_RF_GMI, len, ind, val, GLP_LO,
+ rhs);
+ #else
+- glp_ios_add_row(tree, NULL, GLP_RF_GMI, 0, len, ind, val, GLP_LO,
+- rhs);
++ int ord;
++ ord = glp_ios_add_row(tree, NULL, GLP_RF_GMI, 0, len, ind, val,
++ GLP_LO, rhs);
++ ios_cut_set_single_aux(tree, ord, input_j);
++
++ /* printf("ord: % d beta %f\n", ord, beta); */
++
++ /** callback for a cut being added to the cut pool */
++ if (tree->parm->cb_func != NULL)
++ { xassert(tree->reason == GLP_ICUTGEN);
++ tree->reason = GLP_ICUTADDED;
++ tree->parm->cb_func(tree, tree->parm->cb_info);
++ tree->reason = GLP_ICUTGEN;
++ }
+ #endif
+ fini: return;
+ }
+diff --git a/src/glpios06.c b/src/glpios06.c
+index 2bd0453..4bd3cf5 100644
+--- a/src/glpios06.c
++++ b/src/glpios06.c
+@@ -100,6 +100,29 @@ struct MIR
+ /* sparse vector of cutting plane coefficients, alpha[k] */
+ double cut_rhs;
+ /* right-hand size of the cutting plane, beta */
++
++ /*-------------------------------------------------------------*/
++ /* Extras I've added to reproduce a cut externally */
++ double cut_delta;
++ /* the delta used for generating the cut */
++ char *cut_cset; /* char cut_vec[1+m+n]; */
++ /* cut_cset[k], 1 <= k <= m+n, is set to true if structural
++ variable x[k] was complemented in the cut:
++ 0 - x[k] has been not been complemented
++ non 0 - x[k] has been complemented */
++ int *vlb_rows; /* int vlb_rows[1+m+n]; */
++ /* vlb_rows[k], 1 <= k <= m+n,
++ * vlb_rows[k] <= 0 if virtual lower bound has not been set
++ * vlb_rows[k] = r if virtual lower bound was set using the row r
++ */
++ int *vub_rows; /* int vub_rows[1+m+n]; */
++ /* vub_rows[k], 1 <= k <= m+n,
++ * vub_rows[k] <= 0 if virtual upper bound has not been set
++ * vub_rows[k] = r if virtual upper bound was set using the row r
++ */
++
++ double *agg_coeffs;
++ /* coefficients used to multiply agg_coeffs */
+ };
+
+ /***********************************************************************
+@@ -146,6 +169,7 @@ static void set_row_attrib(glp_tree *tree, struct MIR *mir)
+ xassert(row != row);
+ }
+ mir->vlb[k] = mir->vub[k] = 0;
++ mir->vlb_rows[k] = mir->vub_rows[k] = 0;
+ }
+ return;
+ }
+@@ -181,6 +205,7 @@ static void set_col_attrib(glp_tree *tree, struct MIR *mir)
+ xassert(col != col);
+ }
+ mir->vlb[k] = mir->vub[k] = 0;
++ mir->vlb_rows[k] = mir->vub_rows[k] = 0;
+ }
+ return;
+ }
+@@ -230,6 +255,7 @@ static void set_var_bounds(glp_tree *tree, struct MIR *mir)
+ { /* set variable lower bound for x1 */
+ mir->lb[k1] = - a2 / a1;
+ mir->vlb[k1] = k2;
++ mir->vlb_rows[k1] = i;
+ /* the row should not be used */
+ mir->skip[i] = 1;
+ }
+@@ -240,6 +266,7 @@ static void set_var_bounds(glp_tree *tree, struct MIR *mir)
+ { /* set variable upper bound for x1 */
+ mir->ub[k1] = - a2 / a1;
+ mir->vub[k1] = k2;
++ mir->vub_rows[k1] = i;
+ /* the row should not be used */
+ mir->skip[i] = 1;
+ }
+@@ -313,6 +340,13 @@ void *ios_mir_init(glp_tree *tree)
+ mir->subst = xcalloc(1+m+n, sizeof(char));
+ mir->mod_vec = ios_create_vec(m+n);
+ mir->cut_vec = ios_create_vec(m+n);
++
++ /* added */
++ mir->cut_cset = xcalloc(1+m+n, sizeof(char));
++ mir->vlb_rows = xcalloc(1+m+n, sizeof(int));
++ mir->vub_rows = xcalloc(1+m+n, sizeof(int));
++ mir->agg_coeffs = xcalloc(1+MAXAGGR, sizeof(double));
++
+ /* set global row attributes */
+ set_row_attrib(tree, mir);
+ /* set global column attributes */
+@@ -405,6 +439,9 @@ static void initial_agg_row(glp_tree *tree, struct MIR *mir, int i)
+ mir->skip[i] = 2;
+ mir->agg_cnt = 1;
+ mir->agg_row[1] = i;
++
++ mir->agg_coeffs[1] = +1.0;
++
+ /* use x[i] - sum a[i,j] * x[m+j] = 0, where x[i] is auxiliary
+ variable of row i, x[m+j] are structural variables */
+ ios_clear_vec(mir->agg_vec);
+@@ -784,19 +821,19 @@ static int cmir_cmp(const void *p1, const void *p2)
+
+ static double cmir_sep(const int n, const double a[], const double b,
+ const double u[], const double x[], const double s,
+- double alpha[], double *beta, double *gamma)
++ double alpha[], double *beta, double *gamma,
++ double* delta, char cset[])
+ { int fail, j, k, nv, v;
+- double delta, eps, d_try[1+3], r, r_best;
+- char *cset;
++ double eps, d_try[1+3], r, r_best;
+ struct vset *vset;
+ /* allocate working arrays */
+- cset = xcalloc(1+n, sizeof(char));
++ //cset = xcalloc(1+n, sizeof(char));
+ vset = xcalloc(1+n, sizeof(struct vset));
+ /* choose initial C */
+ for (j = 1; j <= n; j++)
+ cset[j] = (char)(x[j] >= 0.5 * u[j]);
+ /* choose initial delta */
+- r_best = delta = 0.0;
++ r_best = (*delta) = 0.0;
+ for (j = 1; j <= n; j++)
+ { xassert(a[j] != 0.0);
+ /* if x[j] is close to its bounds, skip it */
+@@ -809,16 +846,16 @@ static double cmir_sep(const int n, const double a[], const double b,
+ /* compute violation */
+ r = - (*beta) - (*gamma) * s;
+ for (k = 1; k <= n; k++) r += alpha[k] * x[k];
+- if (r_best < r) r_best = r, delta = fabs(a[j]);
++ if (r_best < r) r_best = r, (*delta) = fabs(a[j]);
+ }
+ if (r_best < 0.001) r_best = 0.0;
+ if (r_best == 0.0) goto done;
+- xassert(delta > 0.0);
++ xassert((*delta) > 0.0);
+ /* try to increase violation by dividing delta by 2, 4, and 8,
+ respectively */
+- d_try[1] = delta / 2.0;
+- d_try[2] = delta / 4.0;
+- d_try[3] = delta / 8.0;
++ d_try[1] = (*delta) / 2.0;
++ d_try[2] = (*delta) / 4.0;
++ d_try[3] = (*delta) / 8.0;
+ for (j = 1; j <= 3; j++)
+ { /* construct c-MIR inequality */
+ fail = cmir_ineq(n, a, b, u, cset, d_try[j], alpha, beta,
+@@ -827,7 +864,7 @@ static double cmir_sep(const int n, const double a[], const double b,
+ /* compute violation */
+ r = - (*beta) - (*gamma) * s;
+ for (k = 1; k <= n; k++) r += alpha[k] * x[k];
+- if (r_best < r) r_best = r, delta = d_try[j];
++ if (r_best < r) r_best = r, (*delta) = d_try[j];
+ }
+ /* build subset of variables lying strictly between their bounds
+ and order it by nondecreasing values of |x[j] - u[j]/2| */
+@@ -849,7 +886,7 @@ static double cmir_sep(const int n, const double a[], const double b,
+ /* replace x[j] by its complement or vice versa */
+ cset[j] = (char)!cset[j];
+ /* construct c-MIR inequality */
+- fail = cmir_ineq(n, a, b, u, cset, delta, alpha, beta, gamma);
++ fail = cmir_ineq(n, a, b, u, cset, (*delta), alpha, beta, gamma);
+ /* restore the variable */
+ cset[j] = (char)!cset[j];
+ /* do not replace the variable in case of failure */
+@@ -860,10 +897,11 @@ static double cmir_sep(const int n, const double a[], const double b,
+ if (r_best < r) r_best = r, cset[j] = (char)!cset[j];
+ }
+ /* construct the best c-MIR inequality chosen */
+- fail = cmir_ineq(n, a, b, u, cset, delta, alpha, beta, gamma);
++ fail = cmir_ineq(n, a, b, u, cset, (*delta), alpha, beta, gamma);
+ xassert(!fail);
++
+ done: /* free working arrays */
+- xfree(cset);
++
+ xfree(vset);
+ /* return to the calling routine */
+ return r_best;
+@@ -874,7 +912,8 @@ static double generate(struct MIR *mir)
+ int m = mir->m;
+ int n = mir->n;
+ int j, k, kk, nint;
+- double s, *u, *x, *alpha, r_best = 0.0, b, beta, gamma;
++ double s, *u, *x, *alpha, r_best = 0.0, b, beta, gamma, delta;
++ char *cset;
+ ios_copy_vec(mir->cut_vec, mir->mod_vec);
+ mir->cut_rhs = mir->mod_rhs;
+ /* remove small terms, which can appear due to substitution of
+@@ -923,6 +962,7 @@ static double generate(struct MIR *mir)
+ u = xcalloc(1+nint, sizeof(double));
+ x = xcalloc(1+nint, sizeof(double));
+ alpha = xcalloc(1+nint, sizeof(double));
++ cset = xcalloc(1+nint, sizeof(char));
+ /* determine u and x */
+ for (j = 1; j <= nint; j++)
+ { k = mir->cut_vec->ind[j];
+@@ -936,6 +976,7 @@ static double generate(struct MIR *mir)
+ x[j] = mir->ub[k] - mir->x[k];
+ else
+ xassert(k != k);
++ if(!(x[j] >= -0.001)) { goto skip; }
+ xassert(x[j] >= -0.001);
+ if (x[j] < 0.0) x[j] = 0.0;
+ }
+@@ -965,6 +1006,7 @@ static double generate(struct MIR *mir)
+ }
+ else
+ xassert(k != k);
++ if(!(x >= -0.001)) { goto skip; }
+ xassert(x >= -0.001);
+ if (x < 0.0) x = 0.0;
+ s -= mir->cut_vec->val[j] * x;
+@@ -973,7 +1015,7 @@ static double generate(struct MIR *mir)
+ /* apply heuristic to obtain most violated c-MIR inequality */
+ b = mir->cut_rhs;
+ r_best = cmir_sep(nint, mir->cut_vec->val, b, u, x, s, alpha,
+- &beta, &gamma);
++ &beta, &gamma, &delta, cset);
+ if (r_best == 0.0) goto skip;
+ xassert(r_best > 0.0);
+ /* convert to raw cut */
+@@ -988,10 +1030,22 @@ static double generate(struct MIR *mir)
+ #if _MIR_DEBUG
+ ios_check_vec(mir->cut_vec);
+ #endif
++ /* added */
++ mir->cut_delta = delta;
++ // this is not a great place for resetting the array,
++ // but it should be sufficient
++ for (j = 1; j <= n+m; j++)
++ mir->cut_cset[j] = 0;
++ for (j = 1; j <= nint; j++)
++ { k = mir->cut_vec->ind[j];
++ xassert(m <= k && k <= m+n);
++ mir->cut_cset[k] = cset[j];
++ }
+ skip: /* free working arrays */
+ xfree(u);
+ xfree(x);
+ xfree(alpha);
++ xfree(cset);
+ done: return r_best;
+ }
+
+@@ -1199,8 +1253,25 @@ static void add_cut(glp_tree *tree, struct MIR *mir)
+ ios_add_cut_row(tree, pool, GLP_RF_MIR, len, ind, val, GLP_UP,
+ mir->cut_rhs);
+ #else
+- glp_ios_add_row(tree, NULL, GLP_RF_MIR, 0, len, ind, val, GLP_UP,
++ int ord;
++ ord = glp_ios_add_row(tree, NULL, GLP_RF_MIR, 0, len, ind, val, GLP_UP,
+ mir->cut_rhs);
++ ios_cut_set_aux(tree, ord, mir->agg_cnt, mir->agg_row, mir->agg_coeffs);
++ ios_cut_set_aux_mir(tree, ord, mir->cut_delta,
++ mir->cut_cset, mir->subst,
++ mir->vlb_rows, mir->vub_rows);
++
++ /** callback for a cut being added to the cut pool */
++ /* printf("mir tree parm %p %d\n", tree->parm->cb_func, ord); */
++ /* printf(" agg_rhs %f\n", mir->agg_rhs); */
++ /* printf(" mod_rhs %f\n", mir->mod_rhs); */
++ /* printf(" cut_rhs %f\n", mir->cut_rhs); */
++ if (tree->parm->cb_func != NULL)
++ { xassert(tree->reason == GLP_ICUTGEN);
++ tree->reason = GLP_ICUTADDED;
++ tree->parm->cb_func(tree, tree->parm->cb_info);
++ tree->reason = GLP_ICUTGEN;
++ }
+ #endif
+ xfree(ind);
+ xfree(val);
+@@ -1216,6 +1287,7 @@ static int aggregate_row(glp_tree *tree, struct MIR *mir)
+ IOSVEC *v;
+ int ii, j, jj, k, kk, kappa = 0, ret = 0;
+ double d1, d2, d, d_max = 0.0;
++ double guass_coeff;
+ /* choose appropriate structural variable in the aggregated row
+ to be substituted */
+ for (j = 1; j <= mir->agg_vec->nnz; j++)
+@@ -1300,8 +1372,9 @@ static int aggregate_row(glp_tree *tree, struct MIR *mir)
+ xassert(j != 0);
+ jj = v->pos[kappa];
+ xassert(jj != 0);
+- ios_linear_comb(mir->agg_vec,
+- - mir->agg_vec->val[j] / v->val[jj], v);
++ guass_coeff = - mir->agg_vec->val[j] / v->val[jj];
++ mir->agg_coeffs[mir->agg_cnt] = guass_coeff;
++ ios_linear_comb(mir->agg_vec, guass_coeff, v);
+ ios_delete_vec(v);
+ ios_set_vj(mir->agg_vec, kappa, 0.0);
+ #if _MIR_DEBUG
+@@ -1440,6 +1513,13 @@ void ios_mir_term(void *gen)
+ xfree(mir->subst);
+ ios_delete_vec(mir->mod_vec);
+ ios_delete_vec(mir->cut_vec);
++
++ /* added */
++ xfree(mir->cut_cset);
++ xfree(mir->vlb_rows);
++ xfree(mir->vub_rows);
++ xfree(mir->agg_coeffs);
++
+ xfree(mir);
+ return;
+ }
+diff --git a/src/glpios07.c b/src/glpios07.c
+index 0892550..9f742e6 100644
+--- a/src/glpios07.c
++++ b/src/glpios07.c
+@@ -543,6 +543,14 @@ void ios_cov_gen(glp_tree *tree)
+ /* add the cut to the cut pool */
+ glp_ios_add_row(tree, NULL, GLP_RF_COV, 0, len, ind, val,
+ GLP_UP, val[0]);
++
++ /** callback for a cut being added to the cut pool */
++ if (tree->parm->cb_func != NULL)
++ { xassert(tree->reason == GLP_ICUTGEN);
++ tree->reason = GLP_ICUTADDED;
++ tree->parm->cb_func(tree, tree->parm->cb_info);
++ tree->reason = GLP_ICUTGEN;
++ }
+ }
+ /* free working arrays */
+ xfree(ind);
+diff --git a/src/glpios08.c b/src/glpios08.c
+index 2d2fcd5..3aad808 100644
+--- a/src/glpios08.c
++++ b/src/glpios08.c
+@@ -129,6 +129,15 @@ void ios_clq_gen(glp_tree *T, void *G_)
+ /* add cut inequality to local cut pool */
+ glp_ios_add_row(T, NULL, GLP_RF_CLQ, 0, len, ind, val, GLP_UP,
+ rhs);
++
++ /** callback for a cut being added to the cut pool */
++ if (T->parm->cb_func != NULL)
++ { xassert(T->reason == GLP_ICUTGEN);
++ T->reason = GLP_ICUTADDED;
++ T->parm->cb_func(T, T->parm->cb_info);
++ T->reason = GLP_ICUTGEN;
++ }
++
+ skip: /* free working arrays */
+ tfree(ind);
+ tfree(val);
+diff --git a/src/glpios11.c b/src/glpios11.c
+index c40e9a5..82d5698 100644
+--- a/src/glpios11.c
++++ b/src/glpios11.c
+@@ -193,6 +193,9 @@ void ios_process_cuts(glp_tree *T)
+ glp_set_mat_row(T->mip, i, len, ind, val);
+ xassert(cut->type == GLP_LO || cut->type == GLP_UP);
+ glp_set_row_bnds(T->mip, i, cut->type, cut->rhs, cut->rhs);
++
++ /* setting this as selected */
++ ios_cut_set_selected(cut, i);
+ }
+ /* free working arrays */
+ xfree(info);
+diff --git a/src/glpk.h b/src/glpk.h
+index 75c292c..e117782 100644
+--- a/src/glpk.h
++++ b/src/glpk.h
+@@ -130,6 +130,7 @@ typedef struct
+ int out_frq; /* spx.out_frq */
+ int out_dly; /* spx.out_dly (milliseconds) */
+ int presolve; /* enable/disable using LP presolver */
++ int stability_lmt; /* maximum number of check stability failures before stopping */
+ double foo_bar[36]; /* (reserved) */
+ } glp_smcp;
+
+@@ -229,6 +230,11 @@ typedef struct
+ #define GLP_IBRANCH 0x05 /* request for branching */
+ #define GLP_ISELECT 0x06 /* request for subproblem selection */
+ #define GLP_IPREPRO 0x07 /* request for preprocessing */
++#define GLP_ICUTADDED 0x08 /* cut was added to the pool */
++#define GLP_ICUTSELECT 0x09 /* cuts were selected as rows */
++#define GLP_LI_BRANCH 0x10 /* a branch was made */
++#define GLP_LI_CLOSE 0x11 /* an active node was closed */
++#define GLP_LI_DELROW 0x12 /* an active node was closed */
+
+ /* branch selection indicator: */
+ #define GLP_NO_BRNCH 0 /* select no branch */
+@@ -1057,6 +1063,54 @@ int glp_top_sort(glp_graph *G, int v_num);
+ int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set);
+ /* find maximum weight clique with exact algorithm */
+
++/*******************************************/
++/*** CUT LOG ***/
++/*******************************************/
++
++int glp_get_it_cnt(glp_prob *P);
++/* get the iteration count of the current problem */
++
++
++int glp_ios_get_cut(glp_tree *T, int i, int ind[], double val[], int* klass, int* type, double* rhs);
++/* determine reason for calling the callback routine */
++
++int glp_ios_cut_get_aux_nrows(glp_tree *tree, int ord);
++/* gets the number of rows used to generate a cut. */
++
++
++void glp_ios_cut_get_aux_rows(glp_tree *tree, int ord,
++ int rows[], double coeffs[]);
++/* gets a cut as an input sequence of rows times coefficients. */
++
++
++void glp_ios_cut_get_mir_cset(glp_tree *tree, int ord, char cset[]);
++/* gets mir cut complement set. */
++double glp_ios_cut_get_mir_delta(glp_tree *tree, int ord);
++/* gets mir cut delta. */
++void glp_ios_cut_get_mir_subst(glp_tree *tree, int ord, char subst[]);
++/* gets mir cut substition information. */
++void glp_ios_cut_get_mir_virtual_rows(glp_tree *tree, int ord,
++ int vlb_rows[], int vub_rows[]);
++/* gets mir cut virtual bounds rows. */
++
++int glp_ios_selected_cuts(glp_tree *tree, int ords[], int sel[]);
++/* gets the list of selected cuts.
++ Can only be called when GLP_ICUTSELECT */
++
++
++int glp_ios_branch_log(glp_tree *tree, double *val, int* parent, int* dn, int* up);
++/* can only be called when GLP_LI_BRANCH.
++ * If id is non-null, returns the id of the structural variable branched upon.
++ * If val is non-null, it is set to the value branched upon.
++ * If parent is non-null, it is set to node id of the node branched upon.
++ * If dn is non-null, it is set to node id of the newly created down node.
++ * If up is non-null, it is set to node id of the newly created up node.
++ */
++
++int glp_ios_node_ord(glp_tree *tree, int node_p);
++
++int glp_ios_rows_deleted(glp_tree *tree, int* rows);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/src/glpspx01.c b/src/glpspx01.c
+index 5c17114..caaab27 100644
+--- a/src/glpspx01.c
++++ b/src/glpspx01.c
+@@ -238,6 +238,9 @@ struct csa
+ double *work2; /* double work2[1+m]; */
+ double *work3; /* double work3[1+m]; */
+ double *work4; /* double work4[1+m]; */
++
++ /** Things Tim has added. */
++ int stability_failures;
+ };
+
+ static const double kappa = 0.10;
+@@ -400,6 +403,8 @@ static void init_csa(struct csa *csa, glp_prob *lp)
+ csa->refct = 0;
+ memset(&refsp[1], 0, (m+n) * sizeof(char));
+ for (j = 1; j <= n; j++) gamma[j] = 1.0;
++
++ csa->stability_failures = 0;
+ return;
+ }
+
+@@ -2647,6 +2652,11 @@ loop: /* main loop starts here */
+ if (check_stab(csa, parm->tol_bnd))
+ { /* there are excessive bound violations due to round-off
+ errors */
++ csa->stability_failures++;
++ if (csa->stability_failures >= parm->stability_lmt){
++ ret = GLP_EINSTAB;
++ goto done;
++ }
+ if (parm->msg_lev >= GLP_MSG_ERR)
+ xprintf("Warning: numerical instability (primal simplex,"
+ " phase %s)\n", csa->phase == 1 ? "I" : "II");
+diff --git a/src/glpspx02.c b/src/glpspx02.c
+index 19152a6..de3d677 100644
+--- a/src/glpspx02.c
++++ b/src/glpspx02.c
+@@ -288,6 +288,9 @@ struct csa
+ double *work2; /* double work2[1+m]; */
+ double *work3; /* double work3[1+m]; */
+ double *work4; /* double work4[1+m]; */
++
++ /* count the number of stability failures */
++ int stability_failures;
+ };
+
+ static const double kappa = 0.10;
+@@ -501,6 +504,8 @@ static void init_csa(struct csa *csa, glp_prob *lp)
+ csa->refct = 0;
+ memset(&refsp[1], 0, (m+n) * sizeof(char));
+ for (i = 1; i <= m; i++) gamma[i] = 1.0;
++
++ csa->stability_failures = 0;
+ return;
+ }
+
+@@ -2741,7 +2746,13 @@ loop: /* main loop starts here */
+ /* make sure that the current basic solution remains dual
+ feasible */
+ if (check_stab(csa, parm->tol_dj) != 0)
+- { if (parm->msg_lev >= GLP_MSG_ERR)
++ {
++ csa->stability_failures++;
++ if (csa->stability_failures >= parm->stability_lmt){
++ ret = GLP_EINSTAB;
++ goto done;
++ }
++ if (parm->msg_lev >= GLP_MSG_ERR)
+ xprintf("Warning: numerical instability (dual simplex, p"
+ "hase %s)\n", csa->phase == 1 ? "I" : "II");
+ #if 1
+@@ -3023,6 +3034,10 @@ loop: /* main loop starts here */
+ /* accuracy check based on the pivot element */
+ { double piv1 = csa->tcol_vec[csa->p]; /* more accurate */
+ double piv2 = csa->trow_vec[csa->q]; /* less accurate */
++ if(piv1 == 0.0){
++ ret = GLP_EFAIL;
++ goto done;
++ }
+ xassert(piv1 != 0.0);
+ if (fabs(piv1 - piv2) > 1e-8 * (1.0 + fabs(piv1)) ||
+ !(piv1 > 0.0 && piv2 > 0.0 || piv1 < 0.0 && piv2 < 0.0))
+--
+2.26.2
diff --git a/examples/api/python/CMakeLists.txt b/examples/api/python/CMakeLists.txt
index e3966fa2d..0da960513 100644
--- a/examples/api/python/CMakeLists.txt
+++ b/examples/api/python/CMakeLists.txt
@@ -1,9 +1,22 @@
set(EXAMPLES_API_PYTHON
+ bitvectors_and_arrays
+ bitvectors
+ combination
+ datatypes
exceptions
+ extract
+ floating_point
+ helloworld
+ linear_arith
sequences
+ sets
+ strings
+ sygus-fun
+ sygus-grammar
+ sygus-inv
)
-find_package(PythonInterp REQUIRED)
+find_package(PythonInterp ${CVC4_BINDINGS_PYTHON_VERSION} REQUIRED)
# Find Python bindings in the corresponding python-*/site-packages directory.
# Lookup Python module directory and store path in PYTHON_MODULE_PATH.
diff --git a/examples/api/python/exceptions.py b/examples/api/python/exceptions.py
index 780f75bf7..27f068011 100644
--- a/examples/api/python/exceptions.py
+++ b/examples/api/python/exceptions.py
@@ -16,40 +16,40 @@
## A simple demonstration of catching CVC4 execptions with the legacy Python
## API.
-import CVC4
+import pycvc4
+from pycvc4 import kinds
import sys
def main():
- em = CVC4.ExprManager()
- smt = CVC4.SmtEngine(em)
+ slv = pycvc4.Solver()
- smt.setOption("produce-models", CVC4.SExpr("true"))
+ slv.setOption("produce-models", "true")
# Setting an invalid option
try:
- smt.setOption("non-existing", CVC4.SExpr("true"))
+ slv.setOption("non-existing", "true")
return 1
- except CVC4.Exception as e:
- print(e.toString())
+ except:
+ pass
# Creating a term with an invalid type
try:
- integer = em.integerType()
- x = em.mkVar("x", integer)
- invalidExpr = em.mkExpr(CVC4.AND, x, x)
- smt.checkSat(invalidExpr)
+ integer = slv.getIntegerSort()
+ x = slv.mkConst("x", integer)
+ invalidTerm = em.mkTerm(AND, x, x)
+ slv.checkSat(invalidTerm)
return 1
- except CVC4.Exception as e:
- print(e.toString())
+ except:
+ pass
# Asking for a model after unsat result
try:
- smt.checkSat(em.mkBoolConst(False))
- smt.getModel()
+ slv.checkSat(slv.mkBoolean(False))
+ slv.getModel()
return 1
- except CVC4.Exception as e:
- print(e.toString())
+ except:
+ pass
return 0
diff --git a/examples/api/python/floating_point.py b/examples/api/python/floating_point.py
index c92666c0b..6fb595e34 100755
--- a/examples/api/python/floating_point.py
+++ b/examples/api/python/floating_point.py
@@ -20,8 +20,15 @@ from pycvc4 import kinds
if __name__ == "__main__":
slv = pycvc4.Solver()
+
+ if not slv.supportsFloatingPoint():
+ # CVC4 must be built with SymFPU to support the theory of
+ # floating-point numbers
+ print("CVC4 was not built with floating-point support.")
+ exit()
+
slv.setOption("produce-models", "true")
- slv.setLogic("FP")
+ slv.setLogic("QF_FP")
# single 32-bit precision
fp32 = slv.mkFloatingPointSort(8, 24)
diff --git a/examples/api/python/sygus-fun.py b/examples/api/python/sygus-fun.py
index 0f53bd343..25090bd8f 100644
--- a/examples/api/python/sygus-fun.py
+++ b/examples/api/python/sygus-fun.py
@@ -53,7 +53,7 @@ if __name__ == "__main__":
leq = slv.mkTerm(kinds.Leq, start, start)
# create the grammar object
- g = slv.mkSygusGrammar({x, y}, {start, start_bool})
+ g = slv.mkSygusGrammar([x, y], [start, start_bool])
# bind each non-terminal to its rules
g.addRules(start, {zero, one, x, y, plus, minus, ite})
@@ -61,8 +61,8 @@ if __name__ == "__main__":
# declare the functions-to-synthesize. Optionally, provide the grammar
# constraints
- max = slv.synthFun("max", {x, y}, integer, g)
- min = slv.synthFun("min", {x, y}, integer)
+ max = slv.synthFun("max", [x, y], integer, g)
+ min = slv.synthFun("min", [x, y], integer)
# declare universal variables.
varX = slv.mkSygusVar(integer, "x")
diff --git a/proofs/signatures/drat.plf b/proofs/signatures/drat.plf
index ad3c8ec8d..20795901f 100644
--- a/proofs/signatures/drat.plf
+++ b/proofs/signatures/drat.plf
@@ -354,7 +354,7 @@
; Helper for `is_operational_drat_proof` which takes a UP model for the working
; formula. The UP model is important for determining which clause deletions
; actually are executed in operational DRAT. Passing the UP model along
-; prevents it from being fully recomputed everytime.
+; prevents it from being fully recomputed every time.
(program is_operational_drat_proof_h ((f cnf) (up_model clause) (pf DRATProof)) bool
(match pf
(DRATProofn (cnf_has_bottom f))
diff --git a/proofs/signatures/lrat.plf b/proofs/signatures/lrat.plf
index b5d46be43..c10f8d6c8 100644
--- a/proofs/signatures/lrat.plf
+++ b/proofs/signatures/lrat.plf
@@ -101,7 +101,7 @@
((pos v2) ff)
((neg v2) (ifequal v1 v2 tt ff))))))
-; Remove **all** occurences of a literal from clause
+; Remove **all** occurrences of a literal from clause
(program clause_remove_all ((l lit) (c clause)) clause
(match c
(cln cln)
@@ -180,7 +180,7 @@
(CMapc ci c (CMap_remove_many is cs'))))))))
; Given a map of clauses and a literal, return all indices in the map
-; corresponsing to clauses that could resolve against that literal. i.e. for x,
+; corresponding to clauses that could resolve against that literal. i.e. for x,
; return the indices of all clauses containing x.
(program collect_resolution_targets_w_lit ((cs CMap) (l lit)) CIList
(match cs
@@ -260,14 +260,14 @@
(fail Unit)
(ifmarked2 v unit (do (markvar2 v) unit))))))
-; Unmarks the variable within a satified literal to render it neither satified nor falsified
+; Unmarks the variable within a satisfied literal to render it neither satisfied nor falsified
; fails if the literal is not already satisfied
(program lit_un_mk_sat ((l lit)) Unit
(match l
((pos v) (ifmarked1 v (do (markvar1 v) unit) (fail Unit)))
((neg v) (ifmarked2 v (do (markvar2 v) unit) (fail Unit)))))
-; Unmarks the variable within a falsified literal to render it neither satified nor falsified
+; Unmarks the variable within a falsified literal to render it neither satisfied nor falsified
; fails if the literal is not already falsified
(program lit_un_mk_unsat ((l lit)) Unit
(match l
@@ -348,7 +348,7 @@
; The return type for verifying that a clause is unit and modifying the global
; assignment to satisfy it
(declare MarkResult type)
-; The clause is unit, and this is the (previoiusly floating) literal that is now satified.
+; The clause is unit, and this is the (previoiusly floating) literal that is now satisfied.
(declare MRUnit (! l lit MarkResult))
; The clause was unsat!
(declare MRUnsat MarkResult)
@@ -357,7 +357,7 @@
; The clause had multiple floating literals.
(declare MRNotUnit MarkResult)
-; Determine wether this clause is sat, unsat, unit, or not unit, and if it is
+; Determine whether this clause is sat, unsat, unit, or not unit, and if it is
; unit, it modifies the global assignment to satisfy the clause, and returns
; the literal that was made SAT by the new mark.
;
diff --git a/proofs/signatures/th_lira.plf b/proofs/signatures/th_lira.plf
index af326bf27..e3f6df112 100644
--- a/proofs/signatures/th_lira.plf
+++ b/proofs/signatures/th_lira.plf
@@ -128,7 +128,7 @@
(default (fail (term Int)))
))
-; This function negates linear interger terms---sums of terms of the form
+; This function negates linear integer terms---sums of terms of the form
; recognized by `negate_linear_monomial_int_term`.
(program negate_linear_int_term ((t (term Int))) (term Int)
(match t
@@ -339,7 +339,7 @@
; the statement that `a` satisfies `b` for all inputs
(declare bounded_aff (! a aff (! b bound formula)))
-; Sum of two bounds (the bound satisfied by the sum of two functions satifying
+; Sum of two bounds (the bound satisfied by the sum of two functions satisfying
; the input bounds)
(program bound_add ((b bound) (b2 bound)) bound
(match b
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 06bc9917f..692ae09ac 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -118,50 +118,13 @@ libcvc4_add_sources(
printer/smt2/smt2_printer.h
printer/tptp/tptp_printer.cpp
printer/tptp/tptp_printer.h
- proof/arith_proof.cpp
- proof/arith_proof.h
- proof/arith_proof_recorder.cpp
- proof/arith_proof_recorder.h
- proof/array_proof.cpp
- 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/dimacs.cpp
- proof/dimacs.h
- proof/drat/drat_proof.cpp
- proof/drat/drat_proof.h
- proof/er/er_proof.cpp
- proof/er/er_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
- proof/proof_output_channel.cpp
- proof/proof_output_channel.h
- proof/proof_utils.cpp
- proof/proof_utils.h
- proof/resolution_bitvector_proof.cpp
- proof/resolution_bitvector_proof.h
proof/sat_proof.h
proof/sat_proof_implementation.h
- proof/simplify_boolean_node.cpp
- proof/simplify_boolean_node.h
- proof/skolemization_manager.cpp
- proof/skolemization_manager.h
- proof/theory_proof.cpp
- proof/theory_proof.h
- proof/uf_proof.cpp
- proof/uf_proof.h
proof/unsat_core.cpp
proof/unsat_core.h
prop/bvminisat/bvminisat.cpp
@@ -247,6 +210,8 @@ libcvc4_add_sources(
smt/model_core_builder.h
smt/model_blocker.cpp
smt/model_blocker.h
+ smt/node_command.cpp
+ smt/node_command.h
smt/options_manager.cpp
smt/options_manager.h
smt/quant_elim_solver.cpp
@@ -288,6 +253,8 @@ libcvc4_add_sources(
theory/arith/approx_simplex.h
theory/arith/arith_ite_utils.cpp
theory/arith/arith_ite_utils.h
+ theory/arith/arith_lemma.cpp
+ theory/arith/arith_lemma.h
theory/arith/arith_msum.cpp
theory/arith/arith_msum.h
theory/arith/arith_rewriter.cpp
@@ -324,6 +291,8 @@ libcvc4_add_sources(
theory/arith/fc_simplex.h
theory/arith/infer_bounds.cpp
theory/arith/infer_bounds.h
+ theory/arith/inference_manager.cpp
+ theory/arith/inference_manager.h
theory/arith/linear_equality.cpp
theory/arith/linear_equality.h
theory/arith/matrix.cpp
@@ -387,10 +356,6 @@ libcvc4_add_sources(
theory/arith/type_enumerator.h
theory/arrays/array_info.cpp
theory/arrays/array_info.h
- theory/arrays/array_proof_reconstruction.cpp
- theory/arrays/array_proof_reconstruction.h
- theory/arrays/static_fact_manager.cpp
- theory/arrays/static_fact_manager.h
theory/arrays/theory_arrays.cpp
theory/arrays/theory_arrays.h
theory/arrays/theory_arrays_rewriter.cpp
@@ -471,6 +436,8 @@ libcvc4_add_sources(
theory/combination_engine.h
theory/datatypes/datatypes_rewriter.cpp
theory/datatypes/datatypes_rewriter.h
+ theory/datatypes/inference_manager.cpp
+ theory/datatypes/inference_manager.h
theory/datatypes/sygus_datatype_utils.cpp
theory/datatypes/sygus_datatype_utils.h
theory/datatypes/sygus_extension.cpp
@@ -825,6 +792,8 @@ libcvc4_add_sources(
theory/theory_engine_proof_generator.h
theory/theory_id.cpp
theory/theory_id.h
+ theory/theory_inference.cpp
+ theory/theory_inference.h
theory/theory_inference_manager.cpp
theory/theory_inference_manager.h
theory/theory_model.cpp
@@ -1098,7 +1067,6 @@ install(FILES
util/integer_gmp_imp.h
util/maybe.h
util/poly_util.h
- util/proof.h
util/rational_cln_imp.h
util/rational_gmp_imp.h
util/real_algebraic_number_poly_imp.h
diff --git a/src/api/cvc4cpp.cpp b/src/api/cvc4cpp.cpp
index 51ecea9f2..5b3384439 100644
--- a/src/api/cvc4cpp.cpp
+++ b/src/api/cvc4cpp.cpp
@@ -3044,10 +3044,10 @@ Term Solver::mkCharFromStrHelper(const std::string& s) const
CVC4_API_CHECK(s.find_first_not_of("0123456789abcdefABCDEF", 0)
== std::string::npos
&& s.size() <= 5 && s.size() > 0)
- << "Unexpected string for hexidecimal character " << s;
+ << "Unexpected string for hexadecimal character " << s;
uint32_t val = static_cast<uint32_t>(std::stoul(s, 0, 16));
CVC4_API_CHECK(val < String::num_codes())
- << "Not a valid code point for hexidecimal character " << s;
+ << "Not a valid code point for hexadecimal character " << s;
std::vector<unsigned> cpts;
cpts.push_back(val);
return mkValHelper<CVC4::String>(CVC4::String(cpts));
@@ -3148,8 +3148,8 @@ Term Solver::mkTermHelper(Kind kind, const std::vector<Term>& children) const
}
std::vector<Sort> Solver::mkDatatypeSortsInternal(
- std::vector<DatatypeDecl>& dtypedecls,
- std::set<Sort>& unresolvedSorts) const
+ const std::vector<DatatypeDecl>& dtypedecls,
+ const std::set<Sort>& unresolvedSorts) const
{
NodeManagerScope scope(getNodeManager());
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
@@ -3240,6 +3240,14 @@ void Solver::checkMkTerm(Kind kind, uint32_t nchildren) const
<< " children (the one under construction has " << nchildren << ")";
}
+/* Solver Configuration */
+/* -------------------------------------------------------------------------- */
+
+bool Solver::supportsFloatingPoint() const
+{
+ return Configuration::isBuiltWithSymFPU();
+}
+
/* Sorts Handling */
/* -------------------------------------------------------------------------- */
@@ -3285,9 +3293,11 @@ Sort Solver::getStringSort(void) const
CVC4_API_SOLVER_TRY_CATCH_END;
}
-Sort Solver::getRoundingmodeSort(void) const
+Sort Solver::getRoundingModeSort(void) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
+ << "Expected CVC4 to be compiled with SymFPU support";
return Sort(this, d_exprMgr->roundingModeType());
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -3323,6 +3333,8 @@ Sort Solver::mkBitVectorSort(uint32_t size) const
Sort Solver::mkFloatingPointSort(uint32_t exp, uint32_t sig) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
+ << "Expected CVC4 to be compiled with SymFPU support";
CVC4_API_ARG_CHECK_EXPECTED(exp > 0, exp) << "exponent size > 0";
CVC4_API_ARG_CHECK_EXPECTED(sig > 0, sig) << "significand size > 0";
@@ -3355,8 +3367,9 @@ std::vector<Sort> Solver::mkDatatypeSorts(
CVC4_API_SOLVER_TRY_CATCH_END;
}
-std::vector<Sort> Solver::mkDatatypeSorts(std::vector<DatatypeDecl>& dtypedecls,
- std::set<Sort>& unresolvedSorts) const
+std::vector<Sort> Solver::mkDatatypeSorts(
+ const std::vector<DatatypeDecl>& dtypedecls,
+ const std::set<Sort>& unresolvedSorts) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
return mkDatatypeSortsInternal(dtypedecls, unresolvedSorts);
@@ -3803,6 +3816,8 @@ Term Solver::mkNegZero(uint32_t exp, uint32_t sig) const
Term Solver::mkRoundingMode(RoundingMode rm) const
{
CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+ CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
+ << "Expected CVC4 to be compiled with SymFPU support";
return mkValHelper<CVC4::RoundingMode>(s_rmodes.at(rm));
CVC4_API_SOLVER_TRY_CATCH_END;
}
@@ -5396,7 +5411,7 @@ Term Solver::synthFunHelper(const std::string& symbol,
{
CVC4_API_CHECK(g->d_ntSyms[0].d_node->getType().toType() == *sort.d_type)
<< "Invalid Start symbol for Grammar g, Expected Start's sort to be "
- << *sort.d_type;
+ << *sort.d_type << " but found " << g->d_ntSyms[0].d_node->getType();
}
Type funType = varTypes.empty()
@@ -5506,7 +5521,7 @@ Term Solver::getSynthSolution(Term term) const
std::map<CVC4::Node, CVC4::Node> map;
CVC4_API_CHECK(d_smtEngine->getSynthSolutions(map))
- << "The solver is not in a state immediately preceeded by a "
+ << "The solver is not in a state immediately preceded by a "
"successful call to checkSynth";
std::map<CVC4::Node, CVC4::Node>::const_iterator it = map.find(*term.d_node);
@@ -5535,7 +5550,7 @@ std::vector<Term> Solver::getSynthSolutions(
std::map<CVC4::Node, CVC4::Node> map;
CVC4_API_CHECK(d_smtEngine->getSynthSolutions(map))
- << "The solver is not in a state immediately preceeded by a "
+ << "The solver is not in a state immediately preceded by a "
"successful call to checkSynth";
std::vector<Term> synthSolution;
diff --git a/src/api/cvc4cpp.h b/src/api/cvc4cpp.h
index 0c322d7da..acf34abf9 100644
--- a/src/api/cvc4cpp.h
+++ b/src/api/cvc4cpp.h
@@ -2153,6 +2153,12 @@ class CVC4_PUBLIC Solver
Solver& operator=(const Solver&) = delete;
/* .................................................................... */
+ /* Solver Configuration */
+ /* .................................................................... */
+
+ bool supportsFloatingPoint() const;
+
+ /* .................................................................... */
/* Sorts Handling */
/* .................................................................... */
@@ -2184,7 +2190,7 @@ class CVC4_PUBLIC Solver
/**
* @return sort RoundingMode
*/
- Sort getRoundingmodeSort() const;
+ Sort getRoundingModeSort() const;
/**
* @return sort String
@@ -2248,8 +2254,9 @@ class CVC4_PUBLIC Solver
* @param unresolvedSorts the list of unresolved sorts
* @return the datatype sorts
*/
- std::vector<Sort> mkDatatypeSorts(std::vector<DatatypeDecl>& dtypedecls,
- std::set<Sort>& unresolvedSorts) const;
+ std::vector<Sort> mkDatatypeSorts(
+ const std::vector<DatatypeDecl>& dtypedecls,
+ const std::set<Sort>& unresolvedSorts) const;
/**
* Create function sort.
@@ -3169,7 +3176,9 @@ class CVC4_PUBLIC Solver
Term mkSygusVar(Sort sort, const std::string& symbol = std::string()) const;
/**
- * Create a Sygus grammar.
+ * Create a Sygus grammar. The first non-terminal is treated as the starting
+ * non-terminal, so the order of non-terminals matters.
+ *
* @param boundVars the parameters to corresponding synth-fun/synth-inv
* @param ntSymbols the pre-declaration of the non-terminal symbols
* @return the grammar
@@ -3345,8 +3354,8 @@ class CVC4_PUBLIC Solver
* @return the datatype sorts
*/
std::vector<Sort> mkDatatypeSortsInternal(
- std::vector<DatatypeDecl>& dtypedecls,
- std::set<Sort>& unresolvedSorts) const;
+ const std::vector<DatatypeDecl>& dtypedecls,
+ const std::set<Sort>& unresolvedSorts) const;
/**
* Synthesize n-ary function following specified syntactic constraints.
diff --git a/src/api/python/cvc4.pxd b/src/api/python/cvc4.pxd
index 16d64b85e..76dcc5317 100644
--- a/src/api/python/cvc4.pxd
+++ b/src/api/python/cvc4.pxd
@@ -1,6 +1,7 @@
# import dereference and increment operators
from cython.operator cimport dereference as deref, preincrement as inc
from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t
+from libcpp.set cimport set
from libcpp.string cimport string
from libcpp.vector cimport vector
from libcpp.pair cimport pair
@@ -27,6 +28,12 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api":
Term getConstructorTerm(const string& name) except +
size_t getNumConstructors() except +
bint isParametric() except +
+ bint isCodatatype() except +
+ bint isTuple() except +
+ bint isRecord() except +
+ bint isFinite() except +
+ bint isWellFounded() except +
+ bint hasNestedRecursion() except +
string toString() except +
cppclass const_iterator:
const_iterator() except +
@@ -116,16 +123,19 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api":
cdef cppclass Solver:
Solver(Options*) except +
+ bint supportsFloatingPoint() except +
Sort getBooleanSort() except +
Sort getIntegerSort() except +
Sort getRealSort() except +
Sort getRegExpSort() except +
- Sort getRoundingmodeSort() except +
+ Sort getRoundingModeSort() except +
Sort getStringSort() except +
Sort mkArraySort(Sort indexSort, Sort elemSort) except +
Sort mkBitVectorSort(uint32_t size) except +
Sort mkFloatingPointSort(uint32_t exp, uint32_t sig) except +
Sort mkDatatypeSort(DatatypeDecl dtypedecl) except +
+ vector[Sort] mkDatatypeSorts(const vector[DatatypeDecl]& dtypedecls,
+ const set[Sort]& unresolvedSorts) except +
Sort mkFunctionSort(Sort domain, Sort codomain) except +
Sort mkFunctionSort(const vector[Sort]& sorts, Sort codomain) except +
Sort mkParamSort(const string& symbol) except +
@@ -312,6 +322,7 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api":
Term()
bint operator==(const Term&) except +
bint operator!=(const Term&) except +
+ Term operator[](size_t idx) except +
Kind getKind() except +
Sort getSort() except +
Term substitute(const vector[Term] es, const vector[Term] & reps) except +
diff --git a/src/api/python/cvc4.pxi b/src/api/python/cvc4.pxi
index a51307d21..8c4bfe5e5 100644
--- a/src/api/python/cvc4.pxi
+++ b/src/api/python/cvc4.pxi
@@ -3,6 +3,7 @@ import sys
from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t
from libcpp.pair cimport pair
+from libcpp.set cimport set
from libcpp.string cimport string
from libcpp.vector cimport vector
@@ -21,7 +22,8 @@ from cvc4 cimport Grammar as c_Grammar
from cvc4 cimport Sort as c_Sort
from cvc4 cimport SortHashFunction as c_SortHashFunction
from cvc4 cimport ROUND_NEAREST_TIES_TO_EVEN, ROUND_TOWARD_POSITIVE
-from cvc4 cimport ROUND_TOWARD_ZERO, ROUND_NEAREST_TIES_TO_AWAY
+from cvc4 cimport ROUND_TOWARD_NEGATIVE, ROUND_TOWARD_ZERO
+from cvc4 cimport ROUND_NEAREST_TIES_TO_AWAY
from cvc4 cimport Term as c_Term
from cvc4 cimport TermHashFunction as c_TermHashFunction
@@ -88,7 +90,7 @@ cdef class Datatype:
if isinstance(index, int) and index >= 0:
dc.cdc = self.cd[(<int?> index)]
elif isinstance(index, str):
- dc.cdc = self.cd[(<const string &> name.encode())]
+ dc.cdc = self.cd[(<const string &> index.encode())]
else:
raise ValueError("Expecting a non-negative integer or string")
return dc
@@ -109,6 +111,24 @@ cdef class Datatype:
def isParametric(self):
return self.cd.isParametric()
+ def isCodatatype(self):
+ return self.cd.isCodatatype()
+
+ def isTuple(self):
+ return self.cd.isTuple()
+
+ def isRecord(self):
+ return self.cd.isRecord()
+
+ def isFinite(self):
+ return self.cd.isFinite()
+
+ def isWellFounded(self):
+ return self.cd.isWellFounded()
+
+ def hasNestedRecursion(self):
+ return self.cd.hasNestedRecursion()
+
def __str__(self):
return self.cd.toString().decode()
@@ -395,6 +415,9 @@ cdef class Solver:
def __dealloc__(self):
del self.csolver
+ def supportsFloatingPoint(self):
+ return self.csolver.supportsFloatingPoint()
+
def getBooleanSort(self):
cdef Sort sort = Sort(self)
sort.csort = self.csolver.getBooleanSort()
@@ -415,9 +438,9 @@ cdef class Solver:
sort.csort = self.csolver.getRegExpSort()
return sort
- def getRoundingmodeSort(self):
+ def getRoundingModeSort(self):
cdef Sort sort = Sort(self)
- sort.csort = self.csolver.getRoundingmodeSort()
+ sort.csort = self.csolver.getRoundingModeSort()
return sort
def getStringSort(self):
@@ -445,6 +468,26 @@ cdef class Solver:
sort.csort = self.csolver.mkDatatypeSort(dtypedecl.cdd)
return sort
+ def mkDatatypeSorts(self, list dtypedecls, unresolvedSorts):
+ sorts = []
+
+ cdef vector[c_DatatypeDecl] decls
+ for decl in dtypedecls:
+ decls.push_back((<DatatypeDecl?> decl).cdd)
+
+ cdef set[c_Sort] usorts
+ for usort in unresolvedSorts:
+ usorts.insert((<Sort?> usort).csort)
+
+ csorts = self.csolver.mkDatatypeSorts(
+ <const vector[c_DatatypeDecl]&> decls, <const set[c_Sort]&> usorts)
+ for csort in csorts:
+ sort = Sort(self)
+ sort.csort = csort
+ sorts.append(sort)
+
+ return sorts
+
def mkFunctionSort(self, sorts, Sort codomain):
cdef Sort sort = Sort(self)
@@ -1350,6 +1393,14 @@ cdef class Term:
def __ne__(self, Term other):
return self.cterm != other.cterm
+ def __getitem__(self, int index):
+ cdef Term term = Term(self.solver)
+ if index >= 0:
+ term.cterm = self.cterm[index]
+ else:
+ raise ValueError("Expecting a non-negative integer or string")
+ return term
+
def __str__(self):
return self.cterm.toString().decode()
@@ -1457,6 +1508,7 @@ cdef class Term:
cdef __rounding_modes = {
<int> ROUND_NEAREST_TIES_TO_EVEN: "RoundNearestTiesToEven",
<int> ROUND_TOWARD_POSITIVE: "RoundTowardPositive",
+ <int> ROUND_TOWARD_NEGATIVE: "RoundTowardNegative",
<int> ROUND_TOWARD_ZERO: "RoundTowardZero",
<int> ROUND_NEAREST_TIES_TO_AWAY: "RoundNearestTiesToAway"
}
diff --git a/src/expr/CMakeLists.txt b/src/expr/CMakeLists.txt
index 8bc732314..aed7a866c 100644
--- a/src/expr/CMakeLists.txt
+++ b/src/expr/CMakeLists.txt
@@ -63,6 +63,10 @@ libcvc4_add_sources(
term_canonize.h
term_context.cpp
term_context.h
+ term_context_node.cpp
+ term_context_node.h
+ term_context_stack.cpp
+ term_context_stack.h
term_conversion_proof_generator.cpp
term_conversion_proof_generator.h
type.cpp
diff --git a/src/expr/expr_manager_template.cpp b/src/expr/expr_manager_template.cpp
index 0d22a3c41..bac9e3b43 100644
--- a/src/expr/expr_manager_template.cpp
+++ b/src/expr/expr_manager_template.cpp
@@ -26,12 +26,6 @@
${includes}
-// This is a hack, but an important one: if there's an error, the
-// compiler directs the user to the template file instead of the
-// generated one. We don't want the user to modify the generated one,
-// since it'll get overwritten on a later build.
-#line 34 "${template}"
-
#ifdef CVC4_STATISTICS_ON
#define INC_STAT(kind) \
{ \
diff --git a/src/expr/expr_manager_template.h b/src/expr/expr_manager_template.h
index a6fce56a2..145f64bd3 100644
--- a/src/expr/expr_manager_template.h
+++ b/src/expr/expr_manager_template.h
@@ -28,12 +28,6 @@
${includes}
-// This is a hack, but an important one: if there's an error, the
-// compiler directs the user to the template file instead of the
-// generated one. We don't want the user to modify the generated one,
-// since it'll get overwritten on a later build.
-#line 36 "${template}"
-
namespace CVC4 {
namespace api {
diff --git a/src/expr/expr_template.cpp b/src/expr/expr_template.cpp
index 226736e8f..a92081fe8 100644
--- a/src/expr/expr_template.cpp
+++ b/src/expr/expr_template.cpp
@@ -29,12 +29,6 @@
${includes}
-// This is a hack, but an important one: if there's an error, the
-// compiler directs the user to the template file instead of the
-// generated one. We don't want the user to modify the generated one,
-// since it'll get overwritten on a later build.
-#line 37 "${template}"
-
using namespace CVC4::kind;
using namespace std;
diff --git a/src/expr/expr_template.h b/src/expr/expr_template.h
index 34374d354..0acce2cb0 100644
--- a/src/expr/expr_template.h
+++ b/src/expr/expr_template.h
@@ -39,12 +39,6 @@ ${includes}
#include "options/language.h"
#include "util/hash.h"
-// This is a hack, but an important one: if there's an error, the
-// compiler directs the user to the template file instead of the
-// generated one. We don't want the user to modify the generated one,
-// since it'll get overwritten on a later build.
-#line 47 "${template}"
-
namespace CVC4 {
// The internal expression representation
@@ -621,8 +615,6 @@ private:
${getConst_instantiations}
-#line 625 "${template}"
-
inline size_t ExprHashFunction::operator()(CVC4::Expr e) const {
return (size_t) e.getId();
}
diff --git a/src/expr/kind_template.cpp b/src/expr/kind_template.cpp
index 0d7f5f4e4..b2e165558 100644
--- a/src/expr/kind_template.cpp
+++ b/src/expr/kind_template.cpp
@@ -69,7 +69,6 @@ std::string kindToString(::CVC4::Kind k) {
std::ostream& operator<<(std::ostream& out, TypeConstant typeConstant) {
switch(typeConstant) {
${type_constant_descriptions}
-#line 73 "${template}"
default:
out << "UNKNOWN_TYPE_CONSTANT";
break;
@@ -85,7 +84,6 @@ TheoryId kindToTheoryId(::CVC4::Kind k) {
case kind::NULL_EXPR:
break;
${kind_to_theory_id}
-#line 89 "${template}"
case kind::LAST_KIND:
break;
}
@@ -97,7 +95,6 @@ TheoryId typeConstantToTheoryId(::CVC4::TypeConstant typeConstant)
switch (typeConstant)
{
${type_constant_to_theory_id}
-#line 101 "${template}"
case LAST_TYPE: break;
}
throw IllegalArgumentException(
diff --git a/src/expr/kind_template.h b/src/expr/kind_template.h
index d34179252..8ae7018b3 100644
--- a/src/expr/kind_template.h
+++ b/src/expr/kind_template.h
@@ -63,8 +63,6 @@ const char* toString(CVC4::Kind k);
*/
std::ostream& operator<<(std::ostream&, CVC4::Kind) CVC4_PUBLIC;
-#line 67 "${template}"
-
/** Returns true if the given kind is associative. This is used by ExprManager to
* decide whether it's safe to modify big expressions by changing the grouping of
* the arguments. */
@@ -86,7 +84,6 @@ struct KindHashFunction {
enum CVC4_PUBLIC TypeConstant
{
${type_constant_list}
-#line 90 "${template}"
LAST_TYPE
}; /* enum TypeConstant */
diff --git a/src/expr/metakind_template.h b/src/expr/metakind_template.h
index 5fa10c90a..e1668836b 100644
--- a/src/expr/metakind_template.h
+++ b/src/expr/metakind_template.h
@@ -201,8 +201,6 @@ Kind operatorToKind(::CVC4::expr::NodeValue* nv);
}/* CVC4::kind namespace */
-#line 205 "${template}"
-
}/* CVC4 namespace */
#endif /* CVC4__NODE_MANAGER_NEEDS_CONSTANT_MAP */
diff --git a/src/expr/mkexpr b/src/expr/mkexpr
index c5f12f487..58531cba4 100755
--- a/src/expr/mkexpr
+++ b/src/expr/mkexpr
@@ -150,9 +150,7 @@ function typerule {
lineno=${BASH_LINENO[0]}
check_theory_seen
typerules="${typerules}
-#line $lineno \"$kf\"
case kind::$1:
-#line $lineno \"$kf\"
typeNode = $2::computeType(nodeManager, n, check);
break;
"
@@ -163,9 +161,7 @@ function construle {
lineno=${BASH_LINENO[0]}
check_theory_seen
construles="${construles}
-#line $lineno \"$kf\"
case kind::$1:
-#line $lineno \"$kf\"
return $2::computeIsConst(nodeManager, n);
"
}
@@ -218,26 +214,19 @@ function constant {
fi
mkConst_instantiations="${mkConst_instantiations}
-#line $lineno \"$kf\"
template <> Expr ExprManager::mkConst($2 const& val);
"
mkConst_implementations="${mkConst_implementations}
-#line $lineno \"$kf\"
template <> Expr ExprManager::mkConst($2 const& val) {
-#line $lineno \"$kf\"
return Expr(this, new Node(d_nodeManager->mkConst< $2 >(val)));
}
"
getConst_instantiations="${getConst_instantiations}
-#line $lineno \"$kf\"
template <> $2 const & Expr::getConst< $2 >() const;
"
getConst_implementations="${getConst_implementations}
-#line $lineno \"$kf\"
template <> $2 const & Expr::getConst() const {
-#line $lineno \"$kf\"
PrettyCheckArgument(getKind() == ::CVC4::kind::$1, *this, \"Improper kind for getConst<$2>()\");
-#line $lineno \"$kf\"
return d_node->getConst< $2 >();
}
"
@@ -288,10 +277,6 @@ check_builtin_theory_seen
## output
-# generate warnings about incorrect #line annotations in templates
-nl -ba -s' ' "$template" | grep '^ *[0-9][0-9]* # *line' |
- awk '{OFS="";if($1+1!=$3) print "'"$template"':",$1,": warning: incorrect annotation \"#line ",$3,"\" (it should be \"#line ",($1+1),"\")"}' >&2
-
text=$(cat "$template")
for var in \
includes \
diff --git a/src/expr/mkkind b/src/expr/mkkind
index fbf37eff4..55276549a 100755
--- a/src/expr/mkkind
+++ b/src/expr/mkkind
@@ -257,23 +257,23 @@ function register_sort {
"
type_constant_to_theory_id="${type_constant_to_theory_id} case $id: return $theory_id;
"
- type_constant_cardinalities="${type_constant_cardinalities}#line $lineno \"$kf\"
+ type_constant_cardinalities="${type_constant_cardinalities}
case $id: return Cardinality($cardinality);
"
- type_constant_wellfoundednesses="${type_constant_wellfoundednesses}#line $lineno \"$kf\"
+ type_constant_wellfoundednesses="${type_constant_wellfoundednesses}
case $id: return $wellfoundedness;
"
if [ -n "$groundterm" ]; then
- type_constant_groundterms="${type_constant_groundterms}#line $lineno \"$kf\"
+ type_constant_groundterms="${type_constant_groundterms}
case $id: return $groundterm;
"
if [ -n "$header" ]; then
- type_properties_includes="${type_properties_includes}#line $lineno \"$kf\"
+ type_properties_includes="${type_properties_includes}
#include \"$header\"
"
fi
else
- type_constant_groundterms="${type_constant_groundterms}#line $lineno \"$kf\"
+ type_constant_groundterms="${type_constant_groundterms}
case $id: Unhandled() << tc;
"
fi
@@ -284,11 +284,11 @@ function register_cardinality {
cardinality_computer=$(sed 's,%TYPE%,typeNode,g' <<<"$2")
header=$3
- type_cardinalities="${type_cardinalities}#line $lineno \"$kf\"
+ type_cardinalities="${type_cardinalities}
case $id: return $cardinality_computer;
"
if [ -n "$header" ]; then
- type_properties_includes="${type_properties_includes}#line $lineno \"$kf\"
+ type_properties_includes="${type_properties_includes}
#include \"$header\"
"
fi
@@ -314,20 +314,20 @@ function register_wellfoundedness {
fi
fi
- type_wellfoundednesses="${type_wellfoundednesses}#line $lineno \"$kf\"
+ type_wellfoundednesses="${type_wellfoundednesses}
case $id: return $wellfoundedness_computer;
"
if [ -n "$groundterm_computer" ]; then
- type_groundterms="${type_groundterms}#line $lineno \"$kf\"
+ type_groundterms="${type_groundterms}
case $id: return $groundterm_computer;
"
else
- type_groundterms="${type_groundterms}#line $lineno \"$kf\"
+ type_groundterms="${type_groundterms}
case $id: Unhandled() << typeNode;
"
fi
if [ -n "$header" ]; then
- type_properties_includes="${type_properties_includes}#line $lineno \"$kf\"
+ type_properties_includes="${type_properties_includes}
#include \"$header\"
"
fi
@@ -390,10 +390,6 @@ check_builtin_theory_seen
## output
-# generate warnings about incorrect #line annotations in templates
-nl -ba -s' ' "$template" | grep '^ *[0-9][0-9]* # *line' |
- awk '{OFS="";if($1+1!=$3) print "'"$template"':",$1,": warning: incorrect annotation \"#line ",$3,"\" (it should be \"#line ",($1+1),"\")"}' >&2
-
text=$(cat "$template")
for var in \
kind_decls \
diff --git a/src/expr/mkmetakind b/src/expr/mkmetakind
index e2a733ec8..9d2f0a475 100755
--- a/src/expr/mkmetakind
+++ b/src/expr/mkmetakind
@@ -270,19 +270,16 @@ $2 const& NodeValue::getConst< $2 >() const {
"
metakind_constHashes="${metakind_constHashes}
case kind::$1:
-#line $lineno \"$kf\"
return $3()(nv->getConst< $2 >());
"
metakind_constPrinters="${metakind_constPrinters}
case kind::$1:
-#line $lineno \"$kf\"
out << nv->getConst< $2 >();
break;
"
cname=`echo "$2" | awk 'BEGIN {FS="::"} {print$NF}'`
metakind_constDeleters="${metakind_constDeleters}
case kind::$1:
-#line $lineno \"$kf\"
std::allocator< $2 >().destroy(reinterpret_cast< $2* >(nv->d_children));
break;
"
@@ -301,7 +298,6 @@ function registerOperatorToKind {
operatorKind=$1
applyKind=$2
metakind_operatorKinds="${metakind_operatorKinds}
-#line $lineno \"$kf\"
case kind::$applyKind: return kind::$operatorKind;";
}
@@ -396,10 +392,6 @@ check_builtin_theory_seen
## output
-# generate warnings about incorrect #line annotations in templates
-nl -ba -s' ' "$template" | grep '^ *[0-9][0-9]* # *line' |
- awk '{OFS="";if($1+1!=$3) print "'"$template"':",$1,": warning: incorrect annotation \"#line ",$3,"\" (it should be \"#line ",($1+1),"\")"}' >&2
-
text=$(cat "$template")
for var in \
metakind_includes \
diff --git a/src/expr/proof_rule.cpp b/src/expr/proof_rule.cpp
index 0a45c6790..1d46b183f 100644
--- a/src/expr/proof_rule.cpp
+++ b/src/expr/proof_rule.cpp
@@ -27,13 +27,15 @@ const char* toString(PfRule id)
case PfRule::SCOPE: return "SCOPE";
case PfRule::SUBS: return "SUBS";
case PfRule::REWRITE: return "REWRITE";
+ case PfRule::EVALUATE: return "EVALUATE";
case PfRule::MACRO_SR_EQ_INTRO: return "MACRO_SR_EQ_INTRO";
case PfRule::MACRO_SR_PRED_INTRO: return "MACRO_SR_PRED_INTRO";
case PfRule::MACRO_SR_PRED_ELIM: return "MACRO_SR_PRED_ELIM";
case PfRule::MACRO_SR_PRED_TRANSFORM: return "MACRO_SR_PRED_TRANSFORM";
- case PfRule::THEORY_REWRITE: return "THEORY_REWRITE";
case PfRule::REMOVE_TERM_FORMULA_AXIOM: return "REMOVE_TERM_FORMULA_AXIOM";
//================================================= Trusted rules
+ case PfRule::THEORY_LEMMA: return "THEORY_LEMMA";
+ case PfRule::THEORY_REWRITE: return "THEORY_REWRITE";
case PfRule::PREPROCESS: return "PREPROCESS";
case PfRule::PREPROCESS_LEMMA: return "PREPROCESS_LEMMA";
case PfRule::THEORY_PREPROCESS: return "THEORY_PREPROCESS";
@@ -94,6 +96,8 @@ const char* toString(PfRule id)
case PfRule::TRUE_ELIM: return "TRUE_ELIM";
case PfRule::FALSE_INTRO: return "FALSE_INTRO";
case PfRule::FALSE_ELIM: return "FALSE_ELIM";
+ case PfRule::HO_APP_ENCODE: return "HO_APP_ENCODE";
+ case PfRule::HO_CONG: return "HO_CONG";
//================================================= Quantifiers rules
case PfRule::WITNESS_INTRO: return "WITNESS_INTRO";
case PfRule::EXISTS_INTRO: return "EXISTS_INTRO";
diff --git a/src/expr/proof_rule.h b/src/expr/proof_rule.h
index 59c406d28..825503d5d 100644
--- a/src/expr/proof_rule.h
+++ b/src/expr/proof_rule.h
@@ -91,6 +91,14 @@ enum class PfRule : uint32_t
// where idr is a MethodId identifier, which determines the kind of rewriter
// to apply, e.g. Rewriter::rewrite.
REWRITE,
+ // ======== Evaluate
+ // Children: none
+ // Arguments: (t)
+ // ----------------------------------------
+ // Conclusion: (= t Evaluator::evaluate(t))
+ // Note this is equivalent to:
+ // (REWRITE t MethodId::RW_EVALUATE)
+ EVALUATE,
// ======== Substitution + Rewriting equality introduction
//
// In this rule, we provide a term t and conclude that it is equal to its
@@ -163,15 +171,6 @@ enum class PfRule : uint32_t
// Notice that we apply rewriting on the witness form of F and G, similar to
// MACRO_SR_PRED_INTRO.
MACRO_SR_PRED_TRANSFORM,
- // ======== Theory Rewrite
- // Children: none
- // Arguments: (t, preRewrite?)
- // ----------------------------------------
- // Conclusion: (= t t')
- // where
- // t' is the result of applying either a pre-rewrite or a post-rewrite step
- // to t (depending on the second argument).
- THEORY_REWRITE,
//================================================= Processing rules
// ======== Remove Term Formulas Axiom
@@ -182,6 +181,28 @@ enum class PfRule : uint32_t
REMOVE_TERM_FORMULA_AXIOM,
//================================================= Trusted rules
+ // ======== Theory lemma
+ // Children: none
+ // Arguments: (F, tid)
+ // ---------------------------------------------------------------
+ // Conclusion: F
+ // where F is a (T-valid) theory lemma generated by theory with TheoryId tid.
+ // This is a "coarse-grained" rule that is used as a placeholder if a theory
+ // did not provide a proof for a lemma or conflict.
+ THEORY_LEMMA,
+ // ======== Theory Rewrite
+ // Children: none
+ // Arguments: (F, tid, preRewrite?)
+ // ----------------------------------------
+ // Conclusion: F
+ // where F is an equality of the form (= t t') where t' is obtained by
+ // applying the theory rewriter with identifier tid in either its prewrite
+ // (when preRewrite is true) or postrewrite method. Notice that the checker
+ // for this rule does not replay the rewrite to ensure correctness, since
+ // theory rewriter methods are not static. For example, the quantifiers
+ // rewriter involves constructing new bound variables that are not guaranteed
+ // to be consistent on each call.
+ THEORY_REWRITE,
// The rules in this section have the signature of a "trusted rule":
//
// Children: none
@@ -520,6 +541,20 @@ enum class PfRule : uint32_t
// ----------------------------------------
// Conclusion: (not F)
FALSE_ELIM,
+ // ======== HO trust
+ // Children: none
+ // Arguments: (t)
+ // ---------------------
+ // Conclusion: (= t TheoryUfRewriter::getHoApplyForApplyUf(t))
+ // For example, this rule concludes (f x y) = (HO_APPLY (HO_APPLY f x) y)
+ HO_APP_ENCODE,
+ // ======== Congruence
+ // Children: (P1:(= f g), P2:(= t1 s1), ..., Pn+1:(= tn sn))
+ // Arguments: ()
+ // ---------------------------------------------
+ // Conclusion: (= (f t1 ... tn) (g s1 ... sn))
+ // Notice that this rule is only used when the application kinds are APPLY_UF.
+ HO_CONG,
//================================================= Quantifiers rules
// ======== Witness intro
diff --git a/src/expr/term_conversion_proof_generator.cpp b/src/expr/term_conversion_proof_generator.cpp
index 1c4baeed7..8cd7561b4 100644
--- a/src/expr/term_conversion_proof_generator.cpp
+++ b/src/expr/term_conversion_proof_generator.cpp
@@ -14,6 +14,8 @@
#include "expr/term_conversion_proof_generator.h"
+#include "expr/term_context_stack.h"
+
using namespace CVC4::kind;
namespace CVC4 {
@@ -45,31 +47,38 @@ TConvProofGenerator::TConvProofGenerator(ProofNodeManager* pnm,
context::Context* c,
TConvPolicy pol,
TConvCachePolicy cpol,
- std::string name)
+ std::string name,
+ TermContext* tccb)
: d_proof(pnm, nullptr, c, name + "::LazyCDProof"),
d_rewriteMap(c ? c : &d_context),
d_policy(pol),
d_cpolicy(cpol),
- d_name(name)
+ d_name(name),
+ d_tcontext(tccb)
{
}
TConvProofGenerator::~TConvProofGenerator() {}
-void TConvProofGenerator::addRewriteStep(Node t, Node s, ProofGenerator* pg)
+void TConvProofGenerator::addRewriteStep(
+ Node t, Node s, ProofGenerator* pg, bool isClosed, uint32_t tctx)
{
- Node eq = registerRewriteStep(t, s);
+ Node eq = registerRewriteStep(t, s, tctx);
if (!eq.isNull())
{
- d_proof.addLazyStep(eq, pg);
+ d_proof.addLazyStep(eq, pg, isClosed);
}
}
-void TConvProofGenerator::addRewriteStep(Node t, Node s, ProofStep ps)
+void TConvProofGenerator::addRewriteStep(Node t,
+ Node s,
+ ProofStep ps,
+ uint32_t tctx)
{
- Node eq = registerRewriteStep(t, s);
+ Node eq = registerRewriteStep(t, s, tctx);
if (!eq.isNull())
{
+ AlwaysAssert(ps.d_rule != PfRule::ASSUME);
d_proof.addStep(eq, ps);
}
}
@@ -78,33 +87,55 @@ void TConvProofGenerator::addRewriteStep(Node t,
Node s,
PfRule id,
const std::vector<Node>& children,
- const std::vector<Node>& args)
+ const std::vector<Node>& args,
+ uint32_t tctx)
{
- Node eq = registerRewriteStep(t, s);
+ Node eq = registerRewriteStep(t, s, tctx);
if (!eq.isNull())
{
+ AlwaysAssert(id != PfRule::ASSUME);
d_proof.addStep(eq, id, children, args);
}
}
-bool TConvProofGenerator::hasRewriteStep(Node t) const
+bool TConvProofGenerator::hasRewriteStep(Node t, uint32_t tctx) const
{
- return !getRewriteStep(t).isNull();
+ return !getRewriteStep(t, tctx).isNull();
}
-Node TConvProofGenerator::registerRewriteStep(Node t, Node s)
+Node TConvProofGenerator::getRewriteStep(Node t, uint32_t tctx) const
+{
+ Node thash = t;
+ if (d_tcontext != nullptr)
+ {
+ thash = TCtxNode::computeNodeHash(t, tctx);
+ }
+ return getRewriteStepInternal(thash);
+}
+
+Node TConvProofGenerator::registerRewriteStep(Node t, Node s, uint32_t tctx)
{
if (t == s)
{
return Node::null();
}
+ Node thash = t;
+ if (d_tcontext != nullptr)
+ {
+ thash = TCtxNode::computeNodeHash(t, tctx);
+ }
+ else
+ {
+ // don't use term context ids if not using term context
+ Assert(tctx == 0);
+ }
// should not rewrite term to two different things
- if (!getRewriteStep(t).isNull())
+ if (!getRewriteStepInternal(thash).isNull())
{
- Assert(getRewriteStep(t) == s);
+ Assert(getRewriteStepInternal(thash) == s);
return Node::null();
}
- d_rewriteMap[t] = s;
+ d_rewriteMap[thash] = s;
if (d_cpolicy == TConvCachePolicy::DYNAMIC)
{
// clear the cache
@@ -115,66 +146,140 @@ Node TConvProofGenerator::registerRewriteStep(Node t, Node s)
std::shared_ptr<ProofNode> TConvProofGenerator::getProofFor(Node f)
{
- Trace("tconv-pf-gen") << "TConvProofGenerator::getProofFor: " << f
- << std::endl;
+ Trace("tconv-pf-gen") << "TConvProofGenerator::getProofFor: " << identify()
+ << ": " << f << std::endl;
if (f.getKind() != EQUAL)
{
- Trace("tconv-pf-gen") << "... fail, non-equality" << std::endl;
- Assert(false);
+ std::stringstream serr;
+ serr << "TConvProofGenerator::getProofFor: " << identify()
+ << ": fail, non-equality " << f;
+ Unhandled() << serr.str();
+ Trace("tconv-pf-gen") << serr.str() << std::endl;
return nullptr;
}
// we use the existing proofs
LazyCDProof lpf(
d_proof.getManager(), &d_proof, nullptr, d_name + "::LazyCDProof");
- Node conc = getProofForRewriting(f[0], lpf);
- if (conc != f)
+ if (f[0] == f[1])
{
- Trace("tconv-pf-gen") << "...failed, mismatch: returned proof concludes "
- << conc << ", expected " << f << std::endl;
- Assert(false);
- return nullptr;
+ // assertion failure in debug
+ Assert(false) << "TConvProofGenerator::getProofFor: " << identify()
+ << ": don't ask for trivial proofs";
+ lpf.addStep(f, PfRule::REFL, {}, {f[0]});
+ }
+ else
+ {
+ Node conc = getProofForRewriting(f[0], lpf, d_tcontext);
+ if (conc != f)
+ {
+ Assert(conc.getKind() == EQUAL && conc[0] == f[0]);
+ std::stringstream serr;
+ serr << "TConvProofGenerator::getProofFor: " << toStringDebug()
+ << ": failed, mismatch (see -t tconv-pf-gen-debug for details)"
+ << std::endl;
+ serr << " source: " << f[0] << std::endl;
+ serr << "expected after rewriting: " << f[1] << std::endl;
+ serr << " actual after rewriting: " << conc[1] << std::endl;
+
+ if (Trace.isOn("tconv-pf-gen-debug"))
+ {
+ Trace("tconv-pf-gen-debug") << "Printing rewrite steps..." << std::endl;
+ serr << "Rewrite steps: " << std::endl;
+ for (NodeNodeMap::const_iterator it = d_rewriteMap.begin();
+ it != d_rewriteMap.end();
+ ++it)
+ {
+ serr << (*it).first << " -> " << (*it).second << std::endl;
+ }
+ }
+ Unhandled() << serr.str();
+ return nullptr;
+ }
}
Trace("tconv-pf-gen") << "... success" << std::endl;
return lpf.getProofFor(f);
}
-Node TConvProofGenerator::getProofForRewriting(Node t, LazyCDProof& pf)
+Node TConvProofGenerator::getProofForRewriting(Node t,
+ LazyCDProof& pf,
+ TermContext* tctx)
{
NodeManager* nm = NodeManager::currentNM();
- // Invariant: if visited[t] = s or rewritten[t] = s and t,s are distinct,
- // then pf is able to generate a proof of t=s.
+ // Invariant: if visited[hash(t)] = s or rewritten[hash(t)] = s and t,s are
+ // distinct, then pf is able to generate a proof of t=s. We must
+ // Node in the domains of the maps below due to hashing creating new (SEXPR)
+ // nodes.
+
// the final rewritten form of terms
- std::unordered_map<TNode, Node, TNodeHashFunction> visited;
+ std::unordered_map<Node, Node, TNodeHashFunction> visited;
// the rewritten form of terms we have processed so far
- std::unordered_map<TNode, Node, TNodeHashFunction> rewritten;
- std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it;
- std::unordered_map<TNode, Node, TNodeHashFunction>::iterator itr;
+ std::unordered_map<Node, Node, TNodeHashFunction> rewritten;
+ std::unordered_map<Node, Node, TNodeHashFunction>::iterator it;
+ std::unordered_map<Node, Node, TNodeHashFunction>::iterator itr;
std::map<Node, std::shared_ptr<ProofNode> >::iterator itc;
+ Trace("tconv-pf-gen-rewrite")
+ << "TConvProofGenerator::getProofForRewriting: " << toStringDebug()
+ << std::endl;
+ Trace("tconv-pf-gen-rewrite") << "Input: " << t << std::endl;
+ // if provided, we use term context for cache
+ std::shared_ptr<TCtxStack> visitctx;
+ // otherwise, visit is used if we don't have a term context
std::vector<TNode> visit;
- TNode cur;
- visit.push_back(t);
+ Node tinitialHash;
+ if (tctx != nullptr)
+ {
+ visitctx = std::make_shared<TCtxStack>(tctx);
+ visitctx->pushInitial(t);
+ tinitialHash = TCtxNode::computeNodeHash(t, tctx->initialValue());
+ }
+ else
+ {
+ visit.push_back(t);
+ tinitialHash = t;
+ }
+ Node cur;
+ uint32_t curCVal = 0;
+ Node curHash;
do
{
- cur = visit.back();
- visit.pop_back();
+ // pop the top element
+ if (tctx != nullptr)
+ {
+ std::pair<Node, uint32_t> curPair = visitctx->getCurrent();
+ cur = curPair.first;
+ curCVal = curPair.second;
+ curHash = TCtxNode::computeNodeHash(cur, curCVal);
+ visitctx->pop();
+ }
+ else
+ {
+ cur = visit.back();
+ curHash = cur;
+ visit.pop_back();
+ }
+ Trace("tconv-pf-gen-rewrite") << "* visit : " << curHash << std::endl;
// has the proof for cur been cached?
- itc = d_cache.find(cur);
+ itc = d_cache.find(curHash);
if (itc != d_cache.end())
{
Node res = itc->second->getResult();
Assert(res.getKind() == EQUAL);
- visited[cur] = res[1];
+ Assert(!res[1].isNull());
+ visited[curHash] = res[1];
pf.addProof(itc->second);
continue;
}
- it = visited.find(cur);
+ it = visited.find(curHash);
if (it == visited.end())
{
- visited[cur] = Node::null();
+ Trace("tconv-pf-gen-rewrite") << "- previsit" << std::endl;
+ visited[curHash] = Node::null();
// did we rewrite the current node (possibly at pre-rewrite)?
- Node rcur = getRewriteStep(cur);
+ Node rcur = getRewriteStepInternal(curHash);
if (!rcur.isNull())
{
+ Trace("tconv-pf-gen-rewrite")
+ << "*** " << curHash << " prerewrites to " << rcur << std::endl;
// d_proof has a proof of cur = rcur. Hence there is nothing
// to do here, as pf will reference d_proof to get its proof.
if (d_policy == TConvPolicy::FIXPOINT)
@@ -182,18 +287,34 @@ Node TConvProofGenerator::getProofForRewriting(Node t, LazyCDProof& pf)
// It may be the case that rcur also rewrites, thus we cannot assign
// the final rewritten form for cur yet. Instead we revisit cur after
// finishing visiting rcur.
- rewritten[cur] = rcur;
- visit.push_back(cur);
- visit.push_back(rcur);
+ rewritten[curHash] = rcur;
+ if (tctx != nullptr)
+ {
+ visitctx->push(cur, curCVal);
+ visitctx->push(rcur, curCVal);
+ }
+ else
+ {
+ visit.push_back(cur);
+ visit.push_back(rcur);
+ }
}
else
{
Assert(d_policy == TConvPolicy::ONCE);
+ Trace("tconv-pf-gen-rewrite") << "-> (once, prewrite) " << curHash
+ << " = " << rcur << std::endl;
// not rewriting again, rcur is final
- visited[cur] = rcur;
- doCache(cur, rcur, pf);
+ Assert(!rcur.isNull());
+ visited[curHash] = rcur;
+ doCache(curHash, cur, rcur, pf);
}
}
+ else if (tctx != nullptr)
+ {
+ visitctx->push(cur, curCVal);
+ visitctx->pushChildren(cur, curCVal);
+ }
else
{
visit.push_back(cur);
@@ -202,7 +323,7 @@ Node TConvProofGenerator::getProofForRewriting(Node t, LazyCDProof& pf)
}
else if (it->second.isNull())
{
- itr = rewritten.find(cur);
+ itr = rewritten.find(curHash);
if (itr != rewritten.end())
{
// only can generate partially rewritten nodes when rewrite again is
@@ -211,9 +332,17 @@ Node TConvProofGenerator::getProofForRewriting(Node t, LazyCDProof& pf)
// if it was rewritten, check the status of the rewritten node,
// which should be finished now
Node rcur = itr->second;
+ Trace("tconv-pf-gen-rewrite")
+ << "- postvisit, previously rewritten to " << rcur << std::endl;
+ Node rcurHash = rcur;
+ if (tctx != nullptr)
+ {
+ rcurHash = TCtxNode::computeNodeHash(rcur, curCVal);
+ }
Assert(cur != rcur);
// the final rewritten form of cur is the final form of rcur
- Node rcurFinal = visited[rcur];
+ Node rcurFinal = visited[rcurHash];
+ Assert(!rcurFinal.isNull());
if (rcurFinal != rcur)
{
// must connect via TRANS
@@ -223,30 +352,54 @@ Node TConvProofGenerator::getProofForRewriting(Node t, LazyCDProof& pf)
Node result = cur.eqNode(rcurFinal);
pf.addStep(result, PfRule::TRANS, pfChildren, {});
}
- visited[cur] = rcurFinal;
- doCache(cur, rcurFinal, pf);
+ Trace("tconv-pf-gen-rewrite")
+ << "-> (rewritten postrewrite) " << curHash << " = " << rcurFinal
+ << std::endl;
+ visited[curHash] = rcurFinal;
+ doCache(curHash, cur, rcurFinal, pf);
}
else
{
+ Trace("tconv-pf-gen-rewrite") << "- postvisit" << std::endl;
Node ret = cur;
+ Node retHash = curHash;
bool childChanged = false;
std::vector<Node> children;
if (cur.getMetaKind() == metakind::PARAMETERIZED)
{
children.push_back(cur.getOperator());
}
- for (const Node& cn : cur)
+ // get the results of the children
+ if (tctx != nullptr)
+ {
+ for (size_t i = 0, nchild = cur.getNumChildren(); i < nchild; i++)
+ {
+ Node cn = cur[i];
+ uint32_t cnval = tctx->computeValue(cur, curCVal, i);
+ Node cnHash = TCtxNode::computeNodeHash(cn, cnval);
+ it = visited.find(cnHash);
+ Assert(it != visited.end());
+ Assert(!it->second.isNull());
+ childChanged = childChanged || cn != it->second;
+ children.push_back(it->second);
+ }
+ }
+ else
{
- it = visited.find(cn);
- Assert(it != visited.end());
- Assert(!it->second.isNull());
- childChanged = childChanged || cn != it->second;
- children.push_back(it->second);
+ // can use simple loop if not term-context-sensitive
+ for (const Node& cn : cur)
+ {
+ it = visited.find(cn);
+ Assert(it != visited.end());
+ Assert(!it->second.isNull());
+ childChanged = childChanged || cn != it->second;
+ children.push_back(it->second);
+ }
}
if (childChanged)
{
ret = nm->mkNode(cur.getKind(), children);
- rewritten[cur] = ret;
+ rewritten[curHash] = ret;
// congruence to show (cur = ret)
std::vector<Node> pfChildren;
for (size_t i = 0, size = cur.getNumChildren(); i < size; i++)
@@ -260,62 +413,96 @@ Node TConvProofGenerator::getProofForRewriting(Node t, LazyCDProof& pf)
}
std::vector<Node> pfArgs;
Kind k = cur.getKind();
+ pfArgs.push_back(ProofRuleChecker::mkKindNode(k));
if (kind::metaKindOf(k) == kind::metakind::PARAMETERIZED)
{
pfArgs.push_back(cur.getOperator());
}
- else
- {
- pfArgs.push_back(nm->operatorOf(k));
- }
Node result = cur.eqNode(ret);
pf.addStep(result, PfRule::CONG, pfChildren, pfArgs);
+ // must update the hash
+ retHash = ret;
+ if (tctx != nullptr)
+ {
+ retHash = TCtxNode::computeNodeHash(ret, curCVal);
+ }
+ }
+ else if (tctx != nullptr)
+ {
+ // now we need the hash
+ retHash = TCtxNode::computeNodeHash(cur, curCVal);
}
// did we rewrite ret (at post-rewrite)?
Node rret;
// only if not ONCE policy, which only does pre-rewrite
if (d_policy != TConvPolicy::ONCE)
{
- rret = getRewriteStep(ret);
+ rret = getRewriteStepInternal(retHash);
}
if (!rret.isNull())
{
- if (cur != ret)
- {
- visit.push_back(cur);
- }
+ Trace("tconv-pf-gen-rewrite")
+ << "*** " << retHash << " postrewrites to " << rret << std::endl;
// d_proof should have a proof of ret = rret, hence nothing to do
// here, for the same reasons as above. It also may be the case that
// rret rewrites, hence we must revisit ret.
- rewritten[ret] = rret;
- visit.push_back(ret);
- visit.push_back(rret);
+ rewritten[retHash] = rret;
+ if (tctx != nullptr)
+ {
+ if (cur != ret)
+ {
+ visitctx->push(cur, curCVal);
+ }
+ visitctx->push(ret, curCVal);
+ visitctx->push(rret, curCVal);
+ }
+ else
+ {
+ if (cur != ret)
+ {
+ visit.push_back(cur);
+ }
+ visit.push_back(ret);
+ visit.push_back(rret);
+ }
}
else
{
+ Trace("tconv-pf-gen-rewrite")
+ << "-> (postrewrite) " << curHash << " = " << ret << std::endl;
// it is final
- visited[cur] = ret;
- doCache(cur, ret, pf);
+ Assert(!ret.isNull());
+ visited[curHash] = ret;
+ doCache(curHash, cur, ret, pf);
}
}
}
- } while (!visit.empty());
- Assert(visited.find(t) != visited.end());
- Assert(!visited.find(t)->second.isNull());
+ else
+ {
+ Trace("tconv-pf-gen-rewrite") << "- already visited" << std::endl;
+ }
+ } while (!(tctx != nullptr ? visitctx->empty() : visit.empty()));
+ Assert(visited.find(tinitialHash) != visited.end());
+ Assert(!visited.find(tinitialHash)->second.isNull());
+ Trace("tconv-pf-gen-rewrite")
+ << "...finished, return " << visited[tinitialHash] << std::endl;
// return the conclusion of the overall proof
- return t.eqNode(visited[t]);
+ return t.eqNode(visited[tinitialHash]);
}
-void TConvProofGenerator::doCache(Node cur, Node r, LazyCDProof& pf)
+void TConvProofGenerator::doCache(Node curHash,
+ Node cur,
+ Node r,
+ LazyCDProof& pf)
{
if (d_cpolicy != TConvCachePolicy::NEVER)
{
Node eq = cur.eqNode(r);
- d_cache[cur] = pf.getProofFor(eq);
+ d_cache[curHash] = pf.getProofFor(eq);
}
}
-Node TConvProofGenerator::getRewriteStep(Node t) const
+Node TConvProofGenerator::getRewriteStepInternal(Node t) const
{
NodeNodeMap::const_iterator it = d_rewriteMap.find(t);
if (it == d_rewriteMap.end())
@@ -326,4 +513,12 @@ Node TConvProofGenerator::getRewriteStep(Node t) const
}
std::string TConvProofGenerator::identify() const { return d_name; }
+std::string TConvProofGenerator::toStringDebug() const
+{
+ std::stringstream ss;
+ ss << identify() << " (policy=" << d_policy << ", cache policy=" << d_cpolicy
+ << (d_tcontext != nullptr ? ", term-context-sensitive" : "") << ")";
+ return ss.str();
+}
+
} // namespace CVC4
diff --git a/src/expr/term_conversion_proof_generator.h b/src/expr/term_conversion_proof_generator.h
index e634b8a83..faee2b9e3 100644
--- a/src/expr/term_conversion_proof_generator.h
+++ b/src/expr/term_conversion_proof_generator.h
@@ -21,6 +21,7 @@
#include "expr/lazy_proof.h"
#include "expr/proof_generator.h"
#include "expr/proof_node_manager.h"
+#include "expr/term_context.h"
namespace CVC4 {
@@ -84,6 +85,35 @@ std::ostream& operator<<(std::ostream& out, TConvCachePolicy tcpol);
* addRewriteStep. In particular, notice that in the above example, we realize
* that f(a) --> c at pre-rewrite instead of post-rewriting a --> b and then
* ending with f(a)=f(b).
+ *
+ * This class may additionally be used for term-context-sensitive rewrite
+ * systems. An example is the term formula removal pass which rewrites
+ * terms dependending on whether they occur in a "term position", for details
+ * see RtfTermContext in expr/term_context.h. To use this class in a way
+ * that takes into account term contexts, the user of the term conversion
+ * proof generator should:
+ * (1) Provide a term context callback to the constructor of this class (tccb),
+ * (2) Register rewrite steps that indicate the term context identifier of
+ * the rewrite, which is a uint32_t.
+ *
+ * For example, RtfTermContext uses hash value 2 to indicate we are in a "term
+ * position". Say the user of this class calls:
+ * addRewriteStep( (and A B), BOOLEAN_TERM_VARIABLE_1, pg, true, 2)
+ * This indicates that (and A B) should rewrite to BOOLEAN_TERM_VARIABLE_1 if
+ * (and A B) occurs in a term position, where pg is a proof generator that can
+ * provide a closed proof of:
+ * (= (and A B) BOOLEAN_TERM_VARIABLE_1)
+ * Subsequently, this class may respond to a call to getProofFor on:
+ * (=
+ * (or (and A B) (P (and A B)))
+ * (or (and A B) (P BOOLEAN_TERM_VARIABLE_1)))
+ * where P is a predicate Bool -> Bool. The proof returned by this class
+ * involves congruence and pg's proof of the equivalence above. In particular,
+ * assuming its proof of the equivalence is P1, this proof is:
+ * (CONG{=} (CONG{or} (REFL (and A B)) (CONG{P} P1)))
+ * Notice the callback provided to this class ensures that the rewrite is
+ * replayed in the expected way, e.g. the occurrence of (and A B) that is not
+ * in term position is not rewritten.
*/
class TConvProofGenerator : public ProofGenerator
{
@@ -99,32 +129,48 @@ class TConvProofGenerator : public ProofGenerator
* details, see d_policy.
* @param cpol The caching policy for this generator.
* @param name The name of this generator (for debugging).
+ * @param tccb The term context callback that this class depends on. If this
+ * is non-null, then this class stores a term-context-sensitive rewrite
+ * system. The rewrite steps should be given term context identifiers.
*/
TConvProofGenerator(ProofNodeManager* pnm,
context::Context* c = nullptr,
TConvPolicy pol = TConvPolicy::FIXPOINT,
TConvCachePolicy cpol = TConvCachePolicy::NEVER,
- std::string name = "TConvProofGenerator");
+ std::string name = "TConvProofGenerator",
+ TermContext* tccb = nullptr);
~TConvProofGenerator();
/**
* Add rewrite step t --> s based on proof generator.
+ *
+ * @param isClosed whether to expect that pg can provide a closed proof for
+ * this fact.
+ * @param tctx The term context identifier for the rewrite step. This
+ * value should correspond to one generated by the term context callback
+ * class provided in the argument tccb provided to the constructor of this
+ * class.
*/
- void addRewriteStep(Node t, Node s, ProofGenerator* pg);
+ void addRewriteStep(Node t,
+ Node s,
+ ProofGenerator* pg,
+ bool isClosed = true,
+ uint32_t tctx = 0);
/** Same as above, for a single step */
- void addRewriteStep(Node t, Node s, ProofStep ps);
+ void addRewriteStep(Node t, Node s, ProofStep ps, uint32_t tctx = 0);
/** Same as above, with explicit arguments */
void addRewriteStep(Node t,
Node s,
PfRule id,
const std::vector<Node>& children,
- const std::vector<Node>& args);
+ const std::vector<Node>& args,
+ uint32_t tctx = 0);
/** Has rewrite step for term t */
- bool hasRewriteStep(Node t) const;
+ bool hasRewriteStep(Node t, uint32_t tctx = 0) const;
/**
* Get rewrite step for term t, returns the s provided in a call to
* addRewriteStep if one exists, or null otherwise.
*/
- Node getRewriteStep(Node t) const;
+ Node getRewriteStep(Node t, uint32_t tctx = 0) const;
/**
* Get the proof for formula f. It should be the case that f is of the form
* t = t', where t' is the result of rewriting t based on the rewrite steps
@@ -161,19 +207,25 @@ class TConvProofGenerator : public ProofGenerator
std::string d_name;
/** The cache for terms */
std::map<Node, std::shared_ptr<ProofNode> > d_cache;
+ /** An (optional) term context object */
+ TermContext* d_tcontext;
+ /** Get rewrite step for (hash value of) term. */
+ Node getRewriteStepInternal(Node thash) const;
/**
* Adds a proof of t = t' to the proof pf where t' is the result of rewriting
* t based on the rewrite steps registered to this class. This method then
* returns the proved equality t = t'.
*/
- Node getProofForRewriting(Node t, LazyCDProof& pf);
+ Node getProofForRewriting(Node t, LazyCDProof& pf, TermContext* tc = nullptr);
/**
* Register rewrite step, returns the equality t=s if t is distinct from s
* and a rewrite step has not already been registered for t.
*/
- Node registerRewriteStep(Node t, Node s);
+ Node registerRewriteStep(Node t, Node s, uint32_t tctx);
/** cache that r is the rewritten form of cur, pf can provide a proof */
- void doCache(Node cur, Node r, LazyCDProof& pf);
+ void doCache(Node curHash, Node cur, Node r, LazyCDProof& pf);
+ /** get debug information on this generator */
+ std::string toStringDebug() const;
};
} // namespace CVC4
diff --git a/src/expr/type_checker_template.cpp b/src/expr/type_checker_template.cpp
index 3dedd856a..8e4dd9236 100644
--- a/src/expr/type_checker_template.cpp
+++ b/src/expr/type_checker_template.cpp
@@ -14,8 +14,6 @@
** TypeChecker implementation.
**/
-#line 18 "${template}"
-
#include "expr/node_manager.h"
#include "expr/node_manager_attributes.h"
#include "expr/type_checker.h"
@@ -23,8 +21,6 @@
${typechecker_includes}
-#line 27 "${template}"
-
namespace CVC4 {
namespace expr {
@@ -44,8 +40,6 @@ TypeNode TypeChecker::computeType(NodeManager* nodeManager, TNode n, bool check)
${typerules}
-#line 48 "${template}"
-
default:
Debug("getType") << "FAILURE" << std::endl;
Unhandled() << n.getKind();
@@ -68,8 +62,6 @@ bool TypeChecker::computeIsConst(NodeManager* nodeManager, TNode n)
switch(n.getKind()) {
${construles}
-#line 72 "${template}"
-
default:;
}
diff --git a/src/expr/type_properties_template.h b/src/expr/type_properties_template.h
index a8adadf6e..9bccd5892 100644
--- a/src/expr/type_properties_template.h
+++ b/src/expr/type_properties_template.h
@@ -19,8 +19,6 @@
#ifndef CVC4__TYPE_PROPERTIES_H
#define CVC4__TYPE_PROPERTIES_H
-#line 23 "${template}"
-
#include <sstream>
#include "base/check.h"
@@ -31,8 +29,6 @@
${type_properties_includes}
-#line 35 "${template}"
-
namespace CVC4 {
namespace kind {
@@ -47,7 +43,6 @@ inline Cardinality getCardinality(TypeConstant tc)
switch (tc)
{
${type_constant_cardinalities}
-#line 51 "${template}"
default: InternalError() << "No cardinality known for type constant " << tc;
}
} /* getCardinality(TypeConstant) */
@@ -64,7 +59,6 @@ inline Cardinality getCardinality(TypeNode typeNode) {
case TYPE_CONSTANT:
return getCardinality(typeNode.getConst<TypeConstant>());
${type_cardinalities}
-#line 68 "${template}"
default:
InternalError() << "A theory kinds file did not provide a cardinality "
<< "or cardinality computer for type:\n"
@@ -75,7 +69,6 @@ ${type_cardinalities}
inline bool isWellFounded(TypeConstant tc) {
switch(tc) {
${type_constant_wellfoundednesses}
-#line 79 "${template}"
default:
InternalError() << "No well-foundedness status known for type constant: "
<< tc;
@@ -88,7 +81,6 @@ inline bool isWellFounded(TypeNode typeNode) {
case TYPE_CONSTANT:
return isWellFounded(typeNode.getConst<TypeConstant>());
${type_wellfoundednesses}
-#line 92 "${template}"
default:
InternalError() << "A theory kinds file did not provide a well-foundedness "
<< "or well-foundedness computer for type:\n"
@@ -101,7 +93,6 @@ inline Node mkGroundTerm(TypeConstant tc)
switch (tc)
{
${type_constant_groundterms}
-#line 105 "${template}"
default:
InternalError() << "No ground term known for type constant: " << tc;
}
@@ -115,7 +106,6 @@ inline Node mkGroundTerm(TypeNode typeNode)
case TYPE_CONSTANT:
return mkGroundTerm(typeNode.getConst<TypeConstant>());
${type_groundterms}
-#line 119 "${template}"
default:
InternalError() << "A theory kinds file did not provide a ground term "
<< "or ground term computer for type:\n"
diff --git a/src/fix-install-headers.sh b/src/fix-install-headers.sh
index 39d8bc663..7f9fa5d5b 100755
--- a/src/fix-install-headers.sh
+++ b/src/fix-install-headers.sh
@@ -2,6 +2,7 @@
set -e -o pipefail
-dir=$1
+dir="$DESTDIR$1"
+
find "$dir/include/cvc4/" -type f \
-exec sed -i'' -e 's/include.*"\(.*\)"/include <cvc4\/\1>/' {} +
diff --git a/src/options/bv_options.toml b/src/options/bv_options.toml
index 7c0aca100..e00db9393 100644
--- a/src/options/bv_options.toml
+++ b/src/options/bv_options.toml
@@ -3,44 +3,6 @@ name = "Bitvector theory"
header = "options/bv_options.h"
[[option]]
- name = "bvProofFormat"
- category = "expert"
- long = "bv-proof-format=MODE"
- type = "BvProofFormat"
- default = "ER"
- predicates = ["checkSatSolverEnabled<BvProofFormat>"]
- help = "choose which UNSAT proof format to use, see --bv-sat-solver=help"
- help_mode = "Bit-vector proof formats."
-[[option.mode.ER]]
- name = "er"
- help = "Extended Resolution, i.e. resolution with new variable definitions."
-[[option.mode.DRAT]]
- name = "drat"
- help = "Deletion and Resolution Asymmetric Tautology Additions."
-[[option.mode.LRAT]]
- name = "lrat"
- help = "DRAT with unit propagation hints to accelerate checking."
-
-[[option]]
- name = "bvOptimizeSatProof"
- category = "expert"
- long = "bv-optimize-sat-proof=MODE"
- type = "BvOptimizeSatProof"
- default = "FORMULA"
- predicates = ["checkSatSolverEnabled<BvOptimizeSatProof>"]
- help = "enable SAT proof optimizations, see --bv-optimize-sat-proof=help"
- help_mode = "SAT proof optimization level."
-[[option.mode.NONE]]
- name = "none"
- help = "Do not optimize the SAT proof."
-[[option.mode.PROOF]]
- name = "proof"
- help = "Use drat-trim to shrink the SAT proof."
-[[option.mode.FORMULA]]
- name = "formula"
- help = "Use drat-trim to shrink the SAT proof and formula."
-
-[[option]]
name = "bvSatSolver"
smt_name = "bv-sat-solver"
category = "expert"
diff --git a/src/options/options.h b/src/options/options.h
index 44f4be7b4..abcf21264 100644
--- a/src/options/options.h
+++ b/src/options/options.h
@@ -150,7 +150,6 @@ public:
options::InstFormatMode getInstFormatMode() const;
OutputLanguage getOutputLanguage() const;
bool getUfHo() const;
- bool getCheckProofs() const;
bool getDumpInstantiations() const;
bool getDumpModels() const;
bool getDumpProofs() const;
@@ -167,7 +166,6 @@ public:
bool getMemoryMap() const;
bool getParseOnly() const;
bool getProduceModels() const;
- bool getProof() const;
bool getSegvSpin() const;
bool getSemanticChecks() const;
bool getStatistics() const;
diff --git a/src/options/options_public_functions.cpp b/src/options/options_public_functions.cpp
index c8104c584..2dc28b10d 100644
--- a/src/options/options_public_functions.cpp
+++ b/src/options/options_public_functions.cpp
@@ -54,10 +54,6 @@ OutputLanguage Options::getOutputLanguage() const {
bool Options::getUfHo() const { return (*this)[options::ufHo]; }
-bool Options::getCheckProofs() const{
- return (*this)[options::checkProofs];
-}
-
bool Options::getDumpInstantiations() const{
return (*this)[options::dumpInstantiations];
}
@@ -124,10 +120,6 @@ bool Options::getProduceModels() const{
return (*this)[options::produceModels];
}
-bool Options::getProof() const{
- return (*this)[options::proof];
-}
-
bool Options::getSegvSpin() const{
return (*this)[options::segvSpin];
}
diff --git a/src/options/proof_options.toml b/src/options/proof_options.toml
index a23241e3d..9db541e27 100644
--- a/src/options/proof_options.toml
+++ b/src/options/proof_options.toml
@@ -1,38 +1,3 @@
id = "PROOF"
name = "Proof"
header = "options/proof_options.h"
-
-[[option]]
- name = "lfscLetification"
- category = "regular"
- long = "lfsc-letification"
- type = "bool"
- default = "true"
- read_only = true
- help = "turns on global letification in LFSC proofs"
-
-[[option]]
- name = "aggressiveCoreMin"
- category = "regular"
- long = "aggressive-core-min"
- type = "bool"
- default = "false"
- read_only = true
- help = "turns on aggressive unsat core minimization (experimental)"
-
-[[option]]
- name = "fewerPreprocessingHoles"
- category = "regular"
- long = "fewer-preprocessing-holes"
- type = "bool"
- default = "false"
- help = "try to eliminate preprocessing holes in proofs"
-
-[[option]]
- name = "allowEmptyDependencies"
- category = "regular"
- long = "allow-empty-dependencies"
- type = "bool"
- default = "false"
- read_only = true
- help = "if unable to track the dependencies of a rewritten/preprocessed assertion, fail silently"
diff --git a/src/options/smt_options.toml b/src/options/smt_options.toml
index 6b5bee6bb..2c87158de 100644
--- a/src/options/smt_options.toml
+++ b/src/options/smt_options.toml
@@ -131,24 +131,6 @@ header = "options/smt_options.h"
help = "Block models based on the concrete model values for the free variables."
[[option]]
- name = "proof"
- smt_name = "produce-proofs"
- category = "regular"
- long = "proof"
- type = "bool"
- default = "false"
- predicates = ["proofEnabledBuild"]
- help = "turn on proof generation"
-
-[[option]]
- name = "checkProofs"
- category = "regular"
- long = "check-proofs"
- type = "bool"
- predicates = ["LFSCEnabledBuild"]
- help = "after UNSAT/VALID, machine-check the generated proof"
-
-[[option]]
name = "dumpProofs"
category = "regular"
long = "dump-proofs"
@@ -390,7 +372,7 @@ header = "options/smt_options.h"
type = "bool"
default = "false"
help = "calculate sort inference of input problem, convert the input based on monotonic sorts"
-
+
[[option]]
name = "incrementalSolving"
category = "common"
@@ -660,7 +642,7 @@ header = "options/smt_options.h"
[[option.mode.BITWISE]]
name = "bitwise"
help = "use bitwise comparisons on binary representation of integer for refinement (experimental)"
-
+
[[option]]
name = "solveIntAsBV"
category = "undocumented"
diff --git a/src/parser/cvc/Cvc.g b/src/parser/cvc/Cvc.g
index 091b5a22b..865776dcd 100644
--- a/src/parser/cvc/Cvc.g
+++ b/src/parser/cvc/Cvc.g
@@ -2481,7 +2481,7 @@ fragment DOT:;
fragment DOTDOT:;
/**
- * Matches the hexidecimal digits (0-9, a-f, A-F)
+ * Matches the hexadecimal digits (0-9, a-f, A-F)
*/
fragment HEX_DIGIT : DIGIT | 'a'..'f' | 'A'..'F';
diff --git a/src/parser/smt2/smt2.cpp b/src/parser/smt2/smt2.cpp
index 1e5d2155a..c4899c8a8 100644
--- a/src/parser/smt2/smt2.cpp
+++ b/src/parser/smt2/smt2.cpp
@@ -718,7 +718,7 @@ Command* Smt2::setLogic(std::string name, bool fromCommand)
}
if (d_logic.isTheoryEnabled(theory::THEORY_FP)) {
- defineType("RoundingMode", d_solver->getRoundingmodeSort());
+ defineType("RoundingMode", d_solver->getRoundingModeSort());
defineType("Float16", d_solver->mkFloatingPointSort(5, 11));
defineType("Float32", d_solver->mkFloatingPointSort(8, 24));
defineType("Float64", d_solver->mkFloatingPointSort(11, 53));
diff --git a/src/preprocessing/assertion_pipeline.cpp b/src/preprocessing/assertion_pipeline.cpp
index a6b9531b6..a9e2d4d36 100644
--- a/src/preprocessing/assertion_pipeline.cpp
+++ b/src/preprocessing/assertion_pipeline.cpp
@@ -16,7 +16,7 @@
#include "preprocessing/assertion_pipeline.h"
#include "expr/node_manager.h"
-#include "proof/proof.h"
+#include "options/smt_options.h"
#include "proof/proof_manager.h"
#include "theory/rewriter.h"
@@ -77,7 +77,10 @@ void AssertionPipeline::pushBackTrusted(theory::TrustNode trn)
void AssertionPipeline::replace(size_t i, Node n, ProofGenerator* pgen)
{
- PROOF(ProofManager::currentPM()->addDependence(n, d_nodes[i]););
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, d_nodes[i]);
+ }
if (isProofEnabled())
{
d_pppg->notifyPreprocessed(d_nodes[i], n, pgen);
@@ -96,11 +99,14 @@ void AssertionPipeline::replace(size_t i,
const std::vector<Node>& addnDeps,
ProofGenerator* pgen)
{
- PROOF(ProofManager::currentPM()->addDependence(n, d_nodes[i]);
- for (const auto& addnDep
- : addnDeps) {
- ProofManager::currentPM()->addDependence(n, addnDep);
- });
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, d_nodes[i]);
+ for (const auto& addnDep : addnDeps)
+ {
+ ProofManager::currentPM()->addDependence(n, addnDep);
+ }
+ }
if (isProofEnabled())
{
d_pppg->notifyPreprocessed(d_nodes[i], n, pgen);
diff --git a/src/preprocessing/passes/ackermann.cpp b/src/preprocessing/passes/ackermann.cpp
index 31c92a09f..ab9c2482b 100644
--- a/src/preprocessing/passes/ackermann.cpp
+++ b/src/preprocessing/passes/ackermann.cpp
@@ -70,11 +70,14 @@ void addLemmaForPair(TNode args1,
}
else
{
- Assert(args1.getKind() == kind::SELECT && args1[0] == func);
- Assert(args2.getKind() == kind::SELECT && args2[0] == func);
+ Assert(args1.getKind() == kind::SELECT && args1.getOperator() == func);
+ Assert(args2.getKind() == kind::SELECT && args2.getOperator() == func);
Assert(args1.getNumChildren() == 2);
Assert(args2.getNumChildren() == 2);
- args_eq = nm->mkNode(kind::EQUAL, args1[1], args2[1]);
+ args_eq = nm->mkNode(Kind::AND,
+ nm->mkNode(kind::EQUAL, args1[0], args2[0]),
+ nm->mkNode(kind::EQUAL, args1[1], args2[1])
+ );
}
Node func_eq = nm->mkNode(kind::EQUAL, args1, args2);
Node lemma = nm->mkNode(kind::IMPLIES, args_eq, func_eq);
@@ -153,7 +156,7 @@ void collectFunctionsAndLemmas(FunctionToArgsMap& fun_to_args,
if (seen.find(term) == seen.end())
{
TNode func;
- if (term.getKind() == kind::APPLY_UF)
+ if (term.getKind() == kind::APPLY_UF || term.getKind() == kind::SELECT)
{
storeFunctionAndAddLemmas(term.getOperator(),
term,
@@ -163,11 +166,6 @@ void collectFunctionsAndLemmas(FunctionToArgsMap& fun_to_args,
nm,
vec);
}
- else if (term.getKind() == kind::SELECT)
- {
- storeFunctionAndAddLemmas(
- term[0], term, fun_to_args, fun_to_skolem, assertions, nm, vec);
- }
else
{
AlwaysAssert(term.getKind() != kind::STORE)
diff --git a/src/preprocessing/passes/ite_simp.cpp b/src/preprocessing/passes/ite_simp.cpp
index 9a6a8ec61..388c5742d 100644
--- a/src/preprocessing/passes/ite_simp.cpp
+++ b/src/preprocessing/passes/ite_simp.cpp
@@ -16,7 +16,6 @@
#include <vector>
-#include "options/proof_options.h"
#include "smt/smt_statistics_registry.h"
#include "smt_util/nary_builder.h"
#include "theory/arith/arith_ite_utils.h"
@@ -118,7 +117,7 @@ bool ITESimp::doneSimpITE(AssertionPipeline* assertionsToPreprocess)
// This pass does not support dependency tracking yet
// (learns substitutions from all assertions so just
// adding addDependence is not enough)
- if (options::unsatCores() || options::fewerPreprocessingHoles())
+ if (options::unsatCores())
{
return true;
}
diff --git a/src/preprocessing/passes/miplib_trick.cpp b/src/preprocessing/passes/miplib_trick.cpp
index f64fce118..3a8bbdb70 100644
--- a/src/preprocessing/passes/miplib_trick.cpp
+++ b/src/preprocessing/passes/miplib_trick.cpp
@@ -522,8 +522,10 @@ PreprocessingPassResult MipLibTrick::applyInternal(
Node n = Rewriter::rewrite(geq.andNode(leq));
assertionsToPreprocess->push_back(n);
- PROOF(ProofManager::currentPM()->addDependence(n, Node::null()));
-
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, Node::null());
+ }
SubstitutionMap nullMap(&fakeContext);
Theory::PPAssertStatus status CVC4_UNUSED; // just for assertions
status = te->solve(geq, nullMap);
@@ -591,9 +593,11 @@ PreprocessingPassResult MipLibTrick::applyInternal(
Debug("miplib") << " " << newAssertion << endl;
assertionsToPreprocess->push_back(newAssertion);
- PROOF(ProofManager::currentPM()->addDependence(newAssertion,
- Node::null()));
-
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(newAssertion,
+ Node::null());
+ }
Debug("miplib") << " assertions to remove: " << endl;
for (vector<TNode>::const_iterator k = asserts[pos_var].begin(),
k_end = asserts[pos_var].end();
diff --git a/src/preprocessing/passes/non_clausal_simp.cpp b/src/preprocessing/passes/non_clausal_simp.cpp
index 6d2482a0e..24c1ac67b 100644
--- a/src/preprocessing/passes/non_clausal_simp.cpp
+++ b/src/preprocessing/passes/non_clausal_simp.cpp
@@ -19,7 +19,6 @@
#include <vector>
#include "context/cdo.h"
-#include "options/proof_options.h"
#include "smt/smt_statistics_registry.h"
#include "theory/theory_model.h"
@@ -54,7 +53,7 @@ NonClausalSimp::NonClausalSimp(PreprocessingPassContext* preprocContext)
PreprocessingPassResult NonClausalSimp::applyInternal(
AssertionPipeline* assertionsToPreprocess)
{
- Assert(!options::unsatCores() && !options::fewerPreprocessingHoles());
+ Assert(!options::unsatCores());
d_preprocContext->spendResource(ResourceManager::Resource::PreprocessStep);
@@ -98,11 +97,14 @@ PreprocessingPassResult NonClausalSimp::applyInternal(
// If in conflict, just return false
Trace("non-clausal-simplify")
<< "conflict in non-clausal propagation" << std::endl;
- Assert(!options::unsatCores() && !options::fewerPreprocessingHoles());
+ Assert(!options::unsatCores());
assertionsToPreprocess->clear();
Node n = NodeManager::currentNM()->mkConst<bool>(false);
assertionsToPreprocess->push_back(n);
- PROOF(ProofManager::currentPM()->addDependence(n, Node::null()));
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, Node::null());
+ }
propagator->setNeedsFinish(true);
return PreprocessingPassResult::CONFLICT;
}
@@ -164,7 +166,10 @@ PreprocessingPassResult NonClausalSimp::applyInternal(
assertionsToPreprocess->clear();
Node n = NodeManager::currentNM()->mkConst<bool>(false);
assertionsToPreprocess->push_back(n);
- PROOF(ProofManager::currentPM()->addDependence(n, Node::null()));
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, Node::null());
+ }
propagator->setNeedsFinish(true);
return PreprocessingPassResult::CONFLICT;
}
@@ -207,7 +212,10 @@ PreprocessingPassResult NonClausalSimp::applyInternal(
assertionsToPreprocess->clear();
Node n = NodeManager::currentNM()->mkConst<bool>(false);
assertionsToPreprocess->push_back(n);
- PROOF(ProofManager::currentPM()->addDependence(n, Node::null()));
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, Node::null());
+ }
propagator->setNeedsFinish(true);
return PreprocessingPassResult::CONFLICT;
}
@@ -241,7 +249,6 @@ PreprocessingPassResult NonClausalSimp::applyInternal(
// equations[0].second); assertionsToPreprocess->clear();
// Node n = NodeManager::currentNM()->mkConst<bool>(false);
// assertionsToPreprocess->push_back(n);
- // PROOF(ProofManager::currentPM()->addDependence(n, Node::null()));
// false); return;
// }
// top_level_substs.simplifyRHS(constantPropagations);
diff --git a/src/preprocessing/passes/quantifier_macros.cpp b/src/preprocessing/passes/quantifier_macros.cpp
index a4d8454a0..f4bc43542 100644
--- a/src/preprocessing/passes/quantifier_macros.cpp
+++ b/src/preprocessing/passes/quantifier_macros.cpp
@@ -19,7 +19,6 @@
#include <vector>
#include "options/quantifiers_options.h"
-#include "proof/proof_manager.h"
#include "smt/smt_engine.h"
#include "smt/smt_engine_scope.h"
#include "theory/arith/arith_msum.h"
@@ -79,11 +78,14 @@ bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite
for( int i=0; i<(int)assertions.size(); i++ ){
Trace("macros-debug") << " process assertion " << assertions[i] << std::endl;
if( processAssertion( assertions[i] ) ){
- PROOF(
- if( std::find( macro_assertions.begin(), macro_assertions.end(), assertions[i] )==macro_assertions.end() ){
- macro_assertions.push_back( assertions[i] );
- }
- );
+ if (options::unsatCores()
+ && std::find(macro_assertions.begin(),
+ macro_assertions.end(),
+ assertions[i])
+ == macro_assertions.end())
+ {
+ macro_assertions.push_back(assertions[i]);
+ }
//process this assertion again
i--;
}
@@ -98,17 +100,22 @@ bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite
if( curr!=assertions[i] ){
curr = Rewriter::rewrite( curr );
Trace("macros-rewrite") << "Rewrite " << assertions[i] << " to " << curr << std::endl;
- //for now, it is dependent upon all assertions involving macros, this is an over-approximation.
- //a more fine-grained unsat core computation would require caching dependencies for each subterm of the formula,
- // which is expensive.
- PROOF(ProofManager::currentPM()->addDependence(curr, assertions[i]);
- for (unsigned j = 0; j < macro_assertions.size(); j++) {
- if (macro_assertions[j] != assertions[i])
- {
- ProofManager::currentPM()->addDependence(
- curr, macro_assertions[j]);
- }
- });
+ // for now, it is dependent upon all assertions involving macros, this
+ // is an over-approximation. a more fine-grained unsat core
+ // computation would require caching dependencies for each subterm of
+ // the formula, which is expensive.
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(curr, assertions[i]);
+ for (unsigned j = 0; j < macro_assertions.size(); j++)
+ {
+ if (macro_assertions[j] != assertions[i])
+ {
+ ProofManager::currentPM()->addDependence(curr,
+ macro_assertions[j]);
+ }
+ }
+ }
assertions[i] = curr;
retVal = true;
}
@@ -432,9 +439,9 @@ Node QuantifierMacros::simplify( Node n ){
for( unsigned i=0; i<children.size(); i++ ){
Node etc = TypeNode::getEnsureTypeCondition( children[i], tno[i] );
if( etc.isNull() ){
- //if this does fail, we are incomplete, since we are eliminating quantified formula corresponding to op,
+ // if this does fail, we are incomplete, since we are eliminating
+ // quantified formula corresponding to op,
// and not ensuring it applies to n when its types are correct.
- //Assert( false );
success = false;
break;
}else if( !etc.isConst() ){
diff --git a/src/printer/ast/ast_printer.cpp b/src/printer/ast/ast_printer.cpp
index d4f28c186..f235721f1 100644
--- a/src/printer/ast/ast_printer.cpp
+++ b/src/printer/ast/ast_printer.cpp
@@ -26,6 +26,7 @@
#include "options/language.h" // for LANG_AST
#include "printer/dagification_visitor.h"
#include "smt/command.h"
+#include "smt/node_command.h"
#include "theory/substitutions.h"
using namespace std;
@@ -156,7 +157,7 @@ void AstPrinter::toStream(std::ostream& out, const Model& m) const
void AstPrinter::toStream(std::ostream& out,
const Model& m,
- const Command* c) const
+ const NodeCommand* c) const
{
// shouldn't be called; only the non-Command* version above should be
Unreachable();
diff --git a/src/printer/ast/ast_printer.h b/src/printer/ast/ast_printer.h
index 17e052037..969240930 100644
--- a/src/printer/ast/ast_printer.h
+++ b/src/printer/ast/ast_printer.h
@@ -175,7 +175,7 @@ class AstPrinter : public CVC4::Printer
void toStream(std::ostream& out, TNode n, int toDepth, bool types) const;
void toStream(std::ostream& out,
const Model& m,
- const Command* c) const override;
+ const NodeCommand* c) const override;
}; /* class AstPrinter */
} // namespace ast
diff --git a/src/printer/cvc/cvc_printer.cpp b/src/printer/cvc/cvc_printer.cpp
index 89b516511..b94977cfe 100644
--- a/src/printer/cvc/cvc_printer.cpp
+++ b/src/printer/cvc/cvc_printer.cpp
@@ -33,6 +33,7 @@
#include "options/smt_options.h"
#include "printer/dagification_visitor.h"
#include "smt/command.h"
+#include "smt/node_command.h"
#include "smt/smt_engine.h"
#include "theory/arrays/theory_arrays_rewriter.h"
#include "theory/substitutions.h"
@@ -1059,11 +1060,11 @@ void CvcPrinter::toStream(std::ostream& out, const CommandStatus* s) const
namespace {
-void DeclareTypeCommandToStream(std::ostream& out,
- const theory::TheoryModel& model,
- const DeclareTypeCommand& command)
+void DeclareTypeNodeCommandToStream(std::ostream& out,
+ const theory::TheoryModel& model,
+ const DeclareTypeNodeCommand& command)
{
- TypeNode type_node = TypeNode::fromType(command.getType());
+ TypeNode type_node = command.getType();
const std::vector<Node>* type_reps =
model.getRepSet()->getTypeRepsOrNull(type_node);
if (options::modelUninterpDtEnum() && type_node.isSort()
@@ -1104,11 +1105,12 @@ void DeclareTypeCommandToStream(std::ostream& out,
}
}
-void DeclareFunctionCommandToStream(std::ostream& out,
- const theory::TheoryModel& model,
- const DeclareFunctionCommand& command)
+void DeclareFunctionNodeCommandToStream(
+ std::ostream& out,
+ const theory::TheoryModel& model,
+ const DeclareFunctionNodeCommand& command)
{
- Node n = Node::fromExpr(command.getFunction());
+ Node n = command.getFunction();
if (n.getKind() == kind::SKOLEM)
{
// don't print out internal stuff
@@ -1172,23 +1174,23 @@ void CvcPrinter::toStream(std::ostream& out, const Model& m) const
void CvcPrinter::toStream(std::ostream& out,
const Model& model,
- const Command* command) const
+ const NodeCommand* command) const
{
const auto* theory_model = dynamic_cast<const theory::TheoryModel*>(&model);
AlwaysAssert(theory_model != nullptr);
if (const auto* declare_type_command =
- dynamic_cast<const DeclareTypeCommand*>(command))
+ dynamic_cast<const DeclareTypeNodeCommand*>(command))
{
- DeclareTypeCommandToStream(out, *theory_model, *declare_type_command);
+ DeclareTypeNodeCommandToStream(out, *theory_model, *declare_type_command);
}
else if (const auto* dfc =
- dynamic_cast<const DeclareFunctionCommand*>(command))
+ dynamic_cast<const DeclareFunctionNodeCommand*>(command))
{
- DeclareFunctionCommandToStream(out, *theory_model, *dfc);
+ DeclareFunctionNodeCommandToStream(out, *theory_model, *dfc);
}
else
{
- out << command << std::endl;
+ out << *command << std::endl;
}
}
diff --git a/src/printer/cvc/cvc_printer.h b/src/printer/cvc/cvc_printer.h
index 0fd3d3a49..3c61fb74f 100644
--- a/src/printer/cvc/cvc_printer.h
+++ b/src/printer/cvc/cvc_printer.h
@@ -177,7 +177,7 @@ class CvcPrinter : public CVC4::Printer
std::ostream& out, TNode n, int toDepth, bool types, bool bracket) const;
void toStream(std::ostream& out,
const Model& m,
- const Command* c) const override;
+ const NodeCommand* c) const override;
bool d_cvc3Mode;
}; /* class CvcPrinter */
diff --git a/src/printer/printer.cpp b/src/printer/printer.cpp
index 0e7550518..d13fc55f1 100644
--- a/src/printer/printer.cpp
+++ b/src/printer/printer.cpp
@@ -23,6 +23,7 @@
#include "printer/cvc/cvc_printer.h"
#include "printer/smt2/smt2_printer.h"
#include "printer/tptp/tptp_printer.h"
+#include "smt/node_command.h"
using namespace std;
@@ -72,9 +73,10 @@ unique_ptr<Printer> Printer::makePrinter(OutputLanguage lang)
void Printer::toStream(std::ostream& out, const Model& m) const
{
for(size_t i = 0; i < m.getNumCommands(); ++i) {
- const Command* cmd = m.getCommand(i);
- const DeclareFunctionCommand* dfc = dynamic_cast<const DeclareFunctionCommand*>(cmd);
- if (dfc != NULL && !m.isModelCoreSymbol(dfc->getFunction()))
+ const NodeCommand* cmd = m.getCommand(i);
+ const DeclareFunctionNodeCommand* dfc =
+ dynamic_cast<const DeclareFunctionNodeCommand*>(cmd);
+ if (dfc != NULL && !m.isModelCoreSymbol(dfc->getFunction().toExpr()))
{
continue;
}
diff --git a/src/printer/printer.h b/src/printer/printer.h
index 3b737ec5f..8c95e3e9b 100644
--- a/src/printer/printer.h
+++ b/src/printer/printer.h
@@ -30,6 +30,8 @@
namespace CVC4 {
+class NodeCommand;
+
class Printer
{
public:
@@ -271,13 +273,13 @@ class Printer
/** write model response to command */
virtual void toStream(std::ostream& out,
const Model& m,
- const Command* c) const = 0;
+ const NodeCommand* c) const = 0;
/** write model response to command using another language printer */
void toStreamUsing(OutputLanguage lang,
std::ostream& out,
const Model& m,
- const Command* c) const
+ const NodeCommand* c) const
{
getPrinter(lang)->toStream(out, m, c);
}
diff --git a/src/printer/smt2/smt2_printer.cpp b/src/printer/smt2/smt2_printer.cpp
index 3d76c81dc..da0423956 100644
--- a/src/printer/smt2/smt2_printer.cpp
+++ b/src/printer/smt2/smt2_printer.cpp
@@ -31,11 +31,12 @@
#include "options/printer_options.h"
#include "options/smt_options.h"
#include "printer/dagification_visitor.h"
+#include "smt/node_command.h"
#include "smt/smt_engine.h"
#include "smt_util/boolean_simplification.h"
#include "theory/arrays/theory_arrays_rewriter.h"
-#include "theory/quantifiers/quantifiers_attributes.h"
#include "theory/datatypes/sygus_datatype_utils.h"
+#include "theory/quantifiers/quantifiers_attributes.h"
#include "theory/substitutions.h"
#include "theory/theory_model.h"
#include "util/smt2_quote_string.h"
@@ -1331,23 +1332,23 @@ void Smt2Printer::toStream(std::ostream& out, const Model& m) const
void Smt2Printer::toStream(std::ostream& out,
const Model& model,
- const Command* command) const
+ const NodeCommand* command) const
{
const theory::TheoryModel* theory_model =
dynamic_cast<const theory::TheoryModel*>(&model);
AlwaysAssert(theory_model != nullptr);
- if (const DeclareTypeCommand* dtc =
- dynamic_cast<const DeclareTypeCommand*>(command))
+ if (const DeclareTypeNodeCommand* dtc =
+ dynamic_cast<const DeclareTypeNodeCommand*>(command))
{
// print out the DeclareTypeCommand
- Type t = (*dtc).getType();
- if (!t.isSort())
+ TypeNode tn = dtc->getType();
+ if (!tn.isSort())
{
out << (*dtc) << endl;
}
else
{
- std::vector<Expr> elements = theory_model->getDomainElements(t);
+ std::vector<Expr> elements = theory_model->getDomainElements(tn.toType());
if (options::modelUninterpDtEnum())
{
if (isVariant_2_6(d_variant))
@@ -1367,7 +1368,7 @@ void Smt2Printer::toStream(std::ostream& out,
else
{
// print the cardinality
- out << "; cardinality of " << t << " is " << elements.size() << endl;
+ out << "; cardinality of " << tn << " is " << elements.size() << endl;
out << (*dtc) << endl;
// print the representatives
for (const Expr& type_ref : elements)
@@ -1375,7 +1376,7 @@ void Smt2Printer::toStream(std::ostream& out,
Node trn = Node::fromExpr(type_ref);
if (trn.isVar())
{
- out << "(declare-fun " << quoteSymbol(trn) << " () " << t << ")"
+ out << "(declare-fun " << quoteSymbol(trn) << " () " << tn << ")"
<< endl;
}
else
@@ -1386,11 +1387,11 @@ void Smt2Printer::toStream(std::ostream& out,
}
}
}
- else if (const DeclareFunctionCommand* dfc =
- dynamic_cast<const DeclareFunctionCommand*>(command))
+ else if (const DeclareFunctionNodeCommand* dfc =
+ dynamic_cast<const DeclareFunctionNodeCommand*>(command))
{
// print out the DeclareFunctionCommand
- Node n = Node::fromExpr((*dfc).getFunction());
+ Node n = dfc->getFunction();
if ((*dfc).getPrintInModelSetByUser())
{
if (!(*dfc).getPrintInModel())
@@ -1432,10 +1433,10 @@ void Smt2Printer::toStream(std::ostream& out,
out << ")" << endl;
}
}
- else if (const DatatypeDeclarationCommand* datatype_declaration_command =
- dynamic_cast<const DatatypeDeclarationCommand*>(command))
+ else if (const DeclareDatatypeNodeCommand* declare_datatype_command =
+ dynamic_cast<const DeclareDatatypeNodeCommand*>(command))
{
- out << datatype_declaration_command;
+ out << *declare_datatype_command;
}
else
{
diff --git a/src/printer/smt2/smt2_printer.h b/src/printer/smt2/smt2_printer.h
index 6b57823a4..0cf06dd6b 100644
--- a/src/printer/smt2/smt2_printer.h
+++ b/src/printer/smt2/smt2_printer.h
@@ -19,8 +19,6 @@
#ifndef CVC4__PRINTER__SMT2_PRINTER_H
#define CVC4__PRINTER__SMT2_PRINTER_H
-#include <iostream>
-
#include "printer/printer.h"
namespace CVC4 {
@@ -234,7 +232,7 @@ class Smt2Printer : public CVC4::Printer
std::ostream& out, TNode n, int toDepth, bool types, TypeNode nt) const;
void toStream(std::ostream& out,
const Model& m,
- const Command* c) const override;
+ const NodeCommand* c) const override;
void toStream(std::ostream& out, const SExpr& sexpr) const;
void toStream(std::ostream& out, const DType& dt) const;
diff --git a/src/printer/tptp/tptp_printer.cpp b/src/printer/tptp/tptp_printer.cpp
index c4623f76a..d25666d70 100644
--- a/src/printer/tptp/tptp_printer.cpp
+++ b/src/printer/tptp/tptp_printer.cpp
@@ -20,12 +20,13 @@
#include <typeinfo>
#include <vector>
-#include "expr/expr.h" // for ExprSetDepth etc..
-#include "expr/node_manager.h" // for VarNameAttr
-#include "options/language.h" // for LANG_AST
-#include "options/smt_options.h" // for unsat cores
-#include "smt/smt_engine.h"
+#include "expr/expr.h" // for ExprSetDepth etc..
+#include "expr/node_manager.h" // for VarNameAttr
+#include "options/language.h" // for LANG_AST
+#include "options/smt_options.h" // for unsat cores
#include "smt/command.h"
+#include "smt/node_command.h"
+#include "smt/smt_engine.h"
using namespace std;
@@ -59,7 +60,7 @@ void TptpPrinter::toStream(std::ostream& out, const Model& m) const
void TptpPrinter::toStream(std::ostream& out,
const Model& m,
- const Command* c) const
+ const NodeCommand* c) const
{
// shouldn't be called; only the non-Command* version above should be
Unreachable();
diff --git a/src/printer/tptp/tptp_printer.h b/src/printer/tptp/tptp_printer.h
index 6682b495e..9377a8895 100644
--- a/src/printer/tptp/tptp_printer.h
+++ b/src/printer/tptp/tptp_printer.h
@@ -47,7 +47,7 @@ class TptpPrinter : public CVC4::Printer
private:
void toStream(std::ostream& out,
const Model& m,
- const Command* c) const override;
+ const NodeCommand* c) const override;
}; /* class TptpPrinter */
diff --git a/src/proof/arith_proof.cpp b/src/proof/arith_proof.cpp
deleted file mode 100644
index 635767b97..000000000
--- a/src/proof/arith_proof.cpp
+++ /dev/null
@@ -1,1207 +0,0 @@
-/********************* */
-/*! \file arith_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Liana Hadarean, Guy Katz
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-#include "proof/arith_proof.h"
-
-#include <memory>
-#include <stack>
-
-#include "base/check.h"
-#include "expr/node.h"
-#include "expr/type_checker_util.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
-#include "theory/arith/constraint_forward.h"
-#include "theory/arith/normal_form.h"
-#include "theory/arith/theory_arith.h"
-
-#define CVC4_ARITH_VAR_TERM_PREFIX "term."
-
-namespace CVC4 {
-
-inline static Node eqNode(TNode n1, TNode n2) {
- return NodeManager::currentNM()->mkNode(kind::EQUAL, n1, n2);
-}
-
-// congrence matching term helper
-inline static bool match(TNode n1, TNode n2) {
- Debug("pf::arith") << "match " << n1 << " " << n2 << std::endl;
- if(ProofManager::currentPM()->hasOp(n1)) {
- n1 = ProofManager::currentPM()->lookupOp(n1);
- }
- if(ProofManager::currentPM()->hasOp(n2)) {
- n2 = ProofManager::currentPM()->lookupOp(n2);
- }
- Debug("pf::arith") << "+ match " << n1 << " " << n2 << std::endl;
- if(n1 == n2) {
- return true;
- }
- if(n1.getType().isFunction() && n2.hasOperator()) {
- if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
- return n1 == ProofManager::currentPM()->lookupOp(n2.getOperator());
- } else {
- return n1 == n2.getOperator();
- }
- }
- if(n2.getType().isFunction() && n1.hasOperator()) {
- if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
- return n2 == ProofManager::currentPM()->lookupOp(n1.getOperator());
- } else {
- return n2 == n1.getOperator();
- }
- }
- if(n1.hasOperator() && n2.hasOperator() && n1.getOperator() != n2.getOperator()) {
- return false;
- }
- for(size_t i = 0; i < n1.getNumChildren() && i < n2.getNumChildren(); ++i) {
- if(n1[i] != n2[i]) {
- return false;
- }
- }
- return true;
-}
-
-void ProofArith::toStream(std::ostream& out) const
-{
- Trace("theory-proof-debug") << "; Print Arith proof..." << std::endl;
- //AJR : carry this further?
- ProofLetMap map;
- toStreamLFSC(out, ProofManager::getArithProof(), *d_proof, map);
-}
-
-void ProofArith::toStreamLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map)
-{
- Debug("lfsc-arith") << "Printing arith proof in LFSC : " << std::endl;
- pf.debug_print("lfsc-arith");
- Debug("lfsc-arith") << std::endl;
- toStreamRecLFSC(out, tp, pf, 0, map);
-}
-
-Node ProofArith::toStreamRecLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- unsigned tb,
- const ProofLetMap& map)
-{
- Debug("pf::arith") << std::endl
- << std::endl
- << "toStreamRecLFSC called. tb = " << tb
- << " . proof:" << std::endl;
- pf.debug_print("pf::arith");
- Debug("pf::arith") << std::endl;
-
- if(tb == 0) {
- Assert(pf.d_id == theory::eq::MERGED_THROUGH_TRANS);
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.size() >= 2);
-
- int neg = -1;
- std::shared_ptr<theory::eq::EqProof> subTrans =
- std::make_shared<theory::eq::EqProof>();
- subTrans->d_id = theory::eq::MERGED_THROUGH_TRANS;
- subTrans->d_node = pf.d_node;
-
- size_t i = 0;
- while (i < pf.d_children.size()) {
- // Look for the negative clause, with which we will form a contradiction.
- if(!pf.d_children[i]->d_node.isNull() && pf.d_children[i]->d_node.getKind() == kind::NOT) {
- Assert(neg < 0);
- neg = i;
- ++i;
- }
-
- // Handle congruence closures over equalities.
- else if (pf.d_children[i]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE && pf.d_children[i]->d_node.isNull()) {
- Debug("pf::arith") << "Handling congruence over equalities" << std::endl;
-
- // Gather the sequence of consecutive congruence closures.
- std::vector<std::shared_ptr<const theory::eq::EqProof>> congruenceClosures;
- unsigned count;
- Debug("pf::arith") << "Collecting congruence sequence" << std::endl;
- for (count = 0;
- i + count < pf.d_children.size() &&
- pf.d_children[i + count]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE &&
- pf.d_children[i + count]->d_node.isNull();
- ++count) {
- Debug("pf::arith") << "Found a congruence: " << std::endl;
- pf.d_children[i+count]->debug_print("pf::arith");
- congruenceClosures.push_back(pf.d_children[i+count]);
- }
-
- Debug("pf::arith") << "Total number of congruences found: " << congruenceClosures.size() << std::endl;
-
- // Determine if the "target" of the congruence sequence appears right before or right after the sequence.
- bool targetAppearsBefore = true;
- bool targetAppearsAfter = true;
-
- if ((i == 0) || (i == 1 && neg == 0)) {
- Debug("pf::arith") << "Target does not appear before" << std::endl;
- targetAppearsBefore = false;
- }
-
- if ((i + count >= pf.d_children.size()) ||
- (!pf.d_children[i + count]->d_node.isNull() &&
- pf.d_children[i + count]->d_node.getKind() == kind::NOT)) {
- Debug("pf::arith") << "Target does not appear after" << std::endl;
- targetAppearsAfter = false;
- }
-
- // Assert that we have precisely one target clause.
- Assert(targetAppearsBefore != targetAppearsAfter);
-
- // Begin breaking up the congruences and ordering the equalities correctly.
- std::vector<std::shared_ptr<theory::eq::EqProof>> orderedEqualities;
-
-
- // Insert target clause first.
- if (targetAppearsBefore) {
- orderedEqualities.push_back(pf.d_children[i - 1]);
- // The target has already been added to subTrans; remove it.
- subTrans->d_children.pop_back();
- } else {
- orderedEqualities.push_back(pf.d_children[i + count]);
- }
-
- // Start with the congruence closure closest to the target clause, and work our way back/forward.
- if (targetAppearsBefore) {
- for (unsigned j = 0; j < count; ++j) {
- if (pf.d_children[i + j]->d_children[0]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.begin(), pf.d_children[i + j]->d_children[0]);
- if (pf.d_children[i + j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.end(), pf.d_children[i + j]->d_children[1]);
- }
- } else {
- for (unsigned j = 0; j < count; ++j) {
- if (pf.d_children[i + count - 1 - j]->d_children[0]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.begin(), pf.d_children[i + count - 1 - j]->d_children[0]);
- if (pf.d_children[i + count - 1 - j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.end(), pf.d_children[i + count - 1 - j]->d_children[1]);
- }
- }
-
- // Copy the result into the main transitivity proof.
- subTrans->d_children.insert(subTrans->d_children.end(), orderedEqualities.begin(), orderedEqualities.end());
-
- // Increase i to skip over the children that have been processed.
- i += count;
- if (targetAppearsAfter) {
- ++i;
- }
- }
-
- // Else, just copy the child proof as is
- else {
- subTrans->d_children.push_back(pf.d_children[i]);
- ++i;
- }
- }
- Assert(neg >= 0);
-
- Node n1;
- std::stringstream ss;
- //Assert(subTrans->d_children.size() == pf.d_children.size() - 1);
- Debug("pf::arith") << "\nsubtrans has " << subTrans->d_children.size() << " children\n";
- if(pf.d_children.size() > 2) {
- n1 = toStreamRecLFSC(ss, tp, *subTrans, 1, map);
- } else {
- n1 = toStreamRecLFSC(ss, tp, *(subTrans->d_children[0]), 1, map);
- Debug("pf::arith") << "\nsubTrans unique child " << subTrans->d_children[0]->d_id << " was proven\ngot: " << n1 << std::endl;
- }
-
- Node n2 = pf.d_children[neg]->d_node;
- Assert(n2.getKind() == kind::NOT);
- out << "(clausify_false (contra _ ";
- Debug("pf::arith") << "\nhave proven: " << n1 << std::endl;
- Debug("pf::arith") << "n2 is " << n2[0] << std::endl;
-
- if (n2[0].getNumChildren() > 0) { Debug("pf::arith") << "\nn2[0]: " << n2[0][0] << std::endl; }
- if (n1.getNumChildren() > 1) { Debug("pf::arith") << "n1[1]: " << n1[1] << std::endl; }
-
- if(n2[0].getKind() == kind::APPLY_UF) {
- out << "(trans _ _ _ _ ";
- out << "(symm _ _ _ ";
- out << ss.str();
- out << ") (pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl;
- } else {
- Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1])
- || (n1[1] == n2[0][0] && n1[0] == n2[0][1]));
- if(n1[1] == n2[0][0]) {
- out << "(symm _ _ _ " << ss.str() << ")";
- } else {
- out << ss.str();
- }
- out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl;
- }
- return Node();
- }
-
- switch(pf.d_id) {
- case theory::eq::MERGED_THROUGH_CONGRUENCE: {
- Debug("pf::arith") << "\nok, looking at congruence:\n";
- pf.debug_print("pf::arith");
- std::stack<const theory::eq::EqProof*> stk;
- for (const theory::eq::EqProof* pf2 = &pf;
- pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE;
- pf2 = pf2->d_children[0].get()) {
- Assert(!pf2->d_node.isNull());
- Assert(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF
- || pf2->d_node.getKind() == kind::BUILTIN
- || pf2->d_node.getKind() == kind::APPLY_UF
- || pf2->d_node.getKind() == kind::SELECT
- || pf2->d_node.getKind() == kind::STORE);
- Assert(pf2->d_children.size() == 2);
- out << "(cong _ _ _ _ _ _ ";
- stk.push(pf2);
- }
- Assert(stk.top()->d_children[0]->d_id
- != theory::eq::MERGED_THROUGH_CONGRUENCE);
- NodeBuilder<> b1(kind::PARTIAL_APPLY_UF), b2(kind::PARTIAL_APPLY_UF);
- const theory::eq::EqProof* pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- Node n1 = toStreamRecLFSC(out, tp, *(pf2->d_children[0]), tb + 1, map);
- out << " ";
- std::stringstream ss;
- Node n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
- Debug("pf::arith") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n";
- pf2->debug_print("pf::arith");
- Debug("pf::arith") << "looking at " << pf2->d_node << "\n";
- Debug("pf::arith") << " " << n1 << "\n";
- Debug("pf::arith") << " " << n2 << "\n";
- int side = 0;
- if(match(pf2->d_node, n1[0])) {
- //if(tb == 1) {
- Debug("pf::arith") << "SIDE IS 0\n";
- //}
- side = 0;
- } else {
- //if(tb == 1) {
- Debug("pf::arith") << "SIDE IS 1\n";
- //}
- if(!match(pf2->d_node, n1[1])) {
- Debug("pf::arith") << "IN BAD CASE, our first subproof is\n";
- pf2->d_children[0]->debug_print("pf::arith");
- }
- Assert(match(pf2->d_node, n1[1]));
- side = 1;
- }
- if(n1[side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::PARTIAL_APPLY_UF || n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::STORE) {
- if(n1[side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::PARTIAL_APPLY_UF) {
- b1 << n1[side].getOperator();
- } else {
- b1 << ProofManager::currentPM()->mkOp(n1[side].getOperator());
- }
- b1.append(n1[side].begin(), n1[side].end());
- } else {
- b1 << n1[side];
- }
- if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || n1[1-side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::STORE) {
- if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || n1[1-side].getKind() == kind::APPLY_UF) {
- b2 << n1[1-side].getOperator();
- } else {
- b2 << ProofManager::currentPM()->mkOp(n1[1-side].getOperator());
- }
- b2.append(n1[1-side].begin(), n1[1-side].end());
- } else {
- b2 << n1[1-side];
- }
- Debug("pf::arith") << "pf2->d_node " << pf2->d_node << std::endl;
- Debug("pf::arith") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl;
- Debug("pf::arith") << "n1 " << n1 << std::endl;
- Debug("pf::arith") << "n2 " << n2 << std::endl;
- Debug("pf::arith") << "side " << side << std::endl;
- if(pf2->d_node[b1.getNumChildren() - (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(pf2->d_node[b1.getNumChildren()
- - (pf2->d_node.getMetaKind()
- == kind::metakind::PARAMETERIZED
- ? 0
- : 1)]
- == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
- out << ")";
- while(!stk.empty()) {
- if(tb == 1) {
- Debug("pf::arith") << "\nMORE TO DO\n";
- }
- pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- out << " ";
- ss.str("");
- n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
- Debug("pf::arith") << "\nok, in cong[" << stk.size() << "]" << "\n";
- Debug("pf::arith") << "looking at " << pf2->d_node << "\n";
- Debug("pf::arith") << " " << n1 << "\n";
- Debug("pf::arith") << " " << n2 << "\n";
- Debug("pf::arith") << " " << b1 << "\n";
- Debug("pf::arith") << " " << b2 << "\n";
- if(pf2->d_node[b1.getNumChildren()] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(pf2->d_node[b1.getNumChildren()] == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
- out << ")";
- }
- n1 = b1;
- n2 = b2;
- Debug("pf::arith") << "at end assert, got " << pf2->d_node << " and " << n1 << std::endl;
- if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
- if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
- b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b1.clear(kind::APPLY_UF);
- b1 << n1.getOperator();
- }
- b1.append(n1.begin(), n1.end());
- n1 = b1;
- Debug("pf::arith") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl;
- if(pf2->d_node.getKind() == kind::APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
- }
- if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
- b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b2.clear(kind::APPLY_UF);
- b2 << n2.getOperator();
- }
- b2.append(n2.begin(), n2.end());
- n2 = b2;
- }
- Node n = (side == 0 ? eqNode(n1, n2) : eqNode(n2, n1));
- if(tb == 1) {
- Debug("pf::arith") << "\ncong proved: " << n << "\n";
- }
- return n;
- }
-
- case theory::eq::MERGED_THROUGH_REFLEXIVITY:
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- out << "(refl _ ";
- tp->printTerm(NodeManager::currentNM()->toExpr(pf.d_node), out, map);
- out << ")";
- return eqNode(pf.d_node, pf.d_node);
-
- case theory::eq::MERGED_THROUGH_EQUALITY:
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- out << ProofManager::getLitName(pf.d_node.negate());
- return pf.d_node;
-
- case theory::eq::MERGED_THROUGH_TRANS: {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.size() >= 2);
- std::stringstream ss;
- Debug("pf::arith") << "\ndoing trans proof[[\n";
- pf.debug_print("pf::arith");
- Debug("pf::arith") << "\n";
- Node n1 = toStreamRecLFSC(ss, tp, *(pf.d_children[0]), tb + 1, map);
- Debug("pf::arith") << "\ndoing trans proof, got n1 " << n1 << "\n";
- if(tb == 1) {
- Debug("pf::arith") << "\ntrans proof[0], got n1 " << n1 << "\n";
- }
-
- bool identicalEqualities = false;
- bool evenLengthSequence;
- Node nodeAfterEqualitySequence;
-
- std::map<size_t, Node> childToStream;
-
- for(size_t i = 1; i < pf.d_children.size(); ++i) {
- std::stringstream ss1(ss.str()), ss2;
- ss.str("");
-
- // It is possible that we've already converted the i'th child to stream. If so,
- // use previously stored result. Otherwise, convert and store.
- Node n2;
- if (childToStream.find(i) != childToStream.end())
- n2 = childToStream[i];
- else {
- n2 = toStreamRecLFSC(ss2, tp, *(pf.d_children[i]), tb + 1, map);
- childToStream[i] = n2;
- }
-
- // The following branch is dedicated to handling sequences of identical equalities,
- // i.e. trans[ a=b, a=b, a=b ].
- //
- // There are two cases:
- // 1. The number of equalities is odd. Then, the sequence can be collapsed to just one equality,
- // i.e. a=b.
- // 2. The number of equalities is even. Now, we have two options: a=a or b=b. To determine this,
- // we look at the node after the equality sequence. If it needs a, we go for a=a; and if it needs
- // b, we go for b=b. If there is no following node, we look at the goal of the transitivity proof,
- // and use it to determine which option we need.
- if(n2.getKind() == kind::EQUAL) {
- if (((n1[0] == n2[0]) && (n1[1] == n2[1])) || ((n1[0] == n2[1]) && (n1[1] == n2[0]))) {
- // We are in a sequence of identical equalities
-
- Debug("pf::arith") << "Detected identical equalities: " << std::endl << "\t" << n1 << std::endl;
-
- if (!identicalEqualities) {
- // The sequence of identical equalities has started just now
- identicalEqualities = true;
-
- Debug("pf::arith") << "The sequence is just beginning. Determining length..." << std::endl;
-
- // Determine whether the length of this sequence is odd or even.
- evenLengthSequence = true;
- bool sequenceOver = false;
- size_t j = i + 1;
-
- while (j < pf.d_children.size() && !sequenceOver) {
- std::stringstream dontCare;
- nodeAfterEqualitySequence = toStreamRecLFSC(
- dontCare, tp, *(pf.d_children[j]), tb + 1, map);
-
- if (((nodeAfterEqualitySequence[0] == n1[0]) && (nodeAfterEqualitySequence[1] == n1[1])) ||
- ((nodeAfterEqualitySequence[0] == n1[1]) && (nodeAfterEqualitySequence[1] == n1[0]))) {
- evenLengthSequence = !evenLengthSequence;
- } else {
- sequenceOver = true;
- }
-
- ++j;
- }
-
- if (evenLengthSequence) {
- // If the length is even, we need to apply transitivity for the "correct" hand of the equality.
-
- Debug("pf::arith") << "Equality sequence of even length" << std::endl;
- Debug("pf::arith") << "n1 is: " << n1 << std::endl;
- Debug("pf::arith") << "n2 is: " << n2 << std::endl;
- Debug("pf::arith") << "pf-d_node is: " << pf.d_node << std::endl;
- Debug("pf::arith") << "Next node is: " << nodeAfterEqualitySequence << std::endl;
-
- ss << "(trans _ _ _ _ ";
-
- // If the sequence is at the very end of the transitivity proof, use pf.d_node to guide us.
- if (!sequenceOver) {
- if (match(n1[0], pf.d_node[0])) {
- n1 = eqNode(n1[0], n1[0]);
- ss << ss1.str() << " (symm _ _ _ " << ss1.str() << ")";
- } else if (match(n1[1], pf.d_node[1])) {
- n1 = eqNode(n1[1], n1[1]);
- ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str();
- } else {
- Debug("pf::arith") << "Error: identical equalities over, but hands don't match what we're proving."
- << std::endl;
- Assert(false);
- }
- } else {
- // We have a "next node". Use it to guide us.
-
- Assert(nodeAfterEqualitySequence.getKind() == kind::EQUAL);
-
- if ((n1[0] == nodeAfterEqualitySequence[0]) || (n1[0] == nodeAfterEqualitySequence[1])) {
-
- // Eliminate n1[1]
- ss << ss1.str() << " (symm _ _ _ " << ss1.str() << ")";
- n1 = eqNode(n1[0], n1[0]);
-
- } else if ((n1[1] == nodeAfterEqualitySequence[0]) || (n1[1] == nodeAfterEqualitySequence[1])) {
-
- // Eliminate n1[0]
- ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str();
- n1 = eqNode(n1[1], n1[1]);
-
- } else {
- Debug("pf::arith") << "Error: even length sequence, but I don't know which hand to keep!" << std::endl;
- Assert(false);
- }
- }
-
- ss << ")";
-
- } else {
- Debug("pf::arith") << "Equality sequence length is odd!" << std::endl;
- ss.str(ss1.str());
- }
-
- Debug("pf::arith") << "Have proven: " << n1 << std::endl;
- } else {
- ss.str(ss1.str());
- }
-
- // Ignore the redundancy.
- continue;
- }
- }
-
- if (identicalEqualities) {
- // We were in a sequence of identical equalities, but it has now ended. Resume normal operation.
- identicalEqualities = false;
- }
-
- Debug("pf::arith") << "\ndoing trans proof, got n2 " << n2 << "\n";
- if(tb == 1) {
- Debug("pf::arith") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n";
- Debug("pf::arith") << (n2.getKind() == kind::EQUAL) << "\n";
-
- if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2)) {
- Debug("pf::arith") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n";
- Debug("pf::arith") << n1[0].getId() << " " << n1[0] << "\n";
- Debug("pf::arith") << n1[1].getId() << " " << n1[1] << "\n";
- Debug("pf::arith") << n2[0].getId() << " " << n2[0] << "\n";
- Debug("pf::arith") << n2[1].getId() << " " << n2[1] << "\n";
- Debug("pf::arith") << (n1[0] == n2[0]) << "\n";
- Debug("pf::arith") << (n1[1] == n2[1]) << "\n";
- Debug("pf::arith") << (n1[0] == n2[1]) << "\n";
- Debug("pf::arith") << (n1[1] == n2[0]) << "\n";
- }
- }
- ss << "(trans _ _ _ _ ";
-
- if((n2.getKind() == kind::EQUAL) && (n1.getKind() == kind::EQUAL))
- // Both elements of the transitivity rule are equalities/iffs
- {
- if(n1[0] == n2[0]) {
- if(tb == 1) { Debug("pf::arith") << "case 1\n"; }
- n1 = eqNode(n1[1], n2[1]);
- ss << "(symm _ _ _ " << ss1.str() << ") " << ss2.str();
- } else if(n1[1] == n2[1]) {
- if(tb == 1) { Debug("pf::arith") << "case 2\n"; }
- n1 = eqNode(n1[0], n2[0]);
- ss << ss1.str() << " (symm _ _ _ " << ss2.str() << ")";
- } else if(n1[0] == n2[1]) {
- if(tb == 1) { Debug("pf::arith") << "case 3\n"; }
- n1 = eqNode(n2[0], n1[1]);
- ss << ss2.str() << " " << ss1.str();
- if(tb == 1) { Debug("pf::arith") << "++ proved " << n1 << "\n"; }
- } else if(n1[1] == n2[0]) {
- if(tb == 1) { Debug("pf::arith") << "case 4\n"; }
- n1 = eqNode(n1[0], n2[1]);
- ss << ss1.str() << " " << ss2.str();
- } else {
- Warning() << "\n\ntrans proof failure at step " << i << "\n\n";
- Warning() << "0 proves " << n1 << "\n";
- Warning() << "1 proves " << n2 << "\n\n";
- pf.debug_print("pf::arith",0);
- //toStreamRec(Warning.getStream(), pf, 0);
- Warning() << "\n\n";
- Unreachable();
- }
- Debug("pf::arith") << "++ trans proof[" << i << "], now have " << n1 << std::endl;
- } else if(n1.getKind() == kind::EQUAL) {
- // n1 is an equality/iff, but n2 is a predicate
- if(n1[0] == n2) {
- n1 = n1[1];
- ss << "(symm _ _ _ " << ss1.str() << ") (pred_eq_t _ " << ss2.str() << ")";
- } else if(n1[1] == n2) {
- n1 = n1[0];
- ss << ss1.str() << " (pred_eq_t _ " << ss2.str() << ")";
- } else {
- Unreachable();
- }
- } else if(n2.getKind() == kind::EQUAL) {
- // n2 is an equality/iff, but n1 is a predicate
- if(n2[0] == n1) {
- n1 = n2[1];
- ss << "(symm _ _ _ " << ss2.str() << ") (pred_eq_t _ " << ss1.str() << ")";
- } else if(n2[1] == n1) {
- n1 = n2[0];
- ss << ss2.str() << " (pred_eq_t _ " << ss1.str() << ")";
- } else {
- Unreachable();
- }
- } else {
- // Both n1 and n2 are prediacates. Don't know what to do...
- Unreachable();
- }
-
- ss << ")";
- }
- out << ss.str();
- Debug("pf::arith") << "\n++ trans proof done, have proven " << n1 << std::endl;
- return n1;
- }
-
- default:
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- Debug("pf::arith") << "theory proof: " << pf.d_node << " by rule " << int(pf.d_id) << std::endl;
- AlwaysAssert(false);
- return pf.d_node;
- }
-}
-
-ArithProof::ArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* pe)
- : TheoryProof(arith, pe), d_recorder()
-{
- arith->setProofRecorder(&d_recorder);
-}
-
-theory::TheoryId ArithProof::getTheoryId() { return theory::THEORY_ARITH; }
-void ArithProof::registerTerm(Expr term) {
- Debug("pf::arith") << "Arith register term: " << term << ". Kind: " << term.getKind()
- << ". Type: " << term.getType() << std::endl;
-
- if (term.getType().isReal() && !term.getType().isInteger()) {
- Debug("pf::arith") << "Entering real mode" << std::endl;
- }
-
- if (term.isVariable() && !ProofManager::getSkolemizationManager()->isSkolem(term)) {
- d_declarations.insert(term);
- }
-
- // recursively declare all other terms
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- // could belong to other theories
- d_proofEngine->registerTerm(term[i]);
- }
-}
-
-void LFSCArithProof::printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Debug("pf::arith") << "Arith print term: " << term << ". Kind: " << term.getKind()
- << ". Type: " << term.getType()
- << ". Number of children: " << term.getNumChildren() << std::endl;
-
- // !d_realMode <--> term.getType().isInteger()
-
- Assert (theory::Theory::theoryOf(term) == theory::THEORY_ARITH);
- std::ostringstream closing;
- if (!expectedType.isNull() && !expectedType.isInteger() && term.getType().isInteger()) {
- os << "(term_int_to_real ";
- closing << ")";
- }
- switch (term.getKind())
- {
- 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);
-
- os << (term.getType().isInteger() ? "(a_int " : "(a_real ");
- closing << ") ";
-
- if (neg)
- {
- os << "(~ ";
- closing << ")";
- }
-
- if (term.getType().isInteger())
- {
- os << r.abs();
- }
- else
- {
- printRational(os, r.abs());
- }
-
- break;
- }
-
- case kind::PLUS:
- case kind::MINUS:
- case kind::MULT:
- case kind::DIVISION:
- case kind::DIVISION_TOTAL:
- {
- Assert(term.getNumChildren() >= 1);
- TypeNode ty = Node::fromExpr(term).getType();
-
- std::string lfscFunction = getLfscFunction(term);
- for (unsigned i = 0; i < term.getNumChildren() - 1; ++i)
- {
- os << "(" << lfscFunction << " ";
- closing << ")";
- d_proofEngine->printBoundTerm(term[i], os, map, ty);
- os << " ";
- }
-
- d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map, ty);
- break;
- }
-
- case kind::UMINUS:
- {
- Assert(term.getNumChildren() == 1);
- os << "(" << getLfscFunction(term) << " ";
- closing << ")";
- d_proofEngine->printBoundTerm(term[0], os, map, Node::fromExpr(term).getType());
- break;
- }
-
- case kind::GT:
- case kind::GEQ:
- case kind::LT:
- case kind::LEQ:
- {
- Assert(term.getNumChildren() == 2);
- Assert(term.getType().isBoolean());
-
- std::string lfscFunction = getLfscFunction(term);
- TypeNode realType = NodeManager::currentNM()->realType();
-
- os << "(" << lfscFunction << " ";
- closing << ")";
-
- d_proofEngine->printBoundTerm(term[0], os, map);
- os << " ";
- d_proofEngine->printBoundTerm(term[1], os, map, realType);
- break;
- }
- case kind::EQUAL:
- {
- Assert(term.getType().isBoolean());
- Assert(term.getNumChildren() == 2);
-
- TypeNode eqType = equalityType(term[0], term[1]);
-
- os << "(= " << eqType << " ";
- closing << ")";
-
- d_proofEngine->printBoundTerm(term[0], os, map, eqType);
- d_proofEngine->printBoundTerm(term[1], os, map, eqType);
- break;
- }
-
- case kind::VARIABLE:
- case kind::SKOLEM:
- os << CVC4_ARITH_VAR_TERM_PREFIX << ProofManager::sanitize(term);
- break;
-
- default:
- Debug("pf::arith") << "Default printing of term: " << term << std::endl;
- os << term;
- break;
- }
- os << closing.str();
-}
-
-void LFSCArithProof::printOwnedSort(Type type, std::ostream& os) {
- Debug("pf::arith") << "Arith print sort: " << type << std::endl;
- os << type;
-}
-
-std::string LFSCArithProof::getLfscFunction(const Node & n) {
- Assert(n.getType().isInteger() || n.getType().isReal() || n.getType().isBoolean());
- std::string opString;
- switch (n.getKind()) {
- case kind::UMINUS:
- opString = "u-_";
- break;
- case kind::PLUS:
- opString = "+_";
- break;
- case kind::MINUS:
- opString = "-_";
- break;
- case kind::MULT:
- opString = "*_";
- break;
- case kind::DIVISION:
- case kind::DIVISION_TOTAL:
- opString = "/_";
- break;
- case kind::GT:
- opString = ">_";
- break;
- case kind::GEQ:
- opString = ">=_";
- break;
- case kind::LT:
- opString = "<_";
- break;
- case kind::LEQ:
- opString = "<=_";
- break;
- default:
- Unreachable() << "Tried to get the operator for a non-operator kind: " << n.getKind();
- }
- std::string typeString;
- if (n.getType().isInteger()) {
- typeString = "Int";
- } else if (n.getType().isReal()) {
- typeString = "Real";
- } else { // Boolean
- if (n[0].getType().isInteger()) {
- typeString = "IntReal";
- } else {
- typeString = "Real";
- }
- }
- return opString + typeString;
-}
-
-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::printInteger(std::ostream& o, const Integer& i)
-{
- if (i.sgn() < 0)
- {
- o << "(~ " << i.abs() << ")";
- }
- else
- {
- o << i;
- }
-}
-
-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 (is_aff_+ _ _ _ _ _ ";
- }
- 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:
- Unreachable() << "Invalid operation " << n.getKind()
- << " in linear polynomial";
- break;
- }
-}
-
-void LFSCArithProof::printLinearMonomialNormalizer(std::ostream& o,
- const Node& n)
-{
- switch (n.getKind())
- {
- case kind::MULT: {
- Assert((n[0].getKind() == kind::CONST_RATIONAL
- && (n[1].getKind() == kind::VARIABLE
- || n[1].getKind() == kind::SKOLEM)))
- << "node " << n << " is not a linear monomial"
- << " " << n[0].getKind() << " " << n[1].getKind();
-
- o << "\n (is_aff_mul_c_L _ _ _ ";
- printConstRational(o, n[0]);
- o << " ";
- printVariableNormalizer(o, n[1]);
- o << ")";
- break;
- }
- case kind::CONST_RATIONAL:
- {
- o << "\n (is_aff_const ";
- printConstRational(o, n);
- o << ")";
- break;
- }
- case kind::VARIABLE:
- case kind::SKOLEM:
- {
- o << "\n ";
- printVariableNormalizer(o, n);
- break;
- }
- default:
- Unreachable() << "Invalid operation " << n.getKind()
- << " in linear monomial";
- 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;
- Assert(n.getKind() == kind::VARIABLE || n.getKind() == kind::SKOLEM)
- << "Invalid variable kind " << n.getKind() << " in linear monomial";
- if (n.getType().isInteger()) {
- o << "(is_aff_var_int ";
- } else if (n.getType().isReal()) {
- o << "(is_aff_var_real ";
- } else {
- Unreachable();
- }
- o << 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 << "\n (is_aff_- _ _ _ _ _ ";
- printLinearPolynomialNormalizer(o, n[0]);
- o << "\n (is_aff_const ";
- printConstRational(o, n[1]);
- o << "))";
-}
-
-std::pair<Node, std::string> LFSCArithProof::printProofAndMaybeTighten(
- const Node& bound)
-{
- const Node & nonNegBound = bound.getKind() == kind::NOT ? bound[0] : bound;
- std::ostringstream pfOfPossiblyTightenedPredicate;
- if (nonNegBound[0].getType().isInteger()) {
- switch(bound.getKind())
- {
- case kind::NOT:
- {
- // Tighten ~[i >= r] to [i < r] to [i <= {r}] to [-i >= -{r}]
- // where
- // * i is an integer
- // * r is a real
- // * {r} denotes the greatest int less than r
- // it is equivalent to (ceil(r) - 1)
- Assert(nonNegBound[1].getKind() == kind::CONST_RATIONAL);
- Rational oldBound = nonNegBound[1].getConst<Rational>();
- Integer newBound = -(oldBound.ceiling() - 1);
- // Since the arith theory rewrites bounds to be purely integral or
- // purely real, mixed bounds should not appear in proofs
- AlwaysAssert(oldBound.isIntegral()) << "Mixed int/real bound in arith proof";
- pfOfPossiblyTightenedPredicate
- << "(tighten_not_>=_IntInt"
- << " _ _ _ _ ("
- << "check_neg_of_greatest_integer_below_int ";
- printInteger(pfOfPossiblyTightenedPredicate, newBound);
- pfOfPossiblyTightenedPredicate << " ";
- printInteger(pfOfPossiblyTightenedPredicate, oldBound.ceiling());
- pfOfPossiblyTightenedPredicate << ") " << ProofManager::getLitName(bound.negate(), "") << ")";
- Node newLeft = (theory::arith::Polynomial::parsePolynomial(nonNegBound[0]) * -1).getNode();
- Node newRight = NodeManager::currentNM()->mkConst(Rational(newBound));
- Node newTerm = NodeManager::currentNM()->mkNode(kind::GEQ, newLeft, newRight);
- return std::make_pair(newTerm, pfOfPossiblyTightenedPredicate.str());
- }
- case kind::GEQ:
- {
- // Tighten [i >= r] to [i >= ceil(r)]
- // where
- // * i is an integer
- // * r is a real
- Assert(nonNegBound[1].getKind() == kind::CONST_RATIONAL);
-
- Rational oldBound = nonNegBound[1].getConst<Rational>();
- // Since the arith theory rewrites bounds to be purely integral or
- // purely real, mixed bounds should not appear in proofs
- AlwaysAssert(oldBound.isIntegral()) << "Mixed int/real bound in arith proof";
- pfOfPossiblyTightenedPredicate << ProofManager::getLitName(bound.negate(), "");
- return std::make_pair(bound, pfOfPossiblyTightenedPredicate.str());
- }
- default: Unreachable();
- }
- } else {
- return std::make_pair(bound, ProofManager::getLitName(bound.negate(), ""));
- }
- // Silence compiler warnings about missing a return.
- Unreachable();
-}
-
-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;
- if (Debug.isOn("pf::arith::printTheoryLemmaProof")) {
- Debug("pf::arith::printTheoryLemmaProof") << "Printing proof for lemma:" << std::endl;
- for (const auto & conjunct : lemma) {
- Debug("pf::arith::printTheoryLemmaProof") << " " << conjunct << std::endl;
- }
- }
- // Prefixes for the names of linearity witnesses
- const char* linearizedProofPrefix = "pf_aff";
- 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
- if (Debug.isOn("pf::arith::printTheoryLemmaProof")) {
- os << "Farkas:" << std::endl;
- for (const auto & n : *farkasCoefficients) {
- os << " " << n << std::endl;
- }
- }
-
- // Prove affine function bounds from term bounds
- os << "\n;; Farkas Proof ;;" << std::endl;
- 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 << ")";
- const std::pair<Node, std::string> tightened = printProofAndMaybeTighten(antecedent);
- switch (tightened.first.getKind())
- {
- case kind::NOT:
- {
- Assert(conflict[i][0].getKind() == kind::GEQ);
- os << "(aff_>_from_term _ _ _ _ ";
- break;
- }
- case kind::GEQ:
- {
- os << "(aff_>=_from_term _ _ _ ";
- break;
- }
- default: Unreachable();
- }
- const Node& nonNegTightened = tightened.first.getKind() == kind::NOT ? tightened.first[0] : tightened.first;
- printLinearPolynomialPredicateNormalizer(os, nonNegTightened);
- os << " (pf_reified_arith_pred _ _ " << tightened.second << "))";
- }
-
- // Now, print the proof of bottom, from affine function bounds
- os << "\n; Farkas Combination";
- os << "\n (clausify_false (bounded_aff_contra _ _";
- lemmaParen << "))";
- for (size_t i = 0; i != nAntecedents; ++i)
- {
- const Node& lit = conflict[i];
- os << "\n (bounded_aff_add _ _ _ _ _";
- os << "\n (bounded_aff_mul_c _ _ _ ";
- printRational(os, (*farkasCoefficients)[i].abs());
- os << " " << ProofManager::getLitName(lit.negate(), linearizedProofPrefix)
- << ")"
- << " ; " << lit;
- lemmaParen << ")";
- }
-
- os << "\n bounded_aff_ax_0_>=_0";
- os << lemmaParen.str(); // Close lemma proof
- }
- else
- {
- os << "\n; Arithmetic proofs which use reasoning more complex than Farkas "
- "proofs and bound tightening are currently unsupported\n"
- "(clausify_false trust)\n";
- }
-}
-
-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)
- {
- Expr term = *it;
- Assert(term.isVariable());
- bool isInt = term.getType().isInteger();
- const char * var_type = isInt ? "int_var" : "real_var";
- os << "(% " << ProofManager::sanitize(term) << " " << var_type << "\n";
- os << "(@ " << CVC4_ARITH_VAR_TERM_PREFIX << ProofManager::sanitize(term)
- << " ";
- os << "(term_" << var_type << " " << ProofManager::sanitize(term) << ")\n";
- paren << ")";
- paren << ")";
- }
-}
-
-void LFSCArithProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
- // Nothing to do here at this point.
-}
-
-void LFSCArithProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) {
- // Nothing to do here at this point.
-}
-
-bool LFSCArithProof::printsAsBool(const Node& n)
-{
- // Our boolean variables and constants print as sort Bool.
- // All complex booleans print as formulas.
- return n.getType().isBoolean() and (n.isVar() or n.isConst());
-}
-
-TypeNode LFSCArithProof::equalityType(const Expr& left, const Expr& right)
-{
- return TypeNode::fromType(!left.getType().isInteger() ? left.getType() : right.getType());
-}
-
-} /* CVC4 namespace */
diff --git a/src/proof/arith_proof.h b/src/proof/arith_proof.h
deleted file mode 100644
index 832afcae0..000000000
--- a/src/proof/arith_proof.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/********************* */
-/*! \file arith_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Guy Katz, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Arith proof
- **
- ** Arith proof
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__ARITH__PROOF_H
-#define CVC4__ARITH__PROOF_H
-
-#include <memory>
-#include <unordered_set>
-
-#include "expr/expr.h"
-#include "proof/arith_proof_recorder.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
-#include "theory/uf/equality_engine.h"
-
-namespace CVC4 {
-
-//proof object outputted by TheoryArith
-class ProofArith : public Proof {
- public:
- ProofArith(std::shared_ptr<theory::eq::EqProof> pf) : d_proof(pf) {}
- void toStream(std::ostream& out) const override;
-
- private:
- static void toStreamLFSC(std::ostream& out, TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map);
- static Node toStreamRecLFSC(std::ostream& out, TheoryProof* tp,
- const theory::eq::EqProof& pf,
- unsigned tb, const ProofLetMap& map);
- // it is simply an equality engine proof
- std::shared_ptr<theory::eq::EqProof> d_proof;
-};
-
-namespace theory {
-namespace arith {
-class TheoryArith;
-}
-}
-
-typedef std::unordered_set<Type, TypeHashFunction > TypeSet;
-
-
-class ArithProof : public TheoryProof {
-protected:
- // std::map<Expr, std::string> d_constRationalString; // all the variable/function declarations
-
- // TypeSet d_sorts; // all the uninterpreted sorts in this theory
- ExprSet d_declarations; // all the variable/function declarations
-
- /**
- * Where farkas proofs of lemmas are stored.
- */
- proof::ArithProofRecorder d_recorder;
-
- theory::TheoryId getTheoryId() override;
-
- public:
- ArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* proofEngine);
-
- void registerTerm(Expr term) override;
-};
-
-class LFSCArithProof : public ArithProof {
-public:
- LFSCArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* proofEngine)
- : ArithProof(arith, proofEngine)
- {}
- void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
- void printOwnedSort(Type type, std::ostream& os) override;
-
- /**
- * Returns the LFSC identifier for the operator of this node.
- *
- * e.g. "+_Real".
- *
- * Does not include any parens.
- *
- * Even if the operator is a comparison (e.g. >=) on integers, will not
- * return a purely `Int` predicate like ">=_Int". Instead this treats the
- * right hand side as a real.
- */
- static std::string getLfscFunction(const Node& n);
-
- /**
- * 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 an integer in LFSC format.
- * e.g. 5 or (~ 1)
- *
- * @param o ostream to print to.
- * @param i the integer to print
- */
- static void printInteger(std::ostream& o, const Integer& i);
-
- /**
- * 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,
- const ProofLetMap& map) override;
- void printSortDeclarations(std::ostream& os, std::ostream& paren) override;
- void printTermDeclarations(std::ostream& os, std::ostream& paren) override;
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
-
- /**
- * Given a node that is an arith literal (an arith comparison or negation
- * thereof), prints a proof of that literal.
- *
- * If the node represents a tightenable bound (e.g. [Int] < 3) then it prints
- * a proof of the tightening instead. (e.g. [Int] <= 2).
- *
- * @return a pair comprising:
- * * the new node (after tightening) and
- * * a string proving it.
- */
- std::pair<Node, std::string> printProofAndMaybeTighten(const Node& bound);
-
- /**
- * Return whether this node, when serialized to LFSC, has sort `Bool`. Otherwise, the sort is `formula`.
- */
- bool printsAsBool(const Node& n) override;
-
- TypeNode equalityType(const Expr& left, const Expr& right) override;
-};
-
-
-}/* CVC4 namespace */
-
-#endif /* CVC4__ARITH__PROOF_H */
diff --git a/src/proof/arith_proof_recorder.cpp b/src/proof/arith_proof_recorder.cpp
deleted file mode 100644
index 01da402c9..000000000
--- a/src/proof/arith_proof_recorder.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/********************* */
-/*! \file arith_proof_recorder.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief A class for recording the skeletons of arithmetic proofs at solve
- ** time so they can later be used during proof-production time.
- **/
-
-#include "proof/arith_proof_recorder.h"
-
-#include <algorithm>
-#include <vector>
-
-#include "base/map_util.h"
-
-namespace CVC4 {
-namespace proof {
-
-ArithProofRecorder::ArithProofRecorder() : d_lemmasToFarkasCoefficients()
-{
- // Nothing else
-}
-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, nchildren = conflict.getNumChildren(); i < nchildren; ++i)
- {
- const Node& child = conflict[i];
- // ... 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, nchildren = conflict.getNumChildren(); i < nchildren;
- ++i)
- {
- const Node& child = conflict[i];
- const Rational& r = (*farkasCoefficients)[i];
- Debug("pf::arith") << " " << std::setw(8) << r;
- Debug("pf::arith") << " " << child << std::endl;
- }
- }
-
- std::set<Node> lits;
- std::copy(
- conflict.begin(), conflict.end(), std::inserter(lits, lits.begin()));
-
- d_lemmasToFarkasCoefficients[lits] =
- std::make_pair(std::move(conflict), *farkasCoefficients);
-}
-
-bool ArithProofRecorder::hasFarkasCoefficients(
- const std::set<Node>& conflict) const
-{
- return d_lemmasToFarkasCoefficients.find(conflict)
- != d_lemmasToFarkasCoefficients.end();
-}
-
-std::pair<Node, theory::arith::RationalVectorCP>
-ArithProofRecorder::getFarkasCoefficients(const std::set<Node>& conflict) const
-{
- if (auto *p = FindOrNull(d_lemmasToFarkasCoefficients, conflict))
- {
- return std::make_pair(p->first, &p->second);
- }
- else
- {
- return std::make_pair(Node(), theory::arith::RationalVectorCPSentinel);
- }
-}
-
-} // namespace proof
-} // namespace CVC4
diff --git a/src/proof/arith_proof_recorder.h b/src/proof/arith_proof_recorder.h
deleted file mode 100644
index 0669e5d16..000000000
--- a/src/proof/arith_proof_recorder.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/********************* */
-/*! \file arith_proof_recorder.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief A class for recording the skeletons of arithmetic proofs at solve
- ** time so they can later be used during proof-production time.
- **
- ** In particular, we're interested in proving bottom from a conjunction of
- ** theory literals.
- **
- ** For now, we assume that this can be done using a Farkas combination, and if
- ** that doesn't work for some reason, then we give up and "trust" the lemma.
- ** In the future we'll build support for more sophisticated reasoning.
- **
- ** Given this scope, our task is to...
- ** for each lemma (a set of literals)
- ** save the Farkas coefficients for those literals
- ** which requires we save an ordering of the literals
- ** and a parallel ordering of Farkas coefficients.
- **
- ** Farkas proofs have the following core structure:
- ** For a list of affine bounds: c[i] dot x >= b[i]
- ** (x is a vector of variables)
- ** (c[i] is a vector of coefficients)
- ** and a list of non-negative coefficients: f[i],
- ** compute
- **
- ** sum_i{ (c[i] dot x) * f[i] } and sum_i{b[i]*f[i]}
- **
- ** and then verify that the left is actually < the right, a contradiction
- **
- ** To be clear: this code does not check Farkas proofs, it just stores the
- ** information needed to write them.
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__ARITH_PROOF_RECORDER_H
-#define CVC4__PROOF__ARITH_PROOF_RECORDER_H
-
-#include <map>
-#include <set>
-
-#include "expr/node.h"
-#include "theory/arith/constraint_forward.h"
-
-namespace CVC4 {
-namespace proof {
-
-class ArithProofRecorder
-{
- public:
- ArithProofRecorder();
-
- /**
- * @brief For a set of incompatible literals, save the Farkas coefficients
- * demonstrating their incompatibility
- *
- * @param conflict a conjunction of conflicting literals
- * @param farkasCoefficients a list of rational coefficients which the literals
- * should be multiplied by (pairwise) to produce a contradiction.
- *
- * The orders of the two vectors must agree!
- */
- void saveFarkasCoefficients(
- Node conflict, theory::arith::RationalVectorCP farkasCoefficients);
-
- /**
- * @brief Determine whether some literals have a Farkas proof of their
- * incompatibility
- *
- * @param conflict a conjunction of (putatively) conflicting literals
- *
- * @return whether or not there is actually a proof for them.
- */
- bool hasFarkasCoefficients(const std::set<Node>& conflict) const;
-
- /**
- * @brief Get the Farkas Coefficients object
- *
- * @param conflict a conjunction of conflicting literals
- * @return theory::arith::RationalVectorCP -- the Farkas coefficients
- * Node -- a conjunction of the problem literals in coefficient order
- *
- * theory::arith::RationalVectorCPSentinel if there is no entry for
- * these lits
- */
- std::pair<Node, theory::arith::RationalVectorCP> getFarkasCoefficients(
- const std::set<Node>& conflict) const;
-
- protected:
- // For each lemma, save the Farkas coefficients of that lemma
- std::map<std::set<Node>, std::pair<Node, theory::arith::RationalVector>>
- d_lemmasToFarkasCoefficients;
-};
-
-} // namespace proof
-} // namespace CVC4
-
-#endif
diff --git a/src/proof/array_proof.cpp b/src/proof/array_proof.cpp
deleted file mode 100644
index 2d42a7489..000000000
--- a/src/proof/array_proof.cpp
+++ /dev/null
@@ -1,1350 +0,0 @@
-/********************* */
-/*! \file array_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Yoni Zohar, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "proof/array_proof.h"
-
-#include <stack>
-
-#include "proof/proof_manager.h"
-#include "proof/simplify_boolean_node.h"
-#include "proof/theory_proof.h"
-#include "theory/arrays/theory_arrays.h"
-
-namespace CVC4 {
-
-namespace {
-
-class ArrayProofPrinter : public theory::eq::EqProof::PrettyPrinter {
- public:
- ArrayProofPrinter(unsigned row, unsigned row1, unsigned ext)
- : d_row(row), d_row1(row1), d_ext(ext) {}
-
- std::string printTag(unsigned tag) override;
-
- private:
- const unsigned d_row;
- const unsigned d_row1;
- const unsigned d_ext;
-}; // class ArrayProofPrinter
-
-std::string ArrayProofPrinter::printTag(unsigned tag) {
- if (tag == theory::eq::MERGED_THROUGH_CONGRUENCE) return "Congruence";
- if (tag == theory::eq::MERGED_THROUGH_EQUALITY) return "Pure Equality";
- if (tag == theory::eq::MERGED_THROUGH_REFLEXIVITY) return "Reflexivity";
- if (tag == theory::eq::MERGED_THROUGH_CONSTANTS) return "Constants";
- if (tag == theory::eq::MERGED_THROUGH_TRANS) return "Transitivity";
-
- if (tag == d_row) return "Read Over Write";
- if (tag == d_row1) return "Read Over Write (1)";
- if (tag == d_ext) return "Extensionality";
-
- std::ostringstream result;
- result << tag;
- return result.str();
-}
-
-} // namespace
-
-
-
-ProofArray::ProofArray(std::shared_ptr<theory::eq::EqProof> pf,
- unsigned row,
- unsigned row1,
- unsigned ext)
- : d_proof(pf), d_reasonRow(row), d_reasonRow1(row1), d_reasonExt(ext)
-{
-}
-
-void ProofArray::toStream(std::ostream& out) const
-{
- ProofLetMap map;
- toStream(out, map);
-}
-
-void ProofArray::toStream(std::ostream& out, const ProofLetMap& map) const
-{
- Trace("pf::array") << "; Print Array proof..." << std::endl;
- toStreamLFSC(out, ProofManager::getArrayProof(), *d_proof, map);
- Debug("pf::array") << "; Print Array proof done!" << std::endl;
-}
-
-void ProofArray::toStreamLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map) const
-{
- Debug("pf::array") << "Printing array proof in LFSC : " << std::endl;
- ArrayProofPrinter proofPrinter(d_reasonRow, d_reasonRow1, d_reasonExt);
- pf.debug_print("pf::array", 0, &proofPrinter);
- Debug("pf::array") << std::endl;
- toStreamRecLFSC(out, tp, pf, 0, map);
- Debug("pf::array") << "Printing array proof in LFSC DONE" << std::endl;
-}
-
-Node ProofArray::toStreamRecLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- unsigned tb,
- const ProofLetMap& map) const
-{
- Debug("pf::array") << std::endl
- << std::endl
- << "toStreamRecLFSC called. tb = " << tb
- << " . proof:" << std::endl;
- ArrayProofPrinter proofPrinter(d_reasonRow, d_reasonRow1, d_reasonExt);
- if(tb == 0) {
- std::shared_ptr<theory::eq::EqProof> subTrans =
- std::make_shared<theory::eq::EqProof>();
-
- int neg = tp->assertAndPrint(pf, map, subTrans, &proofPrinter);
-
- Node n1;
- std::stringstream ss, ss2;
- Debug("mgdx") << "\nsubtrans has " << subTrans->d_children.size() << " children\n";
- bool disequalityFound = (neg >= 0);
-
- if (!disequalityFound || pf.d_children.size() > 2)
- {
- n1 = toStreamRecLFSC(ss, tp, *subTrans, 1, map);
- } else {
- n1 = toStreamRecLFSC(ss, tp, *(subTrans->d_children[0]), 1, map);
- Debug("mgdx") << "\nsubTrans unique child "
- << subTrans->d_children[0]->d_id
- << " was proven\ngot: " << n1 << std::endl;
- }
-
- out << "(clausify_false (contra _ ";
- if (disequalityFound) {
- Node n2 = pf.d_children[neg]->d_node;
- Assert(n2.getKind() == kind::NOT);
- Debug("mgdx") << "\nhave proven: " << n1 << std::endl;
- Debug("mgdx") << "n2 is " << n2 << std::endl;
- Debug("mgdx") << "n2->d_id is " << pf.d_children[neg]->d_id << std::endl;
- Debug("mgdx") << "n2[0] is " << n2[0] << std::endl;
-
- if (n2[0].getNumChildren() > 0) { Debug("mgdx") << "\nn2[0]: " << n2[0][0] << std::endl; }
- if (n1.getNumChildren() > 1) { Debug("mgdx") << "n1[1]: " << n1[1] << std::endl; }
-
- if ((pf.d_children[neg]->d_id == d_reasonExt) ||
- (pf.d_children[neg]->d_id == theory::eq::MERGED_THROUGH_TRANS)) {
- // Ext case: The negative node was created by an EXT rule; e.g. it is a[k]!=b[k], due to a!=b.
- out << ss.str();
- out << " ";
- toStreamRecLFSC(ss2, tp, *pf.d_children[neg], 1, map);
- out << ss2.str();
- } else if (n2[0].getKind() == kind::APPLY_UF) {
- out << "(trans _ _ _ _ ";
- out << "(symm _ _ _ ";
- out << ss.str();
- out << ") (pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl;
- } else {
- Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1])
- || (n1[1] == n2[0][0] && n1[0] == n2[0][1]));
- if(n1[1] == n2[0][0]) {
- out << "(symm _ _ _ " << ss.str() << ")";
- } else {
- out << ss.str();
- }
- Debug("pf::array") << "ArrayProof::toStream: getLitName( " << n2[0] << " ) = " <<
- ProofManager::getLitName(n2[0]) << std::endl;
-
- out << " " << ProofManager::getLitName(n2[0]);
- }
- } else {
- Node n2 = pf.d_node;
- Assert(n2.getKind() == kind::EQUAL);
- Assert((n1[0] == n2[0] && n1[1] == n2[1])
- || (n1[1] == n2[0] && n1[0] == n2[1]));
-
- out << ss.str();
- out << " ";
- ProofManager::getTheoryProofEngine()->printConstantDisequalityProof(out,
- n1[0].toExpr(),
- n1[1].toExpr(),
- map);
- }
-
- out << "))" << std::endl;
- return Node();
- }
-
- switch (pf.d_id)
- {
- case theory::eq::MERGED_THROUGH_CONGRUENCE:
- {
- Debug("mgd") << "\nok, looking at congruence:\n";
- pf.debug_print("mgd", 0, &proofPrinter);
- std::stack<const theory::eq::EqProof*> stk;
- for (const theory::eq::EqProof* pf2 = &pf;
- pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE;
- pf2 = pf2->d_children[0].get())
- {
- Debug("mgd") << "Looking at pf2 with d_node: " << pf2->d_node
- << std::endl;
- Assert(!pf2->d_node.isNull());
- Assert(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF
- || pf2->d_node.getKind() == kind::BUILTIN
- || pf2->d_node.getKind() == kind::APPLY_UF
- || pf2->d_node.getKind() == kind::SELECT
- || pf2->d_node.getKind() == kind::PARTIAL_SELECT_0
- || pf2->d_node.getKind() == kind::PARTIAL_SELECT_1
- || pf2->d_node.getKind() == kind::STORE);
-
- Assert(pf2->d_children.size() == 2);
- out << "(cong _ _ _ _ _ _ ";
- stk.push(pf2);
- }
- Assert(stk.top()->d_children[0]->d_id
- != theory::eq::MERGED_THROUGH_CONGRUENCE);
- // NodeBuilder<> b1(kind::PARTIAL_APPLY_UF),
- // b2(kind::PARTIAL_APPLY_UF);
- NodeBuilder<> b1, b2;
-
- const theory::eq::EqProof* pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- Node n1 = toStreamRecLFSC(out, tp, *(pf2->d_children[0]), tb + 1, map);
- out << " ";
- std::stringstream ss;
- Node n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
-
- Debug("mgd") << "\nok, in FIRST cong[" << stk.size() << "]"
- << "\n";
- pf2->debug_print("mgd", 0, &proofPrinter);
- // Temp
- Debug("mgd") << "n1 is a proof for: " << pf2->d_children[0]->d_node
- << ". It is: " << n1 << std::endl;
- Debug("mgd") << "n2 is a proof for: " << pf2->d_children[1]->d_node
- << ". It is: " << n2 << std::endl;
- //
- Debug("mgd") << "looking at " << pf2->d_node << "\n";
- Debug("mgd") << " " << n1 << "\n";
- Debug("mgd") << " " << n2 << "\n";
-
- int side = 0;
- if (tp->match(pf2->d_node, n1[0]))
- {
- Debug("mgd") << "SIDE IS 0\n";
- side = 0;
- }
- else
- {
- Debug("mgd") << "SIDE IS 1\n";
- if (!tp->match(pf2->d_node, n1[1]))
- {
- Debug("mgd") << "IN BAD CASE, our first subproof is\n";
- pf2->d_children[0]->debug_print("mgd", 0, &proofPrinter);
- }
- Assert(tp->match(pf2->d_node, n1[1]));
- side = 1;
- }
-
- if (n1[side].getKind() == kind::APPLY_UF
- || n1[side].getKind() == kind::PARTIAL_APPLY_UF
- || n1[side].getKind() == kind::SELECT
- || n1[side].getKind() == kind::PARTIAL_SELECT_1
- || n1[side].getKind() == kind::STORE)
- {
- if (n1[side].getKind() == kind::APPLY_UF
- || n1[side].getKind() == kind::PARTIAL_APPLY_UF)
- {
- b1 << kind::PARTIAL_APPLY_UF;
- b1 << n1[side].getOperator();
- }
- else if (n1[side].getKind() == kind::SELECT
- || n1[side].getKind() == kind::PARTIAL_SELECT_1)
- {
- // b1 << n1[side].getKind();
- b1 << kind::SELECT;
- } else {
- b1 << kind::PARTIAL_APPLY_UF;
- b1 << ProofManager::currentPM()->mkOp(n1[side].getOperator());
- }
- b1.append(n1[side].begin(), n1[side].end());
- }
- else if (n1[side].getKind() == kind::PARTIAL_SELECT_0) {
- b1 << kind::PARTIAL_SELECT_1;
- } else {
- b1 << n1[side];
- }
-
- if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF ||
- n1[1-side].getKind() == kind::APPLY_UF ||
- n1[1-side].getKind() == kind::SELECT ||
- n1[1-side].getKind() == kind::PARTIAL_SELECT_1 ||
- n1[1-side].getKind() == kind::STORE) {
- if(n1[1-side].getKind() == kind::APPLY_UF ||
- n1[1-side].getKind() == kind::PARTIAL_APPLY_UF) {
- b2 << kind::PARTIAL_APPLY_UF;
- b2 << n1[1-side].getOperator();
- } else if (n1[1-side].getKind() == kind::SELECT || n1[1-side].getKind() == kind::PARTIAL_SELECT_1) {
- // b2 << n1[1-side].getKind();
- b2 << kind::SELECT;
- } else {
- b2 << kind::PARTIAL_APPLY_UF;
- b2 << ProofManager::currentPM()->mkOp(n1[1-side].getOperator());
- }
- b2.append(n1[1-side].begin(), n1[1-side].end());
- } else if (n1[1-side].getKind() == kind::PARTIAL_SELECT_0) {
- b2 << kind::PARTIAL_SELECT_1;
- } else {
- b2 << n1[1-side];
- }
- Debug("mgd") << "pf2->d_node " << pf2->d_node << std::endl;
- Debug("mgd") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl;
- Debug("mgd") << "n1 " << n1 << std::endl;
- Debug("mgd") << "n2 " << n2 << std::endl;
- // These debug prints can cause a problem if we're constructing a SELECT node and it doesn't have enough
- // children yet.
- // Debug("mgd") << "b1 " << b1 << std::endl;
- // Debug("mgd") << "b2 " << b2 << std::endl;
- Debug("mgd") << "side " << side << std::endl;
- Debug("mgd") << "pf2->d_node's number of children: " << pf2->d_node.getNumChildren() << std::endl;
- Debug("mgd") << "pf2->d_node's meta kind: " << pf2->d_node.getMetaKind() << std::endl;
- Debug("mgd") << "Is this meta kind considered parameterized? " << (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED) << std::endl;
-
- if(pf2->d_node[b1.getNumChildren() +
- (n1[side].getKind() == kind::PARTIAL_SELECT_0 ? 1 : 0) +
- (n1[side].getKind() == kind::PARTIAL_SELECT_1 ? 1 : 0) -
- (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(
- pf2->d_node[b1.getNumChildren()
- + (n1[side].getKind() == kind::PARTIAL_SELECT_0 ? 1 : 0)
- + (n1[side].getKind() == kind::PARTIAL_SELECT_1 ? 1 : 0)
- - (pf2->d_node.getMetaKind()
- == kind::metakind::PARAMETERIZED
- ? 0
- : 1)]
- == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
-
- Debug("mgd") << "After first insertion:" << std::endl;
- Debug("mgd") << "b1 " << b1 << std::endl;
- Debug("mgd") << "b2 " << b2 << std::endl;
-
- out << ")";
- while(!stk.empty()) {
-
- Debug("mgd") << "\nMORE TO DO\n";
-
- pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- out << " ";
- ss.str("");
- n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
-
- Debug("mgd") << "\nok, in cong[" << stk.size() << "]" << "\n";
- Debug("mgd") << "looking at " << pf2->d_node << "\n";
- Debug("mgd") << " " << n1 << "\n";
- Debug("mgd") << " " << n2 << "\n";
- Debug("mgd") << " " << b1 << "\n";
- Debug("mgd") << " " << b2 << "\n";
- if(pf2->d_node[b1.getNumChildren()] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(pf2->d_node[b1.getNumChildren()] == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
- out << ")";
- }
- n1 = b1;
- n2 = b2;
-
- Debug("mgd") << "at end assert!" << std::endl
- << "pf2->d_node = " << pf2->d_node << std::endl
- << "n1 (assigned from b1) = " << n1 << std::endl
- << "n2 (assigned from b2) = " << n2 << std::endl;
-
- if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
-
- Debug("mgd") << "n1.getOperator().getType().getNumChildren() = "
- << n1.getOperator().getType().getNumChildren() << std::endl;
- Debug("mgd") << "n1.getNumChildren() + 1 = "
- << n1.getNumChildren() + 1 << std::endl;
-
- Assert(!(
- (n1.getKind() == kind::PARTIAL_SELECT_0 && n1.getNumChildren() == 2)));
- if (n1.getKind() == kind::PARTIAL_SELECT_1 && n1.getNumChildren() == 2) {
- Debug("mgd") << "Finished a SELECT. Updating.." << std::endl;
- b1.clear(kind::SELECT);
- b1.append(n1.begin(), n1.end());
- n1 = b1;
- Debug("mgd") << "New n1: " << n1 << std::endl;
- } else if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
- b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b1.clear(kind::APPLY_UF);
- b1 << n1.getOperator();
- }
- b1.append(n1.begin(), n1.end());
- n1 = b1;
- Debug("mgd") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl;
- if(pf2->d_node.getKind() == kind::APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
- }
-
- Debug("mgd") << "n2.getOperator().getType().getNumChildren() = "
- << n2.getOperator().getType().getNumChildren() << std::endl;
- Debug("mgd") << "n2.getNumChildren() + 1 = "
- << n2.getNumChildren() + 1 << std::endl;
-
- Assert(!(
- (n2.getKind() == kind::PARTIAL_SELECT_0 && n2.getNumChildren() == 2)));
- if (n2.getKind() == kind::PARTIAL_SELECT_1 && n2.getNumChildren() == 2) {
- Debug("mgd") << "Finished a SELECT. Updating.." << std::endl;
- b2.clear(kind::SELECT);
- b2.append(n2.begin(), n2.end());
- n2 = b2;
- Debug("mgd") << "New n2: " << n2 << std::endl;
- } else if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
- b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b2.clear(kind::APPLY_UF);
- b2 << n2.getOperator();
- }
- b2.append(n2.begin(), n2.end());
- n2 = b2;
- }
- Node n = (side == 0 ? n1.eqNode(n2) : n2.eqNode(n1));
-
- Debug("mgdx") << "\ncong proved: " << n << "\n";
- return n;
- }
- case theory::eq::MERGED_THROUGH_REFLEXIVITY:
- {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- out << "(refl _ ";
- tp->printTerm(NodeManager::currentNM()->toExpr(pf.d_node), out, map);
- out << ")";
- return pf.d_node.eqNode(pf.d_node);
- }
- case theory::eq::MERGED_THROUGH_EQUALITY:
- {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- Debug("pf::array") << "ArrayProof::toStream: getLitName( " << pf.d_node.negate() << " ) = " <<
- ProofManager::getLitName(pf.d_node.negate()) << std::endl;
- out << ProofManager::getLitName(pf.d_node.negate());
- return pf.d_node;
- }
-
- case theory::eq::MERGED_THROUGH_TRANS:
- {
- bool firstNeg = false;
- bool secondNeg = false;
-
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.size() >= 2);
- std::stringstream ss;
- Debug("mgd") << "\ndoing trans proof[[\n";
- pf.debug_print("mgd", 0, &proofPrinter);
- Debug("mgd") << "\n";
-
- pf.d_children[0]->d_node = simplifyBooleanNode(pf.d_children[0]->d_node);
-
- Node n1 = toStreamRecLFSC(ss, tp, *(pf.d_children[0]), tb + 1, map);
- Debug("mgd") << "\ndoing trans proof, got n1 " << n1 << "\n";
- if(tb == 1) {
- Debug("mgdx") << "\ntrans proof[0], got n1 " << n1 << "\n";
- }
-
- bool identicalEqualities = false;
- bool evenLengthSequence;
- std::stringstream dontCare;
- Node nodeAfterEqualitySequence =
- toStreamRecLFSC(dontCare, tp, *(pf.d_children[0]), tb + 1, map);
-
- std::map<size_t, Node> childToStream;
-
- std::pair<Node, Node> nodePair;
- for (size_t i = 1; i < pf.d_children.size(); ++i)
- {
- std::stringstream ss1(ss.str()), ss2;
- ss.str("");
-
- // In congruences, we can have something like a[x] - it's important to
- // keep these,
- // and not turn them into (a[x]=true), because that will mess up the
- // congruence application
- // later.
-
- if (pf.d_children[i]->d_id != theory::eq::MERGED_THROUGH_CONGRUENCE)
- pf.d_children[i]->d_node =
- simplifyBooleanNode(pf.d_children[i]->d_node);
-
- // It is possible that we've already converted the i'th child to stream.
- // If so,
- // use previously stored result. Otherwise, convert and store.
- Node n2;
- if (childToStream.find(i) != childToStream.end())
- n2 = childToStream[i];
- else
- {
- n2 = toStreamRecLFSC(ss2, tp, *(pf.d_children[i]), tb + 1, map);
- childToStream[i] = n2;
- }
-
- Debug("mgd") << "\ndoing trans proof, got (first) n2 " << n2 << "\n";
-
- // The following branch is dedicated to handling sequences of identical
- // equalities,
- // i.e. trans[ a=b, a=b, a=b ].
- //
- // There are two cases:
- // 1. The number of equalities is odd. Then, the sequence can be
- // collapsed to just one equality,
- // i.e. a=b.
- // 2. The number of equalities is even. Now, we have two options: a=a
- // or b=b. To determine this,
- // we look at the node after the equality sequence. If it needs a,
- // we go for a=a; and if it needs
- // b, we go for b=b. If there is no following node, we look at the
- // goal of the transitivity proof,
- // and use it to determine which option we need.
-
- if (n2.getKind() == kind::EQUAL)
- {
- if (((n1[0] == n2[0]) && (n1[1] == n2[1]))
- || ((n1[0] == n2[1]) && (n1[1] == n2[0])))
- {
- // We are in a sequence of identical equalities
-
- Debug("pf::array") << "Detected identical equalities: " << std::endl
- << "\t" << n1 << std::endl;
-
- if (!identicalEqualities)
- {
- // The sequence of identical equalities has started just now
- identicalEqualities = true;
-
- Debug("pf::array")
- << "The sequence is just beginning. Determining length..."
- << std::endl;
-
- // Determine whether the length of this sequence is odd or even.
- evenLengthSequence = true;
- bool sequenceOver = false;
- size_t j = i + 1;
-
- while (j < pf.d_children.size() && !sequenceOver)
- {
- std::stringstream ignore;
- nodeAfterEqualitySequence =
- toStreamRecLFSC(ignore, tp, *(pf.d_children[j]), tb + 1, map);
- if (((nodeAfterEqualitySequence[0] == n1[0])
- && (nodeAfterEqualitySequence[1] == n1[1]))
- || ((nodeAfterEqualitySequence[0] == n1[1])
- && (nodeAfterEqualitySequence[1] == n1[0])))
- {
- evenLengthSequence = !evenLengthSequence;
- }
- else
- {
- sequenceOver = true;
- }
-
- ++j;
- }
-
- nodePair =
- tp->identicalEqualitiesPrinterHelper(evenLengthSequence,
- sequenceOver,
- pf,
- map,
- ss1.str(),
- &ss,
- n1,
- nodeAfterEqualitySequence);
- n1 = nodePair.first;
- nodeAfterEqualitySequence = nodePair.second;
- }
- else
- {
- ss.str(ss1.str());
- }
-
- // Ignore the redundancy.
- continue;
- }
- }
-
- if (identicalEqualities)
- {
- // We were in a sequence of identical equalities, but it has now ended.
- // Resume normal operation.
- identicalEqualities = false;
- }
-
- Debug("mgd") << "\ndoing trans proof, got n2 " << n2 << "\n";
- if (tb == 1)
- {
- Debug("mgdx") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n";
- Debug("mgdx") << (n2.getKind() == kind::EQUAL) << "\n";
-
- if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2))
- {
- Debug("mgdx") << n1[0].getId() << " " << n1[1].getId() << " / "
- << n2[0].getId() << " " << n2[1].getId() << "\n";
- Debug("mgdx") << n1[0].getId() << " " << n1[0] << "\n";
- Debug("mgdx") << n1[1].getId() << " " << n1[1] << "\n";
- Debug("mgdx") << n2[0].getId() << " " << n2[0] << "\n";
- Debug("mgdx") << n2[1].getId() << " " << n2[1] << "\n";
- Debug("mgdx") << (n1[0] == n2[0]) << "\n";
- Debug("mgdx") << (n1[1] == n2[1]) << "\n";
- Debug("mgdx") << (n1[0] == n2[1]) << "\n";
- Debug("mgdx") << (n1[1] == n2[0]) << "\n";
- }
- }
-
- // We can hadnle one of the equalities being negative, but not both
- Assert((n1.getKind() != kind::NOT) || (n2.getKind() != kind::NOT));
-
- firstNeg = false;
- secondNeg = false;
-
- if (n1.getKind() == kind::NOT) {
- Debug("mgdx") << "n1 is negative" << std::endl;
- Debug("pf::array") << "n1 = " << n1 << ", n2 = " << n2 << std::endl;
- firstNeg = true;
- ss << "(negtrans1 _ _ _ _ ";
- n1 = n1[0];
- } else if (n2.getKind() == kind::NOT) {
- Debug("mgdx") << "n2 is negative" << std::endl;
- Debug("pf::array") << "n1 = " << n1 << ", n2 = " << n2 << std::endl;
- secondNeg = true;
- ss << "(negtrans2 _ _ _ _ ";
- n2 = n2[0];
- } else {
- ss << "(trans _ _ _ _ ";
- }
-
- if((n2.getKind() == kind::EQUAL) && (n1.getKind() == kind::EQUAL))
- // Both elements of the transitivity rule are equalities/iffs
- {
- if(n1[0] == n2[0]) {
- if(tb == 1) { Debug("mgdx") << "case 1\n"; }
- n1 = n1[1].eqNode(n2[1]);
- ss << (firstNeg ? "(negsymm _ _ _ " : "(symm _ _ _ ") << ss1.str() << ") " << ss2.str();
- } else if(n1[1] == n2[1]) {
- if(tb == 1) { Debug("mgdx") << "case 2\n"; }
- n1 = n1[0].eqNode(n2[0]);
- ss << ss1.str() << (secondNeg ? " (negsymm _ _ _ " : " (symm _ _ _ " ) << ss2.str() << ")";
- } else if(n1[0] == n2[1]) {
- if(tb == 1) { Debug("mgdx") << "case 3\n"; }
- if(!firstNeg && !secondNeg) {
- n1 = n2[0].eqNode(n1[1]);
- ss << ss2.str() << " " << ss1.str();
- } else if (firstNeg) {
- n1 = n1[1].eqNode(n2[0]);
- ss << " (negsymm _ _ _ " << ss1.str() << ") (symm _ _ _ " << ss2.str() << ")";
- } else {
- Assert(secondNeg);
- n1 = n1[1].eqNode(n2[0]);
- ss << " (symm _ _ _ " << ss1.str() << ") (negsymm _ _ _ " << ss2.str() << ")";
- }
- if(tb == 1) { Debug("mgdx") << "++ proved " << n1 << "\n"; }
- } else if(n1[1] == n2[0]) {
- if(tb == 1) { Debug("mgdx") << "case 4\n"; }
- n1 = n1[0].eqNode(n2[1]);
- ss << ss1.str() << " " << ss2.str();
- } else {
- Warning() << "\n\ntrans proof failure at step " << i << "\n\n";
- Warning() << "0 proves " << n1 << "\n";
- Warning() << "1 proves " << n2 << "\n\n";
- pf.debug_print("mgdx", 0, &proofPrinter);
- //toStreamRec(Warning.getStream(), pf, 0);
- Warning() << "\n\n";
- Unreachable();
- }
- Debug("mgd") << "++ trans proof[" << i << "], now have " << n1 << std::endl;
- } else if(n1.getKind() == kind::EQUAL) {
- // n1 is an equality/iff, but n2 is a predicate
- if(n1[0] == n2) {
- n1 = n1[1];
- ss << (firstNeg ? "(negsymm _ _ _ " : "(symm _ _ _ ")
- << ss1.str() << ") (pred_eq_t _ " << ss2.str() << ")";
- } else if(n1[1] == n2) {
- n1 = n1[0];
- ss << ss1.str() << " (pred_eq_t _ " << ss2.str() << ")";
- } else {
- Unreachable();
- }
- } else if(n2.getKind() == kind::EQUAL) {
- // n2 is an equality/iff, but n1 is a predicate
- if(n2[0] == n1) {
- n1 = n2[1];
- ss << (secondNeg ? "(negsymm _ _ _ " : "(symm _ _ _ ")
- << ss2.str() << ") (pred_eq_t _ " << ss1.str() << ")";
- } else if(n2[1] == n1) {
- n1 = n2[0];
- ss << ss2.str() << " (pred_eq_t _ " << ss1.str() << ")";
- } else {
- Unreachable();
- }
- } else {
- // Both n1 and n2 are prediacates. Don't know what to do...
- Unreachable();
- }
-
- ss << ")";
-
- if (firstNeg || secondNeg) {
- n1 = (n1.getKind() == kind::NOT) ? n1[0] : n1.notNode();
- }
- }
-
- out << ss.str();
- Debug("mgd") << "\n++ trans proof done, have proven " << n1 << std::endl;
- //return (firstNeg || secondNeg) ? n1.notNode() : n1;
- return n1;
- }
-
- case theory::eq::MERGED_THROUGH_CONSTANTS:
- {
- Debug("pf::array") << "Proof for: " << pf.d_node << std::endl;
- Assert(pf.d_node.getKind() == kind::NOT);
- Node n = pf.d_node[0];
- Assert(n.getKind() == kind::EQUAL);
- Assert(n.getNumChildren() == 2);
- Assert(n[0].isConst() && n[1].isConst());
-
- ProofManager::getTheoryProofEngine()->printConstantDisequalityProof(
- out, n[0].toExpr(), n[1].toExpr(), map);
- return pf.d_node;
- }
-
- default:
- {
- if (pf.d_id == d_reasonRow)
- {
- Debug("mgd") << "row lemma: " << pf.d_node << std::endl;
- Assert(pf.d_node.getKind() == kind::EQUAL);
-
- if (pf.d_node[1].getKind() == kind::SELECT)
- {
- // This is the case where ((a[i]:=t)[k] == a[k]), and the sub-proof
- // explains why (i != k).
- TNode t1, t2, t3, t4;
- Node ret;
- if (pf.d_node[1].getKind() == kind::SELECT
- && pf.d_node[1][0].getKind() == kind::STORE
- && pf.d_node[0].getKind() == kind::SELECT
- && pf.d_node[0][0] == pf.d_node[1][0][0]
- && pf.d_node[0][1] == pf.d_node[1][1])
- {
- t2 = pf.d_node[1][0][1];
- t3 = pf.d_node[1][1];
- t1 = pf.d_node[0][0];
- t4 = pf.d_node[1][0][2];
- ret = pf.d_node[1].eqNode(pf.d_node[0]);
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3
- << "\nt4 " << t4 << "\n";
- }
- else
- {
- Assert(pf.d_node[0].getKind() == kind::SELECT
- && pf.d_node[0][0].getKind() == kind::STORE
- && pf.d_node[1].getKind() == kind::SELECT
- && pf.d_node[1][0] == pf.d_node[0][0][0]
- && pf.d_node[1][1] == pf.d_node[0][1]);
- t2 = pf.d_node[0][0][1];
- t3 = pf.d_node[0][1];
- t1 = pf.d_node[1][0];
- t4 = pf.d_node[0][0][2];
- ret = pf.d_node;
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3
- << "\nt4 " << t4 << "\n";
- }
-
- // inner index != outer index
- // t3 is the outer index
-
- Assert(pf.d_children.size() == 1);
- std::stringstream ss;
- Node subproof =
- toStreamRecLFSC(ss, tp, *(pf.d_children[0]), tb + 1, map);
-
- out << "(row _ _ ";
- tp->printTerm(t2.toExpr(), out, map);
- out << " ";
- tp->printTerm(t3.toExpr(), out, map);
- out << " ";
- tp->printTerm(t1.toExpr(), out, map);
- out << " ";
- tp->printTerm(t4.toExpr(), out, map);
- out << " ";
-
- Debug("pf::array") << "pf.d_children[0]->d_node is: "
- << pf.d_children[0]->d_node << ". t3 is: " << t3
- << std::endl
- << "subproof is: " << subproof << std::endl;
-
- Debug("pf::array") << "Subproof is: " << ss.str() << std::endl;
-
- // The subproof needs to show that t2 != t3. This can either be a direct
- // disequality,
- // or, if (wlog) t2 is constant, it can show that t3 is equal to another
- // constant.
- if (subproof.getKind() == kind::NOT)
- {
- // The subproof is for t2 != t3 (or t3 != t2)
- if (subproof[0][1] == t3)
- {
- Debug("pf::array") << "Dont need symmetry!" << std::endl;
- out << ss.str();
- }
- else
- {
- Debug("pf::array") << "Need symmetry!" << std::endl;
- out << "(negsymm _ _ _ " << ss.str() << ")";
- }
- }
- else
- {
- // Either t2 or t3 is a constant.
- Assert(subproof.getKind() == kind::EQUAL);
- Assert(subproof[0].isConst() || subproof[1].isConst());
- Assert(t2.isConst() || t3.isConst());
- Assert(!(t2.isConst() && t3.isConst()));
-
- bool t2IsConst = t2.isConst();
- if (subproof[0].isConst())
- {
- if (t2IsConst)
- {
- // (t3 == subproof[1]) == subproof[0] != t2
- // goal is t2 != t3
- // subproof already shows constant = t3
- Assert(t3 == subproof[1]);
- out << "(negtrans _ _ _ _ ";
- tp->printConstantDisequalityProof(
- out, t2.toExpr(), subproof[0].toExpr(), map);
- out << " ";
- out << ss.str();
- out << ")";
- }
- else
- {
- Assert(t2 == subproof[1]);
- out << "(negsymm _ _ _ ";
- out << "(negtrans _ _ _ _ ";
- tp->printConstantDisequalityProof(
- out, t3.toExpr(), subproof[0].toExpr(), map);
- out << " ";
- out << ss.str();
- out << "))";
- }
- }
- else
- {
- if (t2IsConst)
- {
- // (t3 == subproof[0]) == subproof[1] != t2
- // goal is t2 != t3
- // subproof already shows constant = t3
- Assert(t3 == subproof[0]);
- out << "(negtrans _ _ _ _ ";
- tp->printConstantDisequalityProof(
- out, t2.toExpr(), subproof[1].toExpr(), map);
- out << " ";
- out << "(symm _ _ _ " << ss.str() << ")";
- out << ")";
- }
- else
- {
- Assert(t2 == subproof[0]);
- out << "(negsymm _ _ _ ";
- out << "(negtrans _ _ _ _ ";
- tp->printConstantDisequalityProof(
- out, t3.toExpr(), subproof[1].toExpr(), map);
- out << " ";
- out << "(symm _ _ _ " << ss.str() << ")";
- out << "))";
- }
- }
- }
-
- out << ")";
- return ret;
- }
- else
- {
- Debug("pf::array") << "In the case of NEGATIVE ROW" << std::endl;
-
- Debug("pf::array") << "pf.d_children[0]->d_node is: "
- << pf.d_children[0]->d_node << std::endl;
-
- // This is the case where (i == k), and the sub-proof explains why
- // ((a[i]:=t)[k] != a[k])
-
- // If we wanted to remove the need for "negativerow", we would need to
- // prove i==k using a new satlem. We would:
- // 1. Create a new satlem.
- // 2. Assume that i != k
- // 3. Apply ROW to show that ((a[i]:=t)[k] == a[k])
- // 4. Contradict this with the fact that ((a[i]:=t)[k] != a[k]),
- // obtaining our contradiction
-
- TNode t1, t2, t3, t4;
- Node ret;
-
- // pf.d_node is an equality, i==k.
- t1 = pf.d_node[0];
- t2 = pf.d_node[1];
-
- // pf.d_children[0]->d_node will have the form: (not (= (select (store
- // a_565 i7 e_566) i1) (select a_565 i1))),
- // or its symmetrical version.
-
- unsigned side;
- if (pf.d_children[0]->d_node[0][0].getKind() == kind::SELECT
- && pf.d_children[0]->d_node[0][0][0].getKind() == kind::STORE)
- {
- side = 0;
- }
- else if (pf.d_children[0]->d_node[0][1].getKind() == kind::SELECT
- && pf.d_children[0]->d_node[0][1][0].getKind() == kind::STORE)
- {
- side = 1;
- }
- else
- {
- Unreachable();
- }
-
- Debug("pf::array") << "Side is: " << side << std::endl;
-
- // The array's index and element types will come from the subproof...
- t3 = pf.d_children[0]->d_node[0][side][0][0];
- t4 = pf.d_children[0]->d_node[0][side][0][2];
- ret = pf.d_node;
-
- // The order of indices needs to match; we might have to swap t1 and t2
- // and then apply symmetry.
- bool swap = (t2 == pf.d_children[0]->d_node[0][side][0][1]);
-
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 "
- << t4 << "\n";
-
- Assert(pf.d_children.size() == 1);
- std::stringstream ss;
- Node subproof =
- toStreamRecLFSC(ss, tp, *(pf.d_children[0]), tb + 1, map);
-
- Debug("pf::array") << "Subproof is: " << ss.str() << std::endl;
-
- if (swap)
- {
- out << "(symm _ _ _ ";
- }
-
- out << "(negativerow _ _ ";
- tp->printTerm(swap ? t2.toExpr() : t1.toExpr(), out, map);
- out << " ";
- tp->printTerm(swap ? t1.toExpr() : t2.toExpr(), out, map);
- out << " ";
- tp->printTerm(t3.toExpr(), out, map);
- out << " ";
- tp->printTerm(t4.toExpr(), out, map);
- out << " ";
-
- if (side != 0)
- {
- out << "(negsymm _ _ _ " << ss.str() << ")";
- }
- else
- {
- out << ss.str();
- }
-
- out << ")";
-
- if (swap)
- {
- out << ") ";
- }
-
- return ret;
- }
- }
- else if (pf.d_id == d_reasonRow1)
- {
- Debug("mgd") << "row1 lemma: " << pf.d_node << std::endl;
- Assert(pf.d_node.getKind() == kind::EQUAL);
- TNode t1, t2, t3;
- Node ret;
- if (pf.d_node[1].getKind() == kind::SELECT
- && pf.d_node[1][0].getKind() == kind::STORE
- && pf.d_node[1][0][1] == pf.d_node[1][1]
- && pf.d_node[1][0][2] == pf.d_node[0])
- {
- t1 = pf.d_node[1][0][0];
- t2 = pf.d_node[1][0][1];
- t3 = pf.d_node[0];
- ret = pf.d_node[1].eqNode(pf.d_node[0]);
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
- }
- else
- {
- Assert(pf.d_node[0].getKind() == kind::SELECT
- && pf.d_node[0][0].getKind() == kind::STORE
- && pf.d_node[0][0][1] == pf.d_node[0][1]
- && pf.d_node[0][0][2] == pf.d_node[1]);
- t1 = pf.d_node[0][0][0];
- t2 = pf.d_node[0][0][1];
- t3 = pf.d_node[1];
- ret = pf.d_node;
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
- }
- out << "(row1 _ _ ";
- tp->printTerm(t1.toExpr(), out, map);
- out << " ";
- tp->printTerm(t2.toExpr(), out, map);
- out << " ";
- tp->printTerm(t3.toExpr(), out, map);
- out << ")";
- return ret;
- }
- else if (pf.d_id == d_reasonExt) {
- Assert(pf.d_node.getKind() == kind::NOT);
- Assert(pf.d_node[0].getKind() == kind::EQUAL);
- Assert(pf.d_children.size() == 1);
- std::shared_ptr<theory::eq::EqProof> child_proof = pf.d_children[0];
- Assert(child_proof->d_node.getKind() == kind::NOT);
- Assert(child_proof->d_node[0].getKind() == kind::EQUAL);
-
- Debug("mgd") << "EXT lemma: " << pf.d_node << std::endl;
-
- TNode t1, t2, t3;
- t1 = child_proof->d_node[0][0];
- t2 = child_proof->d_node[0][1];
- t3 = pf.d_node[0][0][1];
-
- Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
-
- out << "(or_elim_1 _ _ ";
- out << ProofManager::getLitName(child_proof->d_node[0]);
- out << " ";
- out << ProofManager::getArrayProof()->skolemToLiteral(t3.toExpr());
- out << ")";
-
- return pf.d_node;
- }
-
- else {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- Debug("mgd") << "theory proof: " << pf.d_node << " by rule " << int(pf.d_id) << std::endl;
- AlwaysAssert(false);
- return pf.d_node;
- }
-}
- }
-}
-
-ArrayProof::ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* pe)
- : TheoryProof(arrays, pe)
-{}
-
-theory::TheoryId ArrayProof::getTheoryId() { return theory::THEORY_ARRAYS; }
-void ArrayProof::registerTerm(Expr term) {
- // already registered
- if (d_declarations.find(term) != d_declarations.end())
- return;
-
- Type type = term.getType();
- if (type.isSort()) {
- // declare uninterpreted sorts
- d_sorts.insert(type);
- }
-
- if (term.getKind() == kind::APPLY_UF) {
- Expr function = term.getOperator();
- d_declarations.insert(function);
- }
-
- if (term.isVariable()) {
- d_declarations.insert(term);
- }
-
- if (term.getKind() == kind::SELECT && term.getType().isBoolean()) {
- // Ensure cnf literals
- Node asNode(term);
- ProofManager::currentPM()->ensureLiteral(
- asNode.eqNode(NodeManager::currentNM()->mkConst(true)));
- ProofManager::currentPM()->ensureLiteral(
- asNode.eqNode(NodeManager::currentNM()->mkConst(false)));
- }
-
- // recursively declare all other terms
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- // could belong to other theories
- d_proofEngine->registerTerm(term[i]);
- }
-}
-
-std::string ArrayProof::skolemToLiteral(Expr skolem) {
- Debug("pf::array") << "ArrayProof::skolemToLiteral( " << skolem << ")" << std::endl;
- Assert(d_skolemToLiteral.find(skolem) != d_skolemToLiteral.end());
- return d_skolemToLiteral[skolem];
-}
-
-void LFSCArrayProof::printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Assert(theory::Theory::theoryOf(term) == theory::THEORY_ARRAYS);
-
- if (theory::Theory::theoryOf(term) != theory::THEORY_ARRAYS) {
- // We can get here, for instance, if there's a (select ite ...), e.g. a non-array term
- // hiding as a subterm of an array term. In that case, send it back to the dispatcher.
- d_proofEngine->printBoundTerm(term, os, map);
- return;
- }
-
- if (term.getKind() == kind::VARIABLE || term.getKind() == kind::SKOLEM) {
- os << term;
- return;
- }
-
- Assert((term.getKind() == kind::SELECT)
- || (term.getKind() == kind::PARTIAL_SELECT_0)
- || (term.getKind() == kind::PARTIAL_SELECT_1)
- || (term.getKind() == kind::STORE));
-
- switch (term.getKind()) {
- case kind::SELECT: {
- Assert(term.getNumChildren() == 2);
-
- bool convertToBool = (term[1].getType().isBoolean() && !d_proofEngine->printsAsBool(term[1]));
-
- os << "(apply _ _ (apply _ _ (read ";
- printSort(ArrayType(term[0].getType()).getIndexType(), os);
- os << " ";
- printSort(ArrayType(term[0].getType()).getConstituentType(), os);
- os << ") ";
- printTerm(term[0], os, map);
- os << ") ";
- if (convertToBool) os << "(f_to_b ";
- printTerm(term[1], os, map);
- if (convertToBool) os << ")";
- os << ") ";
- return;
- }
-
- case kind::PARTIAL_SELECT_0:
- Assert(term.getNumChildren() == 1);
- os << "(read ";
- printSort(ArrayType(term[0].getType()).getIndexType(), os);
- os << " ";
- printSort(ArrayType(term[0].getType()).getConstituentType(), os);
- os << ") ";
- return;
-
- case kind::PARTIAL_SELECT_1:
- Debug("pf::array") << "This branch has not beed tested yet." << std::endl;
- Unreachable();
-
- Assert(term.getNumChildren() == 1);
- os << "(apply _ _ (read ";
- printSort(ArrayType(term[0].getType()).getIndexType(), os);
- os << " ";
- printSort(ArrayType(term[0].getType()).getConstituentType(), os);
- os << ") ";
- printTerm(term[0], os, map);
- os << ") ";
- return;
-
- case kind::STORE:
- os << "(apply _ _ (apply _ _ (apply _ _ (write ";
- printSort(ArrayType(term[0].getType()).getIndexType(), os);
- os << " ";
- printSort(ArrayType(term[0].getType()).getConstituentType(), os);
- os << ") ";
- printTerm(term[0], os, map);
- os << ") ";
- printTerm(term[1], os, map);
- os << ") ";
- printTerm(term[2], os, map);
- os << ") ";
- return;
-
- default:
- Unreachable();
- return;
- }
-}
-
-void LFSCArrayProof::printOwnedSort(Type type, std::ostream& os) {
- Debug("pf::array") << std::endl << "(pf::array) LFSCArrayProof::printOwnedSort: type is: " << type << std::endl;
- Assert(type.isArray() || type.isSort());
- if (type.isArray()){
- ArrayType array_type(type);
-
- Debug("pf::array") << "LFSCArrayProof::printOwnedSort: type is an array. Index type: "
- << array_type.getIndexType()
- << ", element type: " << array_type.getConstituentType() << std::endl;
-
- os << "(Array ";
- printSort(array_type.getIndexType(), os);
- os << " ";
- printSort(array_type.getConstituentType(), os);
- os << ")";
- } else {
- os << type;
- }
-}
-
-void LFSCArrayProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map) {
- os << " ;; Array Theory Lemma \n;;";
- for (unsigned i = 0; i < lemma.size(); ++i) {
- os << lemma[i] <<" ";
- }
- os <<"\n";
- //os << " (clausify_false trust)";
- ArrayProof::printTheoryLemmaProof(lemma, os, paren, map);
-}
-
-void LFSCArrayProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
- // declaring the sorts
- for (TypeSet::const_iterator it = d_sorts.begin(); it != d_sorts.end(); ++it) {
- if (!ProofManager::currentPM()->wasPrinted(*it)) {
- os << "(% " << *it << " sort\n";
- paren << ")";
- ProofManager::currentPM()->markPrinted(*it);
- }
- }
-}
-
-void LFSCArrayProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
- Debug("pf::array") << "Arrays declaring terms..." << std::endl;
-
- for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
- Expr term = *it;
-
- Assert(term.getType().isArray() || term.isVariable());
-
- Debug("pf::array") << "LFSCArrayProof::printDeclarations: term is: " << term
- << ". It's type is: " << term.getType()
- << std::endl;
-
- if (term.getType().isArray()){
- ArrayType array_type(term.getType());
-
- Debug("pf::array") << "LFSCArrayProof::printDeclarations: term is an array. Index type: "
- << array_type.getIndexType()
- << ", element type: " << array_type.getConstituentType() << std::endl;
-
- os << "(% " << ProofManager::sanitize(term) << " ";
- os << "(term ";
- os << "(Array ";
-
- printSort(array_type.getIndexType(), os);
- os << " ";
- printSort(array_type.getConstituentType(), os);
-
- os << "))\n";
- paren << ")";
- } else {
- Assert(term.isVariable());
- if (ProofManager::getSkolemizationManager()->isSkolem(*it)) {
- Debug("pf::array") << "This term is a skoelm!" << std::endl;
- d_skolemDeclarations.insert(*it);
- } else {
- os << "(% " << ProofManager::sanitize(term) << " ";
- os << "(term ";
- os << term.getType() << ")\n";
- paren << ")";
- }
- }
- }
-
- Debug("pf::array") << "Declaring terms done!" << std::endl;
-}
-
-void LFSCArrayProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
- Debug("pf::array") << "Array: print deferred declarations called" << std::endl;
-
- unsigned count = 1;
- for (ExprSet::const_iterator it = d_skolemDeclarations.begin(); it != d_skolemDeclarations.end(); ++it) {
- Expr term = *it;
- Node equality = ProofManager::getSkolemizationManager()->getDisequality(*it);
-
- Debug("pf::array") << "LFSCArrayProof::printDeferredDeclarations: term is: " << *it << std::endl
- << "It is a witness for: " << equality << std::endl;
-
- std::ostringstream newSkolemLiteral;
- newSkolemLiteral << ".sl" << count++;
- std::string skolemLiteral = newSkolemLiteral.str();
-
- d_skolemToLiteral[*it] = skolemLiteral;
-
- Debug("pf::array") << "LFSCArrayProof::printDeferredDeclarations: new skolem literal is: " << skolemLiteral << std::endl;
-
- Assert(equality.getKind() == kind::NOT);
- Assert(equality[0].getKind() == kind::EQUAL);
-
- Node array_one = equality[0][0];
- Node array_two = equality[0][1];
-
- ProofLetMap map;
- os << "(ext _ _ ";
- printTerm(array_one.toExpr(), os, map);
- os << " ";
- printTerm(array_two.toExpr(), os, map);
- os << " (\\ ";
- os << ProofManager::sanitize(*it);
- os << " (\\ ";
- os << skolemLiteral.c_str();
- os << "\n";
-
- paren << ")))";
- }
-}
-
-void LFSCArrayProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) {
- // Nothing to do here at this point.
-}
-
-bool LFSCArrayProof::printsAsBool(const Node &n)
-{
- if (n.getKind() == kind::SELECT)
- return true;
-
- return false;
-}
-
-} /* CVC4 namespace */
diff --git a/src/proof/array_proof.h b/src/proof/array_proof.h
deleted file mode 100644
index ffcff165a..000000000
--- a/src/proof/array_proof.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/********************* */
-/*! \file array_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Tim King, Mathias Preiner, Guy Katz
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Arrray proof
- **
- ** Arrau proof
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__ARRAY__PROOF_H
-#define CVC4__ARRAY__PROOF_H
-
-#include <memory>
-#include <unordered_set>
-
-#include "expr/expr.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
-#include "theory/arrays/theory_arrays.h"
-#include "theory/uf/equality_engine.h"
-
-namespace CVC4 {
-
-// Proof object outputted by TheoryARRAY.
-class ProofArray : public Proof {
- public:
- ProofArray(std::shared_ptr<theory::eq::EqProof> pf, unsigned row,
- unsigned row1, unsigned ext);
-
- void registerSkolem(Node equality, Node skolem);
-
- void toStream(std::ostream& out) const override;
- void toStream(std::ostream& out, const ProofLetMap& map) const override;
-
- private:
- void toStreamLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map) const;
-
- Node toStreamRecLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- unsigned tb,
- const ProofLetMap& map) const;
-
- // It is simply an equality engine proof.
- std::shared_ptr<theory::eq::EqProof> d_proof;
-
- /** Merge tag for ROW applications */
- unsigned d_reasonRow;
- /** Merge tag for ROW1 applications */
- unsigned d_reasonRow1;
- /** Merge tag for EXT applications */
- unsigned d_reasonExt;
-};
-
-namespace theory {
-namespace arrays{
-class TheoryArrays;
-} /* namespace CVC4::theory::arrays */
-} /* namespace CVC4::theory */
-
-typedef std::unordered_set<Type, TypeHashFunction > TypeSet;
-
-class ArrayProof : public TheoryProof {
- // TODO: whatever goes in this theory
-protected:
- TypeSet d_sorts; // all the uninterpreted sorts in this theory
- ExprSet d_declarations; // all the variable/function declarations
- ExprSet d_skolemDeclarations; // all the skolem variable declarations
- std::map<Expr, std::string> d_skolemToLiteral;
- theory::TheoryId getTheoryId() override;
-
- public:
- ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine);
-
- std::string skolemToLiteral(Expr skolem);
-
- void registerTerm(Expr term) override;
-};
-
-class LFSCArrayProof : public ArrayProof {
-public:
- LFSCArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine)
- : ArrayProof(arrays, proofEngine)
- {}
-
- void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
- void printOwnedSort(Type type, std::ostream& os) override;
- void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) override;
- void printSortDeclarations(std::ostream& os, std::ostream& paren) override;
- void printTermDeclarations(std::ostream& os, std::ostream& paren) override;
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
-
- bool printsAsBool(const Node& n) override;
-};
-
-
-}/* CVC4 namespace */
-
-#endif /* CVC4__ARRAY__PROOF_H */
diff --git a/src/proof/bitvector_proof.cpp b/src/proof/bitvector_proof.cpp
deleted file mode 100644
index 98e3300f5..000000000
--- a/src/proof/bitvector_proof.cpp
+++ /dev/null
@@ -1,792 +0,0 @@
-/********************* */
-/*! \file bitvector_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Liana Hadarean, Guy Katz, Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** Contains implementions (e.g. code for printing bitblasting bindings that is
- ** common to all kinds of bitvector proofs.
- **/
-
-#include "proof/bitvector_proof.h"
-#include "options/bv_options.h"
-#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),
- d_declarations(),
- d_seenBBTerms(),
- d_bbTerms(),
- d_bbAtoms(),
- d_bitblaster(nullptr),
- d_useConstantLetification(false),
- d_cnfProof()
-{
-}
-
-void BitVectorProof::setBitblaster(theory::bv::TBitblaster<Node>* bb)
-{
- Assert(d_bitblaster == NULL);
- d_bitblaster = bb;
-}
-
-void BitVectorProof::registerTermBB(Expr term)
-{
- Debug("pf::bv") << "BitVectorProof::registerTermBB( " << term
- << " )" << std::endl;
-
- if (d_seenBBTerms.find(term) != d_seenBBTerms.end()) return;
-
- d_seenBBTerms.insert(term);
- d_bbTerms.push_back(term);
-
- // If this term gets used in the final proof, we will want to register it.
- // However, we don't know this at this point; and when the theory proof engine
- // sees it, if it belongs to another theory, it won't register it with this
- // proof. So, we need to tell the engine to inform us.
-
- if (theory::Theory::theoryOf(term) != theory::THEORY_BV)
- {
- Debug("pf::bv") << "\tMarking term " << term
- << " for future BV registration" << std::endl;
- d_proofEngine->markTermForFutureRegistration(term, theory::THEORY_BV);
- }
-}
-
-void BitVectorProof::registerAtomBB(Expr atom, Expr atom_bb) {
- Debug("pf::bv") << "BitVectorProof::registerAtomBB( " << atom
- << ", " << atom_bb << " )" << std::endl;
-
- Expr def = atom.eqExpr(atom_bb);
- d_bbAtoms.insert(std::make_pair(atom, def));
- registerTerm(atom);
-
- // Register the atom's terms for bitblasting
- registerTermBB(atom[0]);
- registerTermBB(atom[1]);
-}
-
-void BitVectorProof::registerTerm(Expr term) {
- Debug("pf::bv") << "BitVectorProof::registerTerm( " << term << " )"
- << std::endl;
-
- if (options::lfscLetification() && term.isConst()
- && term.getType().isBitVector())
- {
- if (d_constantLetMap.find(term) == d_constantLetMap.end()) {
- std::ostringstream name;
- name << "letBvc" << d_constantLetMap.size();
- d_constantLetMap[term] = name.str();
- }
- }
-
- d_usedBB.insert(term);
-
- if (theory::Theory::isLeafOf(term, theory::THEORY_BV) && !term.isConst())
- {
- d_declarations.insert(term);
- }
-
- Debug("pf::bv") << "Going to register children: " << std::endl;
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- Debug("pf::bv") << "\t" << term[i] << std::endl;
- }
-
- // don't care about parametric operators for bv?
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- d_proofEngine->registerTerm(term[i]);
- }
-}
-
-std::string BitVectorProof::getBBTermName(Expr expr)
-{
- Debug("pf::bv") << "BitVectorProof::getBBTermName( " << expr << " ) = bt"
- << expr.getId() << std::endl;
- std::ostringstream os;
- os << "bt" << expr.getId();
- return os.str();
-}
-
-void BitVectorProof::printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Debug("pf::bv") << std::endl
- << "(pf::bv) BitVectorProof::printOwnedTerm( " << term
- << " ), theory is: " << theory::Theory::theoryOf(term)
- << std::endl;
-
- Assert(theory::Theory::theoryOf(term) == theory::THEORY_BV);
-
- // peel off eager bit-blasting trick
- if (term.getKind() == kind::BITVECTOR_EAGER_ATOM) {
- d_proofEngine->printBoundTerm(term[0], os, map);
- return;
- }
-
- switch (term.getKind()) {
- case kind::CONST_BITVECTOR : {
- printConstant(term, os);
- return;
- }
- case kind::BITVECTOR_AND :
- case kind::BITVECTOR_OR :
- case kind::BITVECTOR_XOR :
- case kind::BITVECTOR_NAND :
- case kind::BITVECTOR_NOR :
- case kind::BITVECTOR_XNOR :
- case kind::BITVECTOR_COMP :
- case kind::BITVECTOR_MULT :
- case kind::BITVECTOR_PLUS :
- case kind::BITVECTOR_SUB :
- case kind::BITVECTOR_UDIV :
- case kind::BITVECTOR_UREM :
- case kind::BITVECTOR_UDIV_TOTAL :
- case kind::BITVECTOR_UREM_TOTAL :
- case kind::BITVECTOR_SDIV :
- case kind::BITVECTOR_SREM :
- case kind::BITVECTOR_SMOD :
- case kind::BITVECTOR_SHL :
- case kind::BITVECTOR_LSHR :
- case kind::BITVECTOR_ASHR :
- case kind::BITVECTOR_CONCAT : {
- printOperatorNary(term, os, map);
- return;
- }
- case kind::BITVECTOR_NEG :
- case kind::BITVECTOR_NOT :
- case kind::BITVECTOR_ROTATE_LEFT :
- case kind::BITVECTOR_ROTATE_RIGHT : {
- printOperatorUnary(term, os, map);
- return;
- }
- case kind::EQUAL :
- case kind::BITVECTOR_ULT :
- case kind::BITVECTOR_ULE :
- case kind::BITVECTOR_UGT :
- case kind::BITVECTOR_UGE :
- case kind::BITVECTOR_SLT :
- case kind::BITVECTOR_SLE :
- case kind::BITVECTOR_SGT :
- case kind::BITVECTOR_SGE : {
- printPredicate(term, os, map);
- return;
- }
- case kind::BITVECTOR_EXTRACT :
- case kind::BITVECTOR_REPEAT :
- case kind::BITVECTOR_ZERO_EXTEND :
- case kind::BITVECTOR_SIGN_EXTEND : {
- printOperatorParametric(term, os, map);
- return;
- }
- case kind::BITVECTOR_BITOF : {
- printBitOf(term, os, map);
- return;
- }
-
- case kind::VARIABLE: {
- os << "(a_var_bv " << utils::getSize(term)<< " " << ProofManager::sanitize(term) << ")";
- return;
- }
-
- case kind::SKOLEM: {
-
- // TODO: we need to distinguish between "real" skolems (e.g. from array) and "fake" skolems,
- // like ITE terms. Is there a more elegant way?
-
- if (ProofManager::getSkolemizationManager()->isSkolem(term)) {
- os << ProofManager::sanitize(term);
- } else {
- os << "(a_var_bv " << utils::getSize(term)<< " " << ProofManager::sanitize(term) << ")";
- }
- return;
- }
-
- default:
- Unreachable();
- }
-}
-
-void BitVectorProof::printEmptyClauseProof(std::ostream& os,
- std::ostream& paren)
-{
- Assert(options::bitblastMode() == options::BitblastMode::EAGER)
- << "the BV theory should only be proving bottom directly in the eager "
- "bitblasting mode";
-}
-
-void BitVectorProof::printBitOf(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- Assert(term.getKind() == kind::BITVECTOR_BITOF);
- unsigned bit = term.getOperator().getConst<BitVectorBitOf>().d_bitIndex;
- Expr var = term[0];
-
- Debug("pf::bv") << "BitVectorProof::printBitOf( " << term << " ), "
- << "bit = " << bit << ", var = " << var << std::endl;
-
- os << "(bitof ";
- os << d_exprToVariableName[var];
- os << " " << bit << ")";
-}
-
-void BitVectorProof::printConstant(Expr term, std::ostream& os)
-{
- Assert(term.isConst());
- os << "(a_bv " << utils::getSize(term) << " ";
-
- if (d_useConstantLetification) {
- os << d_constantLetMap[term] << ")";
- } else {
- std::ostringstream paren;
- int size = utils::getSize(term);
- for (int i = size - 1; i >= 0; --i) {
- os << "(bvc ";
- os << (utils::getBit(term, i) ? "b1" : "b0") <<" ";
- paren << ")";
- }
- os << " bvn)";
- os << paren.str();
- }
-}
-
-void BitVectorProof::printOperatorNary(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- std::string op = utils::toLFSCKindTerm(term);
- std::ostringstream paren;
- std::string holes = term.getKind() == kind::BITVECTOR_CONCAT ? "_ _ " : "";
- unsigned size = term.getKind() == kind::BITVECTOR_CONCAT? utils::getSize(term) :
- utils::getSize(term[0]); // cause of COMP
-
- for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
- os <<"("<< op <<" " << size <<" " << holes;
- }
- d_proofEngine->printBoundTerm(term[0], os, map);
- os <<" ";
- for (unsigned i = 1; i < term.getNumChildren(); ++i) {
- d_proofEngine->printBoundTerm(term[i], os, map);
- os << ")";
- }
-}
-
-void BitVectorProof::printOperatorUnary(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- os <<"(";
- os << utils::toLFSCKindTerm(term) << " " << utils::getSize(term) <<" ";
- os << " ";
- d_proofEngine->printBoundTerm(term[0], os, map);
- os <<")";
-}
-
-void BitVectorProof::printPredicate(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- os <<"(";
- os << utils::toLFSCKindTerm(term) << " " << utils::getSize(term[0]) <<" ";
- os << " ";
- d_proofEngine->printBoundTerm(term[0], os, map);
- os << " ";
- d_proofEngine->printBoundTerm(term[1], os, map);
- os <<")";
-}
-
-void BitVectorProof::printOperatorParametric(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- os <<"(";
- os << utils::toLFSCKindTerm(term) << " " << utils::getSize(term) <<" ";
- os <<" ";
- if (term.getKind() == kind::BITVECTOR_REPEAT) {
- unsigned amount =
- term.getOperator().getConst<BitVectorRepeat>().d_repeatAmount;
- os << amount <<" _ ";
- }
- if (term.getKind() == kind::BITVECTOR_SIGN_EXTEND) {
- unsigned amount =
- term.getOperator().getConst<BitVectorSignExtend>().d_signExtendAmount;
- os << amount <<" _ ";
- }
-
- if (term.getKind() == kind::BITVECTOR_ZERO_EXTEND) {
- unsigned amount =
- term.getOperator().getConst<BitVectorZeroExtend>().d_zeroExtendAmount;
- os << amount<<" _ ";
- }
- if (term.getKind() == kind::BITVECTOR_EXTRACT) {
- unsigned low = utils::getExtractLow(term);
- unsigned high = utils::getExtractHigh(term);
- os << high <<" " << low << " " << utils::getSize(term[0]);
- }
- os <<" ";
- Assert(term.getNumChildren() == 1);
- d_proofEngine->printBoundTerm(term[0], os, map);
- os <<")";
-}
-
-void BitVectorProof::printOwnedSort(Type type, std::ostream& os)
-{
- Debug("pf::bv") << std::endl
- << "(pf::bv) BitVectorProof::printOwnedSort( " << type << " )"
- << std::endl;
- Assert(type.isBitVector());
- unsigned width = utils::getSize(type);
- os << "(BitVec " << width << ")";
-}
-
-void BitVectorProof::printSortDeclarations(std::ostream& os,
- std::ostream& paren)
-{
- // Nothing to do here at this point.
-}
-
-void BitVectorProof::printTermDeclarations(std::ostream& os,
- std::ostream& paren)
-{
- ExprSet::const_iterator it = d_declarations.begin();
- ExprSet::const_iterator end = d_declarations.end();
- for (; it != end; ++it) {
- if ((it->isVariable() || it->isConst()) && !ProofManager::getSkolemizationManager()->isSkolem(*it)) {
- d_exprToVariableName[*it] = ProofManager::sanitize(*it);
- } else {
- std::string newAlias = assignAlias(*it);
- d_exprToVariableName[*it] = newAlias;
- }
-
- os << "(% " << d_exprToVariableName[*it] <<" var_bv" << "\n";
- paren <<")";
- }
-}
-
-void BitVectorProof::printDeferredDeclarations(std::ostream& os,
- std::ostream& paren)
-{
- if (options::lfscLetification()) {
- os << std::endl << ";; BV const letification\n" << std::endl;
- std::map<Expr,std::string>::const_iterator it;
- for (it = d_constantLetMap.begin(); it != d_constantLetMap.end(); ++it) {
- os << "\n(@ " << it->second << " ";
- std::ostringstream localParen;
- int size = utils::getSize(it->first);
- for (int i = size - 1; i >= 0; --i) {
- os << "(bvc ";
- os << (utils::getBit(it->first, i) ? "b1" : "b0") << " ";
- localParen << ")";
- }
- os << "bvn";
- os << localParen.str();
- paren << ")";
- }
- os << std::endl;
-
- d_useConstantLetification = true;
- }
-}
-
-void BitVectorProof::printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap)
-{
- // Print "trust" statements to bind complex bv variables to their associated terms
-
- ExprToString::const_iterator it = d_assignedAliases.begin();
- ExprToString::const_iterator end = d_assignedAliases.end();
-
- for (; it != end; ++it) {
- Debug("pf::bv") << "Printing aliasing declaration for: " << *it << std::endl;
- std::stringstream declaration;
- declaration << ".fbvd" << d_aliasToBindDeclaration.size();
- d_aliasToBindDeclaration[it->second] = declaration.str();
-
- os << "(th_let_pf _ ";
-
- os << "(trust_f ";
- os << "(= (BitVec " << utils::getSize(it->first) << ") ";
- os << "(a_var_bv " << utils::getSize(it->first) << " " << it->second << ") ";
- d_proofEngine->printBoundTerm(it->first, os, globalLetMap);
- os << ")) ";
- os << "(\\ "<< d_aliasToBindDeclaration[it->second] << "\n";
- paren << "))";
- }
-
- os << "\n";
-}
-
-void BitVectorProof::printTermBitblasting(Expr term, std::ostream& os)
-{
- // TODO: once we have the operator elimination rules remove those that we
- // eliminated
- Assert(term.getType().isBitVector());
- Kind kind = term.getKind();
-
- if (theory::Theory::isLeafOf(term, theory::THEORY_BV) && !term.isConst())
- {
- // A term is a leaf if it has no children, or if it belongs to another theory
- os << "(bv_bbl_var " << utils::getSize(term) << " " << d_exprToVariableName[term];
- os << " _)";
- return;
- }
-
- switch(kind) {
- case kind::CONST_BITVECTOR : {
- os << "(bv_bbl_const "<< utils::getSize(term) <<" _ ";
- std::ostringstream paren;
- int size = utils::getSize(term);
- if (d_useConstantLetification) {
- os << d_constantLetMap[term] << ")";
- } else {
- for (int i = size - 1; i>= 0; --i) {
- os << "(bvc ";
- os << (utils::getBit(term, i) ? "b1" : "b0") <<" ";
- paren << ")";
- }
- os << " bvn)";
- os << paren.str();
- }
- return;
- }
-
- case kind::BITVECTOR_AND :
- case kind::BITVECTOR_OR :
- case kind::BITVECTOR_XOR :
- case kind::BITVECTOR_NAND :
- case kind::BITVECTOR_NOR :
- case kind::BITVECTOR_XNOR :
- case kind::BITVECTOR_COMP :
- case kind::BITVECTOR_MULT :
- case kind::BITVECTOR_PLUS :
- case kind::BITVECTOR_SUB :
- case kind::BITVECTOR_CONCAT : {
- Debug("pf::bv") << "Bitblasing kind = " << kind << std::endl;
-
- for (int i = term.getNumChildren() - 1; i > 0; --i) {
- os <<"(bv_bbl_"<< utils::toLFSCKind(kind);
-
- if (kind == kind::BITVECTOR_CONCAT) {
- os << " " << utils::getSize(term) << " _";
- }
- os << " _ _ _ _ _ _ ";
- }
-
- os << getBBTermName(term[0]) << " ";
-
- for (unsigned i = 1; i < term.getNumChildren(); ++i) {
- os << getBBTermName(term[i]);
- os << ") ";
- }
- return;
- }
-
- case kind::BITVECTOR_NEG :
- case kind::BITVECTOR_NOT :
- case kind::BITVECTOR_ROTATE_LEFT :
- case kind::BITVECTOR_ROTATE_RIGHT : {
- os << "(bv_bbl_"<<utils::toLFSCKind(kind);
- os << " _ _ _ _ ";
- os << getBBTermName(term[0]);
- os << ")";
- return;
- }
- case kind::BITVECTOR_EXTRACT : {
- os <<"(bv_bbl_"<<utils::toLFSCKind(kind);
-
- os << " " << utils::getSize(term) << " ";
- os << utils::getExtractHigh(term) << " ";
- os << utils::getExtractLow(term) << " ";
- os << " _ _ _ _ ";
-
- os << getBBTermName(term[0]);
- os <<")";
- return;
- }
- case kind::BITVECTOR_REPEAT :
- case kind::BITVECTOR_ZERO_EXTEND :
- case kind::BITVECTOR_SIGN_EXTEND : {
- os << "(bv_bbl_" << utils::toLFSCKind(kind) << " ";
- os << utils::getSize(term) << " ";
- if (term.getKind() == kind::BITVECTOR_REPEAT) {
- unsigned amount =
- term.getOperator().getConst<BitVectorRepeat>().d_repeatAmount;
- os << amount;
- }
- if (term.getKind() == kind::BITVECTOR_SIGN_EXTEND) {
- unsigned amount =
- term.getOperator().getConst<BitVectorSignExtend>().d_signExtendAmount;
- os << amount;
- }
-
- if (term.getKind() == kind::BITVECTOR_ZERO_EXTEND) {
- unsigned amount =
- term.getOperator().getConst<BitVectorZeroExtend>().d_zeroExtendAmount;
- os << amount;
- }
-
- os <<" _ _ _ _ ";
- os << getBBTermName(term[0]);
- os <<")";
- return;
- }
- case kind::BITVECTOR_UDIV :
- case kind::BITVECTOR_UREM :
- case kind::BITVECTOR_UDIV_TOTAL :
- case kind::BITVECTOR_UREM_TOTAL :
- case kind::BITVECTOR_SDIV :
- case kind::BITVECTOR_SREM :
- case kind::BITVECTOR_SMOD :
- case kind::BITVECTOR_SHL :
- case kind::BITVECTOR_LSHR :
- case kind::BITVECTOR_ASHR : {
- // these are terms for which bit-blasting is not supported yet
- std::ostringstream paren;
- os <<"(trust_bblast_term _ ";
- paren <<")";
- d_proofEngine->printLetTerm(term, os);
- os <<" ";
- std::vector<Node> bits;
- d_bitblaster->bbTerm(term, bits);
-
- for (int i = utils::getSize(term) - 1; i >= 0; --i) {
- os << "(bbltc ";
- d_proofEngine->printLetTerm((bits[i]).toExpr(), os);
- paren << ")";
- }
- os << "bbltn" << paren.str();
- return;
- }
-
- default: Unreachable() << "BitVectorProof Unknown operator";
- }
-}
-
-void BitVectorProof::printAtomBitblasting(Expr atom,
- std::ostream& os,
- bool swap)
-{
- Kind kind = atom.getKind();
- switch(kind) {
- case kind::BITVECTOR_ULT :
- case kind::BITVECTOR_ULE :
- case kind::BITVECTOR_UGT :
- case kind::BITVECTOR_UGE :
- case kind::BITVECTOR_SLT :
- case kind::BITVECTOR_SLE :
- case kind::BITVECTOR_SGT :
- case kind::BITVECTOR_SGE :
- case kind::EQUAL: {
- Debug("pf::bv") << "Bitblasing kind = " << kind << std::endl;
-
- os << "(bv_bbl_" << utils::toLFSCKindTerm(atom);
-
- if (swap) {os << "_swap";}
-
- os << " _ _ _ _ _ _ ";
- os << getBBTermName(atom[0]);
- os << " ";
- os << getBBTermName(atom[1]);
- os << ")";
-
- return;
- }
- default: Unreachable() << "BitVectorProof Unknown atom kind";
- }
-}
-
-void BitVectorProof::printAtomBitblastingToFalse(Expr atom, std::ostream& os)
-{
- Assert(atom.getKind() == kind::EQUAL);
-
- os << "(bv_bbl_=_false";
- os << " _ _ _ _ _ _ ";
- os << getBBTermName(atom[0]);
-
- os << " ";
-
- os << getBBTermName(atom[1]);
-
- os << ")";
-}
-
-void BitVectorProof::printBitblasting(std::ostream& os, std::ostream& paren)
-{
- // bit-blast terms
- {
- Debug("pf::bv")
- << "BitVectorProof::printBitblasting: the bitblasted terms are: "
- << std::endl;
- std::vector<Expr>::const_iterator it = d_bbTerms.begin();
- std::vector<Expr>::const_iterator end = d_bbTerms.end();
-
- for (; it != end; ++it) {
- if (d_usedBB.find(*it) == d_usedBB.end()) {
- Debug("pf::bv") << "\t" << *it << "\t(UNUSED)" << std::endl;
- } else {
- Debug("pf::bv") << "\t" << *it << std::endl;
- }
- }
-
- Debug("pf::bv") << std::endl;
- }
-
- std::vector<Expr>::const_iterator it = d_bbTerms.begin();
- std::vector<Expr>::const_iterator end = d_bbTerms.end();
- for (; it != end; ++it) {
- if (d_usedBB.find(*it) == d_usedBB.end()
- && options::bitblastMode() != options::BitblastMode::EAGER)
- continue;
-
- // Is this term has an alias, we inject it through the decl_bblast statement
- if (hasAlias(*it)) {
- os << "(decl_bblast_with_alias _ _ _ _ ";
- printTermBitblasting(*it, os);
- os << " " << d_aliasToBindDeclaration[d_assignedAliases[*it]] << " ";
- os << "(\\ "<< getBBTermName(*it);
- os << "\n";
- paren <<"))";
- } else {
- os << "(decl_bblast _ _ _ ";
- printTermBitblasting(*it, os);
- os << "(\\ "<< getBBTermName(*it);
- os << "\n";
- paren <<"))";
- }
- }
- // bit-blast atoms
- ExprToExpr::const_iterator ait = d_bbAtoms.begin();
- ExprToExpr::const_iterator aend = d_bbAtoms.end();
- for (; ait != aend; ++ait) {
- if (d_usedBB.find(ait->first) == d_usedBB.end()
- && options::bitblastMode() != options::BitblastMode::EAGER)
- continue;
-
- os << "(th_let_pf _ ";
- if (ait->first.getKind() == kind::CONST_BOOLEAN) {
- bool val = ait->first.getConst<bool>();
- os << "(iff_symm " << (val ? "true" : "false" ) << ")";
- } else {
- Assert(ait->first == ait->second[0]);
-
- bool swap = false;
- if (ait->first.getKind() == kind::EQUAL) {
- Expr bitwiseEquivalence = ait->second[1];
- if ((bitwiseEquivalence.getKind() == kind::CONST_BOOLEAN) && !bitwiseEquivalence.getConst<bool>()) {
- printAtomBitblastingToFalse(ait->first, os);
- } else {
- if (bitwiseEquivalence.getKind() != kind::AND) {
- // Just one bit
- if (bitwiseEquivalence.getNumChildren() > 0 && bitwiseEquivalence[0].getKind() == kind::BITVECTOR_BITOF) {
- swap = (ait->first[1] == bitwiseEquivalence[0][0]);
- }
- } else {
- // Multiple bits
- if (bitwiseEquivalence[0].getNumChildren() > 0 &&
- bitwiseEquivalence[0][0].getKind() == kind::BITVECTOR_BITOF) {
- swap = (ait->first[1] == bitwiseEquivalence[0][0][0]);
- } else if (bitwiseEquivalence[0].getNumChildren() > 0 &&
- bitwiseEquivalence[0][1].getKind() == kind::BITVECTOR_BITOF) {
- swap = (ait->first[0] == bitwiseEquivalence[0][1][0]);
- }
- }
-
- printAtomBitblasting(ait->first, os, swap);
- }
- } else {
- printAtomBitblasting(ait->first, os, swap);
- }
- }
-
- os <<"(\\ " << ProofManager::getPreprocessedAssertionName(ait->second) <<"\n";
- paren <<"))";
- }
-}
-
-theory::TheoryId BitVectorProof::getTheoryId() { return theory::THEORY_BV; }
-
-const std::set<Node>* BitVectorProof::getAtomsInBitblastingProof()
-{
- return &d_atomsInBitblastingProof;
-}
-
-std::string BitVectorProof::assignAlias(Expr expr)
-{
- Assert(d_exprToVariableName.find(expr) == d_exprToVariableName.end());
-
- std::stringstream ss;
- ss << "fbv" << d_assignedAliases.size();
- Debug("pf::bv") << "assignAlias( " << expr << ") = " << ss.str() << std::endl;
- d_assignedAliases[expr] = ss.str();
- return ss.str();
-}
-
-bool BitVectorProof::hasAlias(Expr expr)
-{
- return d_assignedAliases.find(expr) != d_assignedAliases.end();
-}
-
-void BitVectorProof::printConstantDisequalityProof(
- std::ostream& os, Expr c1, Expr c2, const ProofLetMap& globalLetMap)
-{
- Assert(c1.isConst());
- Assert(c2.isConst());
- Assert(utils::getSize(c1) == utils::getSize(c2));
-
- os << "(bv_disequal_constants " << utils::getSize(c1) << " ";
-
- std::ostringstream paren;
-
- for (int i = utils::getSize(c1) - 1; i >= 0; --i) {
- os << "(bvc ";
- os << (utils::getBit(c1, i) ? "b1" : "b0") << " ";
- paren << ")";
- }
- os << "bvn";
- os << paren.str();
-
- os << " ";
-
- for (int i = utils::getSize(c2) - 1; i >= 0; --i) {
- os << "(bvc ";
- os << (utils::getBit(c2, i) ? "b1" : "b0") << " ";
-
- }
- os << "bvn";
- os << paren.str();
-
- os << ")";
-}
-
-void BitVectorProof::printRewriteProof(std::ostream& os,
- const Node& n1,
- const Node& n2)
-{
- ProofLetMap emptyMap;
- os << "(rr_bv_default ";
- d_proofEngine->printBoundTerm(n2.toExpr(), os, emptyMap);
- os << " ";
- d_proofEngine->printBoundTerm(n1.toExpr(), os, emptyMap);
- os << ")";
-}
-
-} // namespace proof
-
-} // namespace CVC4
diff --git a/src/proof/bitvector_proof.h b/src/proof/bitvector_proof.h
deleted file mode 100644
index 9a9071e58..000000000
--- a/src/proof/bitvector_proof.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/********************* */
-/*! \file bitvector_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Bitvector proof base class
- **
- ** Contains code (e.g. proof printing code) which is common to all bitvector
- *proofs.
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__BITVECTOR_PROOF_H
-#define CVC4__BITVECTOR_PROOF_H
-
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "expr/expr.h"
-#include "proof/cnf_proof.h"
-#include "proof/theory_proof.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;
-typedef std::unordered_map<Expr, Expr, ExprHashFunction> ExprToExpr;
-typedef std::unordered_map<Expr, std::string, ExprHashFunction> ExprToString;
-
-/**
- * A bitvector proof is best understood as having
- *
- * 1. A declaration of a "bitblasted formulas" -- boolean formulas
- * that are each translations of a BV-literal (a comparison between BVs).
- *
- * (and a proof that each "bitblasted formula" is implied by the
- * corresponding BV literal)
- *
- * 2. A declaration of a cnf formula equisatisfiable to the bitblasted
- * formula
- *
- * (and a proof that each clause is implied by some bitblasted formula)
- *
- * 3. A proof of UNSAT from the clauses.
- *
- * This class is responsible for 1 & 2. The proof of UNSAT is delegated to a
- * subclass.
- */
-class BitVectorProof : public TheoryProof
-{
- protected:
- BitVectorProof(theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine);
- virtual ~BitVectorProof(){};
-
- // Set of BV variables in the input. (e.g. "a" in [ a = 000 ] ^ [ a == 001 ])
- ExprSet d_declarations;
-
- // terms and formulas that are actually relevant to the proof
- ExprSet d_usedBB;
-
- ExprSet d_seenBBTerms; // terms that need to be bit-blasted
- std::vector<Expr> d_bbTerms; // order of bit-blasting
-
- /** atoms that need to be bit-blasted,
- * BV-literals -> (BV-literals <=> bool formula)
- * where a BV literal is a signed or unsigned comparison.
- */
- ExprToExpr d_bbAtoms;
-
- // map from Expr representing normalized lemma to ClauseId in SAT solver
- ExprToClauseId d_bbConflictMap;
-
- theory::bv::TBitblaster<Node>* d_bitblaster;
-
- /** In an LFSC proof the manifestation of this expression bit-level
- * representation will have a string name. This method returns that name.
- */
- std::string getBBTermName(Expr expr);
-
- /** A mapping from constant BV terms to identifiers that will refer to them in
- * an LFSC proof, if constant-letification is enabled.
- */
- std::map<Expr, std::string> d_constantLetMap;
-
- /** Should we introduced identifiers to refer to BV constant terms? It may
- * reduce the textual size of a proof!
- */
- bool d_useConstantLetification;
-
- /** Temporary storage for the set of nodes in the bitblasted formula which
- * correspond to CNF variables eventually used in the proof of unsat on the
- * CNF formula
- */
- std::set<Node> d_atomsInBitblastingProof;
-
- /**
- * Prints out
- * (a) a declaration of bit-level interpretations corresponding to bits in
- * the input BV terms.
- * (b) a proof that the each BV literal entails a boolean formula on
- * bitof expressions.
- */
- void printBitblasting(std::ostream& os, std::ostream& paren);
-
- /**
- * The proof that the bit-blasted SAT formula is correctly converted to CNF
- */
- std::unique_ptr<CnfProof> d_cnfProof;
-
- theory::TheoryId getTheoryId() override;
-
- public:
- void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
-
- void printOwnedSort(Type type, std::ostream& os) override;
-
- /**
- * Populate the d_atomsInBitblastingProof member.
- * See its documentation
- */
- 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);
-
- /**
- * Read the d_atomsInBitblastingProof member.
- * See its documentation.
- */
- const std::set<Node>* getAtomsInBitblastingProof();
-
- void registerTermBB(Expr term);
-
- /**
- * Informs the proof that the `atom` predicate was bitblasted into the
- * `atom_bb` term.
- *
- * The `atom` term must be a comparison of bitvectors, and the `atom_bb` term
- * a boolean formula on bitof expressions
- */
- void registerAtomBB(Expr atom, Expr atom_bb);
-
- void registerTerm(Expr term) override;
-
- /**
- * 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* 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;
-
- ExprToString d_assignedAliases;
- std::map<std::string, std::string> d_aliasToBindDeclaration;
- std::string assignAlias(Expr expr);
- bool hasAlias(Expr expr);
-
- // Functions for printing various BV terms. Helpers for BV's `printOwnedTerm`
- void printConstant(Expr term, std::ostream& os);
- void printOperatorNary(Expr term, std::ostream& os, const ProofLetMap& map);
- void printOperatorUnary(Expr term, std::ostream& os, const ProofLetMap& map);
- void printPredicate(Expr term, std::ostream& os, const ProofLetMap& map);
- void printOperatorParametric(Expr term, std::ostream& os, const ProofLetMap& map);
- void printBitOf(Expr term, std::ostream& os, const ProofLetMap& map);
-
- /**
- * Prints the LFSC construction of a bblast_term for `term`
- */
- void printTermBitblasting(Expr term, std::ostream& os);
-
- /**
- * For a given BV-atom (a comparison), prints a proof that that comparison
- * holds iff the bitblasted equivalent of it holds.
- * Uses a side-condidition to do the bit-blasting.
- */
- void printAtomBitblasting(Expr term, std::ostream& os, bool swap);
- void printAtomBitblastingToFalse(Expr term, std::ostream& os);
-
- void printSortDeclarations(std::ostream& os, std::ostream& paren) override;
- void printTermDeclarations(std::ostream& os, std::ostream& paren) override;
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
-
- void printConstantDisequalityProof(std::ostream& os,
- Expr c1,
- Expr c2,
- const ProofLetMap& globalLetMap) override;
- void printRewriteProof(std::ostream& os,
- const Node& n1,
- 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
deleted file mode 100644
index 21e8056ca..000000000
--- a/src/proof/clausal_bitvector_proof.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-/********************* */
-/*! \file clausal_bitvector_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner, Andres Noetzli
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** 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 <iostream>
-#include <iterator>
-#include <map>
-
-#include "options/bv_options.h"
-#include "proof/clausal_bitvector_proof.h"
-#include "proof/dimacs.h"
-#include "proof/drat/drat_proof.h"
-#include "proof/er/er_proof.h"
-#include "proof/lfsc_proof_printer.h"
-#include "proof/lrat/lrat_proof.h"
-#include "prop/sat_solver_types.h"
-#include "smt/smt_statistics_registry.h"
-#include "theory/bv/theory_bv.h"
-
-#if CVC4_USE_DRAT2ER
-#include "drat2er_options.h"
-#include "drat_trim_interface.h"
-#endif
-
-namespace CVC4 {
-
-namespace proof {
-
-ClausalBitVectorProof::ClausalBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine)
- : BitVectorProof(bv, proofEngine),
- d_clauses(),
- d_originalClauseIndices(),
- d_binaryDratProof(),
- d_coreClauseIndices(),
- d_dratTranslationStatistics(),
- d_dratOptimizationStatistics()
-{
-}
-
-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)
-{
- prop::SatClause& emplaced_clause =
- d_clauses.emplace(id, clause).first->second;
- canonicalizeClause(emplaced_clause);
- d_originalClauseIndices.push_back(id);
-};
-
-void ClausalBitVectorProof::calculateAtomsInBitblastingProof()
-{
- optimizeDratProof();
-
- // Debug dump of DRAT Proof
- if (Debug.isOn("bv::clausal"))
- {
- std::string serializedDratProof = d_binaryDratProof.str();
- Debug("bv::clausal") << "option: " << options::bvOptimizeSatProof()
- << std::endl;
- Debug("bv::clausal") << "binary DRAT proof byte count: "
- << serializedDratProof.size() << std::endl;
- Debug("bv::clausal") << "clause count: " << d_coreClauseIndices.size()
- << std::endl;
- }
-
- // Empty any old record of which atoms were used
- d_atomsInBitblastingProof.clear();
- Assert(d_atomsInBitblastingProof.size() == 0);
-
- // For each used clause, ask the CNF proof which atoms are used in it
- for (const ClauseId usedIdx : d_coreClauseIndices)
- {
- d_cnfProof->collectAtoms(&d_clauses.at(usedIdx), d_atomsInBitblastingProof);
- }
-}
-
-struct SatClausePointerComparator
-{
- inline bool operator()(const prop::SatClause* const& l,
- const prop::SatClause* const& r) const
- {
- prop::SatClauseLessThan cmp;
- return cmp(*l, *r);
- }
-};
-
-void ClausalBitVectorProof::optimizeDratProof()
-{
- TimerStat::CodeTimer optimizeDratProofTimer{
- d_dratOptimizationStatistics.d_totalTime};
- if (options::bvOptimizeSatProof() == options::BvOptimizeSatProof::PROOF
- || options::bvOptimizeSatProof() == options::BvOptimizeSatProof::FORMULA)
- {
- Debug("bv::clausal") << "Optimizing DRAT" << std::endl;
- std::string formulaFilename("cvc4-dimacs-XXXXXX");
- std::string dratFilename("cvc4-drat-XXXXXX");
- std::string optDratFilename("cvc4-optimized-drat-XXXXXX");
- std::string optFormulaFilename("cvc4-optimized-formula-XXXXXX");
-
- {
- std::unique_ptr<std::fstream> formStream = openTmpFile(&formulaFilename);
- const int64_t startPos = static_cast<int64_t>(formStream->tellp());
- printDimacs(*formStream, d_clauses, d_originalClauseIndices);
- d_dratOptimizationStatistics.d_initialFormulaSize.setData(
- static_cast<int64_t>(formStream->tellp()) - startPos);
- formStream->close();
- }
-
- {
- std::unique_ptr<std::fstream> dratStream = openTmpFile(&dratFilename);
- const int64_t startPos = static_cast<int64_t>(dratStream->tellp());
- (*dratStream) << d_binaryDratProof.str();
- d_dratOptimizationStatistics.d_initialDratSize.setData(
- static_cast<int64_t>(dratStream->tellp()) - startPos);
- dratStream->close();
- }
-
- std::unique_ptr<std::fstream> optDratStream = openTmpFile(&optDratFilename);
- std::unique_ptr<std::fstream> optFormulaStream =
- openTmpFile(&optFormulaFilename);
-
-#if CVC4_USE_DRAT2ER
- {
- TimerStat::CodeTimer runDratTimeOptimizationTimer{
- d_dratOptimizationStatistics.d_toolTime};
- int dratTrimExitCode =
- drat2er::drat_trim::OptimizeWithDratTrim(formulaFilename,
- dratFilename,
- optFormulaFilename,
- optDratFilename,
- drat2er::options::QUIET);
- AlwaysAssert(dratTrimExitCode == 0)
- << "drat-trim exited with " << dratTrimExitCode;
- }
-#else
- Unimplemented()
- << "Proof production when using CryptoMiniSat requires drat2er.\n"
- << "Run contrib/get-drat2er, reconfigure with --drat2er, and rebuild";
-#endif
-
- {
- d_binaryDratProof.str("");
- Assert(d_binaryDratProof.str().size() == 0);
-
- const int64_t startPos = static_cast<int64_t>(d_binaryDratProof.tellp());
- std::ifstream lratStream(optDratFilename);
- std::copy(std::istreambuf_iterator<char>(lratStream),
- std::istreambuf_iterator<char>(),
- std::ostreambuf_iterator<char>(d_binaryDratProof));
- d_dratOptimizationStatistics.d_optimizedDratSize.setData(
- static_cast<int64_t>(d_binaryDratProof.tellp()) - startPos);
- }
-
- if (options::bvOptimizeSatProof() == options::BvOptimizeSatProof::FORMULA)
- {
- std::ifstream optFormulaInStream{optFormulaFilename};
- const int64_t startPos = static_cast<int64_t>(optFormulaInStream.tellg());
- std::vector<prop::SatClause> core = parseDimacs(optFormulaInStream);
- d_dratOptimizationStatistics.d_optimizedFormulaSize.setData(
- static_cast<int64_t>(optFormulaInStream.tellg()) - startPos);
-
- CodeTimer clauseMatchingTimer{
- d_dratOptimizationStatistics.d_clauseMatchingTime};
-
- // Now we need to compute the clause indices for the UNSAT core. This is a
- // bit difficult because drat-trim may have reordered clauses, and/or
- // removed duplicate literals. We use literal sets as the canonical clause
- // form.
- //
- // TODO (aozdemir) It may be better to use a hash map instead of a tree
- // map here.
- std::map<const prop::SatClause*, ClauseId, SatClausePointerComparator>
- cannonicalClausesToIndices;
- for (const auto& kv : d_clauses)
- {
- cannonicalClausesToIndices[&kv.second] = kv.first;
- }
-
- d_coreClauseIndices.clear();
-
- for (prop::SatClause& coreClause : core)
- {
- canonicalizeClause(coreClause);
- d_coreClauseIndices.push_back(
- cannonicalClausesToIndices.at(&coreClause));
- }
- Debug("bv::clausal") << "Optimizing the DRAT proof and the formula"
- << std::endl;
- }
- else
- {
- Debug("bv::clausal") << "Optimizing the DRAT proof but not the formula"
- << std::endl;
- d_coreClauseIndices = d_originalClauseIndices;
- }
-
- optFormulaStream->close();
-
- Assert(d_coreClauseIndices.size() > 0);
- remove(formulaFilename.c_str());
- remove(dratFilename.c_str());
- remove(optDratFilename.c_str());
- remove(optFormulaFilename.c_str());
- Debug("bv::clausal") << "Optimized DRAT" << std::endl;
- }
- else
- {
- Debug("bv::clausal") << "Not optimizing the formula or the DRAT proof"
- << std::endl;
- d_coreClauseIndices = d_originalClauseIndices;
- }
-}
-
-void ClausalBitVectorProof::canonicalizeClause(prop::SatClause& clause)
-{
- std::sort(clause.begin(), clause.end());
- clause.erase(std::unique(clause.begin(), clause.end()), clause.end());
-}
-
-ClausalBitVectorProof::DratTranslationStatistics::DratTranslationStatistics()
- : d_totalTime("proof::bv::dratTranslation::totalTime"),
- d_toolTime("proof::bv::dratTranslation::toolTime")
-{
- smtStatisticsRegistry()->registerStat(&d_totalTime);
- smtStatisticsRegistry()->registerStat(&d_toolTime);
-}
-
-ClausalBitVectorProof::DratTranslationStatistics::~DratTranslationStatistics()
-{
- smtStatisticsRegistry()->unregisterStat(&d_totalTime);
- smtStatisticsRegistry()->unregisterStat(&d_toolTime);
-}
-
-ClausalBitVectorProof::DratOptimizationStatistics::DratOptimizationStatistics()
- : d_totalTime("proof::bv::dratOptimization::totalTime"),
- d_toolTime("proof::bv::dratOptimization::toolTime"),
- d_clauseMatchingTime("proof::bv::dratOptimization::clauseMatchingTime"),
- d_initialDratSize("proof::bv::dratOptimization::initialDratSize", 0),
- d_optimizedDratSize("proof::bv::dratOptimization::optimizedDratSize", 0),
- d_initialFormulaSize("proof::bv::dratOptimization::initialFormulaSize",
- 0),
- d_optimizedFormulaSize(
- "proof::bv::dratOptimization::optimizedFormulaSize", 0)
-{
- smtStatisticsRegistry()->registerStat(&d_totalTime);
- smtStatisticsRegistry()->registerStat(&d_toolTime);
- smtStatisticsRegistry()->registerStat(&d_clauseMatchingTime);
- smtStatisticsRegistry()->registerStat(&d_initialDratSize);
- smtStatisticsRegistry()->registerStat(&d_optimizedDratSize);
- smtStatisticsRegistry()->registerStat(&d_initialFormulaSize);
- smtStatisticsRegistry()->registerStat(&d_optimizedFormulaSize);
-}
-
-ClausalBitVectorProof::DratOptimizationStatistics::~DratOptimizationStatistics()
-{
- smtStatisticsRegistry()->unregisterStat(&d_totalTime);
- smtStatisticsRegistry()->unregisterStat(&d_toolTime);
- smtStatisticsRegistry()->unregisterStat(&d_clauseMatchingTime);
- smtStatisticsRegistry()->unregisterStat(&d_initialDratSize);
- smtStatisticsRegistry()->unregisterStat(&d_optimizedDratSize);
- smtStatisticsRegistry()->unregisterStat(&d_initialFormulaSize);
- smtStatisticsRegistry()->unregisterStat(&d_optimizedFormulaSize);
-}
-
-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)
-{
- os << "\n;; Bitblasting mappings\n";
- printBitblasting(os, paren);
-
- os << "\n;; BB-CNF mappings\n";
- d_cnfProof->printAtomMapping(d_atomsInBitblastingProof, os, paren, letMap);
-
- os << "\n;; BB-CNF proofs\n";
- for (const ClauseId id : d_coreClauseIndices)
- {
- d_cnfProof->printCnfProofForClause(id, &d_clauses.at(id), os, paren);
- }
-}
-
-void LfscDratBitVectorProof::printEmptyClauseProof(std::ostream& os,
- std::ostream& paren)
-{
- Assert(options::bitblastMode() == options::BitblastMode::EAGER)
- << "the BV theory should only be proving bottom directly in the eager "
- "bitblasting mode";
-
- os << "\n;; Proof of input to SAT solver\n";
- os << "(@ proofOfSatInput ";
- paren << ")";
-
- LFSCProofPrinter::printSatInputProof(d_coreClauseIndices, os, "bb");
-
- os << "\n;; DRAT Proof Value\n";
- os << "(@ dratProof ";
- paren << ")";
- d_dratTranslationStatistics.d_totalTime.start();
- drat::DratProof pf = drat::DratProof::fromBinary(d_binaryDratProof.str());
- d_dratTranslationStatistics.d_totalTime.stop();
- pf.outputAsLfsc(os, 2);
- os << "\n";
-
- os << "\n;; Verification of DRAT Proof\n";
- os << "(drat_proof_of_bottom _ proofOfSatInput dratProof "
- << "\n)";
-}
-
-void LfscLratBitVectorProof::printEmptyClauseProof(std::ostream& os,
- std::ostream& paren)
-{
- Assert(options::bitblastMode() == options::BitblastMode::EAGER)
- << "the BV theory should only be proving bottom directly in the eager "
- "bitblasting mode";
-
- os << "\n;; Proof of input to SAT solver\n";
- os << "(@ proofOfCMap ";
- paren << ")";
- LFSCProofPrinter::printCMapProof(d_coreClauseIndices, os, "bb");
-
- os << "\n;; DRAT Proof Value\n";
- os << "(@ lratProof ";
- paren << ")";
- d_dratTranslationStatistics.d_totalTime.start();
- lrat::LratProof pf =
- lrat::LratProof::fromDratProof(d_clauses,
- d_coreClauseIndices,
- d_binaryDratProof.str(),
- d_dratTranslationStatistics.d_toolTime);
- d_dratTranslationStatistics.d_totalTime.stop();
- pf.outputAsLfsc(os);
- os << "\n";
-
- os << "\n;; Verification of DRAT Proof\n";
- os << "(lrat_proof_of_bottom _ proofOfCMap lratProof "
- << "\n)";
-}
-
-void LfscErBitVectorProof::printEmptyClauseProof(std::ostream& os,
- std::ostream& paren)
-{
- Assert(options::bitblastMode() == options::BitblastMode::EAGER)
- << "the BV theory should only be proving bottom directly in the eager "
- "bitblasting mode";
-
- d_dratTranslationStatistics.d_totalTime.start();
- er::ErProof pf =
- er::ErProof::fromBinaryDratProof(d_clauses,
- d_coreClauseIndices,
- d_binaryDratProof.str(),
- d_dratTranslationStatistics.d_toolTime);
- d_dratTranslationStatistics.d_totalTime.stop();
-
- pf.outputAsLfsc(os);
-}
-
-} // namespace proof
-
-}; // namespace CVC4
diff --git a/src/proof/clausal_bitvector_proof.h b/src/proof/clausal_bitvector_proof.h
deleted file mode 100644
index 28a53c90c..000000000
--- a/src/proof/clausal_bitvector_proof.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/********************* */
-/*! \file clausal_bitvector_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief 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"
-#include "util/statistics_registry.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::unordered_map<ClauseId, prop::SatClause> d_clauses{};
- std::vector<ClauseId> d_originalClauseIndices{};
- // Stores the proof recieved from the SAT solver.
- std::ostringstream d_binaryDratProof{};
- std::vector<ClauseId> d_coreClauseIndices{};
-
- struct DratTranslationStatistics
- {
- DratTranslationStatistics();
- ~DratTranslationStatistics();
-
- // Total time spent doing translation (optimized binary DRAT -> in memory
- // target format including IO, postprocessing, etc.)
- TimerStat d_totalTime;
- // Time that the external tool actually spent
- TimerStat d_toolTime;
- };
-
- DratTranslationStatistics d_dratTranslationStatistics;
-
- private:
- // Optimizes the DRAT proof stored in `d_binaryDratProof` and returns a list
- // of clause actually needed to check that proof (a smaller UNSAT core)
- void optimizeDratProof();
-
- // Given reference to a SAT clause encoded as a vector of literals, puts the
- // literals into a canonical order
- static void canonicalizeClause(prop::SatClause& clause);
-
- struct DratOptimizationStatistics
- {
- DratOptimizationStatistics();
- ~DratOptimizationStatistics();
-
- // Total time spent using drat-trim to optimize the DRAT proof/formula
- // (including IO, etc.)
- TimerStat d_totalTime;
- // Time that drat-trim actually spent optimizing the DRAT proof/formula
- TimerStat d_toolTime;
- // Time that was spent matching clauses in drat-trim's output to clauses in
- // its input
- TimerStat d_clauseMatchingTime;
- // Bytes in binary DRAT proof before optimization
- IntStat d_initialDratSize;
- // Bytes in binary DRAT proof after optimization
- IntStat d_optimizedDratSize;
- // Bytes in textual DIMACS bitblasted formula before optimization
- IntStat d_initialFormulaSize;
- // Bytes in textual DIMACS bitblasted formula after optimization
- IntStat d_optimizedFormulaSize;
- };
-
- DratOptimizationStatistics d_dratOptimizationStatistics;
-};
-
-/**
- * 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)
- {
- }
-
- 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;
-};
-
-/**
- * A DRAT proof for a bit-vector problem
- */
-class LfscDratBitVectorProof : public LfscClausalBitVectorProof
-{
- public:
- LfscDratBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine)
- : LfscClausalBitVectorProof(bv, proofEngine)
- {
- }
-
- void printEmptyClauseProof(std::ostream& os, std::ostream& paren) override;
-};
-
-/**
- * An LRAT proof for a bit-vector problem
- */
-class LfscLratBitVectorProof : public LfscClausalBitVectorProof
-{
- public:
- LfscLratBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine)
- : LfscClausalBitVectorProof(bv, proofEngine)
- {
- }
-
- void printEmptyClauseProof(std::ostream& os, std::ostream& paren) override;
-};
-
-/**
- * An Extended Resolution proof for a bit-vector problem
- */
-class LfscErBitVectorProof : public LfscClausalBitVectorProof
-{
- public:
- LfscErBitVectorProof(theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine)
- : LfscClausalBitVectorProof(bv, proofEngine)
- {
- }
-
- 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/clause_id.h b/src/proof/clause_id.h
index b2d36c9cb..5d7ec94f6 100644
--- a/src/proof/clause_id.h
+++ b/src/proof/clause_id.h
@@ -28,6 +28,13 @@ namespace CVC4 {
*/
typedef unsigned ClauseId;
+/** Reserved clauseId values used in the resolution proof. The represent,
+ * respectively, the empty clause, that adding the clause to the SAT solver was
+ * a no-op, and that an error occurred when trying to add. */
+const ClauseId ClauseIdEmpty(-1);
+const ClauseId ClauseIdUndef(-2);
+const ClauseId ClauseIdError(-3);
+
}/* CVC4 namespace */
#endif /* CVC4__PROOF__CLAUSE_ID_H */
diff --git a/src/proof/cnf_proof.cpp b/src/proof/cnf_proof.cpp
index 677bf2f8c..258e2fdb2 100644
--- a/src/proof/cnf_proof.cpp
+++ b/src/proof/cnf_proof.cpp
@@ -19,8 +19,6 @@
#include "proof/clause_id.h"
#include "proof/proof_manager.h"
-#include "proof/proof_utils.h"
-#include "proof/theory_proof.h"
#include "prop/cnf_stream.h"
#include "prop/minisat/minisat.h"
#include "prop/sat_solver_types.h"
@@ -32,11 +30,7 @@ CnfProof::CnfProof(prop::CnfStream* stream,
const std::string& name)
: d_cnfStream(stream)
, d_clauseToAssertion(ctx)
- , d_assertionToProofRule(ctx)
, d_currentAssertionStack()
- , d_currentDefinitionStack()
- , d_clauseToDefinition(ctx)
- , d_definitions()
, d_cnfDeps()
, d_name(name)
{
@@ -46,86 +40,22 @@ CnfProof::CnfProof(prop::CnfStream* stream,
CnfProof::~CnfProof() {}
-bool CnfProof::isAssertion(Node node) {
- return d_assertionToProofRule.find(node) !=
- d_assertionToProofRule.end();
-}
-
-bool CnfProof::isDefinition(Node node) {
- return d_definitions.find(node) !=
- d_definitions.end();
-}
-
-ProofRule CnfProof::getProofRule(Node node) {
- Assert(isAssertion(node));
- NodeToProofRule::iterator it = d_assertionToProofRule.find(node);
- return (*it).second;
-}
-
-ProofRule CnfProof::getProofRule(ClauseId clause) {
- TNode assertion = getAssertionForClause(clause);
- return getProofRule(assertion);
-}
-
Node CnfProof::getAssertionForClause(ClauseId clause) {
ClauseIdToNode::const_iterator it = d_clauseToAssertion.find(clause);
Assert(it != d_clauseToAssertion.end() && !(*it).second.isNull());
return (*it).second;
}
-Node CnfProof::getDefinitionForClause(ClauseId clause) {
- ClauseIdToNode::const_iterator it = d_clauseToDefinition.find(clause);
- Assert(it != d_clauseToDefinition.end());
- return (*it).second;
-}
-
-void CnfProof::registerConvertedClause(ClauseId clause, bool explanation) {
+void CnfProof::registerConvertedClause(ClauseId clause)
+{
Assert(clause != ClauseIdUndef && clause != ClauseIdError
&& clause != ClauseIdEmpty);
-
- // Explanations do not need a CNF conversion proof since they are in CNF
- // (they will only need a theory proof as they are theory valid)
- if (explanation) {
- Debug("proof:cnf") << "CnfProof::registerConvertedClause "
- << clause << " explanation? " << explanation << std::endl;
- Assert(d_explanations.find(clause) == d_explanations.end());
- d_explanations.insert(clause);
- return;
- }
-
Node current_assertion = getCurrentAssertion();
- Node current_expr = getCurrentDefinition();
- Debug("proof:cnf") << "CnfProof::registerConvertedClause "
- << clause << " assertion = " << current_assertion
- << clause << " definition = " << current_expr << std::endl;
+ Debug("proof:cnf") << "CnfProof::registerConvertedClause " << clause
+ << " assertion = " << current_assertion << std::endl;
setClauseAssertion(clause, current_assertion);
- 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) {
@@ -145,56 +75,15 @@ void CnfProof::setClauseAssertion(ClauseId clause, Node expr) {
return;
}
- d_clauseToAssertion.insert (clause, expr);
+ d_clauseToAssertion.insert(clause, expr);
}
-void CnfProof::setClauseDefinition(ClauseId clause, Node definition) {
- Debug("proof:cnf") << "CnfProof::setClauseDefinition "
- << clause << " definition " << definition << std::endl;
- // We keep the first definition
- if (d_clauseToDefinition.find(clause) != d_clauseToDefinition.end())
- return;
-
- d_clauseToDefinition.insert(clause, definition);
- d_definitions.insert(definition);
-}
-
-void CnfProof::registerAssertion(Node assertion, ProofRule reason) {
- Debug("proof:cnf") << "CnfProof::registerAssertion "
- << assertion << " reason " << reason << std::endl;
- // We can obtain the assertion from different reasons (e.g. if the
- // assertion is a lemma over shared terms both theories can generate
- // the same lemma) We only need to prove the lemma in one way, so we
- // keep the first reason.
- if (isAssertion(assertion)) {
- return;
- }
- d_assertionToProofRule.insert(assertion, reason);
-}
-
-LemmaProofRecipe CnfProof::getProofRecipe(const std::set<Node> &lemma) {
- Assert(d_lemmaToProofRecipe.find(lemma) != d_lemmaToProofRecipe.end());
- return d_lemmaToProofRecipe[lemma];
-}
-
-bool CnfProof::haveProofRecipe(const std::set<Node> &lemma) {
- return d_lemmaToProofRecipe.find(lemma) != d_lemmaToProofRecipe.end();
-}
-
-void CnfProof::setCnfDependence(Node from, Node to) {
- Debug("proof:cnf") << "CnfProof::setCnfDependence "
- << "from " << from << std::endl
- << " to " << to << std::endl;
-
- Assert(from != to);
- d_cnfDeps.insert(std::make_pair(from, to));
-}
-
-void CnfProof::pushCurrentAssertion(Node assertion) {
+void CnfProof::pushCurrentAssertion(Node assertion, bool isInput)
+{
Debug("proof:cnf") << "CnfProof::pushCurrentAssertion " << assertion
<< std::endl;
- d_currentAssertionStack.push_back(assertion);
+ d_currentAssertionStack.push_back(std::pair<Node, bool>(assertion, isInput));
Debug("proof:cnf") << "CnfProof::pushCurrentAssertion "
<< "new stack size = " << d_currentAssertionStack.size()
@@ -205,7 +94,7 @@ void CnfProof::popCurrentAssertion() {
Assert(d_currentAssertionStack.size());
Debug("proof:cnf") << "CnfProof::popCurrentAssertion "
- << d_currentAssertionStack.back() << std::endl;
+ << d_currentAssertionStack.back().first << std::endl;
d_currentAssertionStack.pop_back();
@@ -216,740 +105,12 @@ void CnfProof::popCurrentAssertion() {
Node CnfProof::getCurrentAssertion() {
Assert(d_currentAssertionStack.size());
- return d_currentAssertionStack.back();
+ return d_currentAssertionStack.back().first;
}
-void CnfProof::setProofRecipe(LemmaProofRecipe* proofRecipe) {
- Assert(proofRecipe);
- Assert(proofRecipe->getNumSteps() > 0);
- d_lemmaToProofRecipe[proofRecipe->getBaseAssertions()] = *proofRecipe;
-}
-
-void CnfProof::pushCurrentDefinition(Node definition) {
- Debug("proof:cnf") << "CnfProof::pushCurrentDefinition "
- << definition << std::endl;
-
- d_currentDefinitionStack.push_back(definition);
-}
-
-void CnfProof::popCurrentDefinition() {
- Assert(d_currentDefinitionStack.size());
-
- Debug("proof:cnf") << "CnfProof::popCurrentDefinition "
- << d_currentDefinitionStack.back() << std::endl;
-
- d_currentDefinitionStack.pop_back();
-}
-
-Node CnfProof::getCurrentDefinition() {
- Assert(d_currentDefinitionStack.size());
- return d_currentDefinitionStack.back();
-}
-
-Node CnfProof::getAtom(prop::SatVariable var) {
- prop::SatLiteral lit (var);
- Node node = d_cnfStream->getNode(lit);
- return node;
-}
-
-void CnfProof::collectAtoms(const prop::SatClause* clause,
- std::set<Node>& atoms) {
- for (unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = clause->operator[](i);
- prop::SatVariable var = lit.getSatVariable();
- TNode atom = getAtom(var);
- if (atoms.find(atom) == atoms.end()) {
- atoms.insert(atom);
- }
- }
-}
-
-prop::SatLiteral CnfProof::getLiteral(TNode atom) {
- return d_cnfStream->getLiteral(atom);
-}
-
-bool CnfProof::hasLiteral(TNode atom) {
- return d_cnfStream->hasLiteral(atom);
-}
-
-void CnfProof::ensureLiteral(TNode atom, bool noPreregistration) {
- d_cnfStream->ensureLiteral(atom, noPreregistration);
-}
-
-void CnfProof::collectAtomsForClauses(const IdToSatClause& clauses,
- std::set<Node>& atoms) {
- IdToSatClause::const_iterator it = clauses.begin();
- for (; it != clauses.end(); ++it) {
- const prop::SatClause* clause = it->second;
- collectAtoms(clause, atoms);
- }
-}
-
-void CnfProof::collectAtomsAndRewritesForLemmas(const IdToSatClause& lemmaClauses,
- std::set<Node>& atoms,
- NodePairSet& rewrites) {
- IdToSatClause::const_iterator it = lemmaClauses.begin();
- for (; it != lemmaClauses.end(); ++it) {
- const prop::SatClause* clause = it->second;
-
- // TODO: just calculate the map from ID to recipe once,
- // instead of redoing this over and over again
- std::vector<Expr> clause_expr;
- std::set<Node> clause_expr_nodes;
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = getAtom(lit.getSatVariable());
- Expr atom = node.toExpr();
- if (atom.isConst()) {
- Assert(atom == utils::mkTrue());
- continue;
- }
- clause_expr_nodes.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- LemmaProofRecipe recipe = getProofRecipe(clause_expr_nodes);
-
- for (unsigned i = 0; i < recipe.getNumSteps(); ++i) {
- const LemmaProofRecipe::ProofStep* proofStep = recipe.getStep(i);
- Node atom = proofStep->getLiteral();
-
- if (atom == Node()) {
- // The last proof step always has the empty node as its target...
- continue;
- }
-
- if (atom.getKind() == kind::NOT) {
- atom = atom[0];
- }
-
- atoms.insert(atom);
- }
-
- LemmaProofRecipe::RewriteIterator rewriteIt;
- for (rewriteIt = recipe.rewriteBegin(); rewriteIt != recipe.rewriteEnd(); ++rewriteIt) {
- rewrites.insert(NodePair(rewriteIt->first, rewriteIt->second));
-
- // The unrewritten terms also need to have literals, so insert them into atoms
- Node rewritten = rewriteIt->first;
- if (rewritten.getKind() == kind::NOT) {
- rewritten = rewritten[0];
- }
- atoms.insert(rewritten);
- }
- }
-}
-
-void CnfProof::collectAssertionsForClauses(const IdToSatClause& clauses,
- NodeSet& assertions) {
- IdToSatClause::const_iterator it = clauses.begin();
- for (; it != clauses.end(); ++it) {
- TNode used_assertion = getAssertionForClause(it->first);
- assertions.insert(used_assertion);
- // it can be the case that a definition for a clause is an assertion
- // but it is not the assertion for the clause
- // e.g. the assertions [(and a b), a]
- TNode used_definition = getDefinitionForClause(it->first);
- if (isAssertion(used_definition)) {
- assertions.insert(used_definition);
- }
- }
-}
-
-// Detects whether a clause has x v ~x for some x
-// If so, returns the positive occurence's idx first, then the negative's
-Maybe<std::pair<size_t, size_t>> CnfProof::detectTrivialTautology(
- const prop::SatClause& clause)
+bool CnfProof::getCurrentAssertionKind()
{
- // a map from a SatVariable to its previous occurence's polarity and location
- std::map<prop::SatVariable, std::pair<bool, size_t>> varsToPolsAndIndices;
- for (size_t i = 0; i < clause.size(); ++i)
- {
- prop::SatLiteral lit = clause[i];
- prop::SatVariable var = lit.getSatVariable();
- bool polarity = !lit.isNegated();
-
- // Check if this var has already occured w/ opposite polarity
- auto iter = varsToPolsAndIndices.find(var);
- if (iter != varsToPolsAndIndices.end() && iter->second.first != polarity)
- {
- if (iter->second.first)
- {
- return Maybe<std::pair<size_t, size_t>>{
- std::make_pair(iter->second.second, i)};
- }
- else
- {
- return Maybe<std::pair<size_t, size_t>>{
- std::make_pair(i, iter->second.second)};
- }
- }
- varsToPolsAndIndices[var] = std::make_pair(polarity, i);
- }
- return Maybe<std::pair<size_t, size_t>>{};
-}
-
-void LFSCCnfProof::printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren) {
- std::set<Node>::const_iterator it = atoms.begin();
- std::set<Node>::const_iterator end = atoms.end();
-
- for (;it != end; ++it) {
- os << "(decl_atom ";
- Node atom = *it;
- prop::SatVariable var = getLiteral(atom).getSatVariable();
- //FIXME hideous
- LFSCTheoryProofEngine* pe = (LFSCTheoryProofEngine*)ProofManager::currentPM()->getTheoryProofEngine();
- pe->printLetTerm(atom.toExpr(), os);
-
- os << " (\\ " << ProofManager::getVarName(var, d_name);
- os << " (\\ " << ProofManager::getAtomName(var, d_name) << "\n";
- paren << ")))";
- }
-}
-
-void LFSCCnfProof::printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap &letMap) {
- std::set<Node>::const_iterator it = atoms.begin();
- std::set<Node>::const_iterator end = atoms.end();
-
- for (;it != end; ++it) {
- os << "(decl_atom ";
- Node atom = *it;
- prop::SatVariable var = getLiteral(atom).getSatVariable();
- //FIXME hideous
- LFSCTheoryProofEngine* pe = (LFSCTheoryProofEngine*)ProofManager::currentPM()->getTheoryProofEngine();
- if (pe->printsAsBool(atom.toExpr())) os << "(p_app ";
- pe->printBoundTerm(atom.toExpr(), os, letMap);
- if (pe->printsAsBool(atom.toExpr())) os << ")";
-
- os << " (\\ " << ProofManager::getVarName(var, d_name);
- os << " (\\ " << ProofManager::getAtomName(var, d_name) << "\n";
- paren << ")))";
- }
-}
-
-// maps each expr to the position it had in the clause and the polarity it had
-Node LFSCCnfProof::clauseToNode(const prop::SatClause& clause,
- std::map<Node, unsigned>& childIndex,
- std::map<Node, bool>& childPol ) {
- std::vector< Node > children;
- for (unsigned i = 0; i < clause.size(); ++i) {
- prop::SatLiteral lit = clause[i];
- prop::SatVariable var = lit.getSatVariable();
- Node atom = getAtom(var);
- children.push_back( lit.isNegated() ? atom.negate() : atom );
- childIndex[atom] = i;
- childPol[atom] = !lit.isNegated();
- }
- return children.size()==1 ? children[0] :
- NodeManager::currentNM()->mkNode(kind::OR, children );
-}
-
-void LFSCCnfProof::printCnfProofForClause(ClauseId id,
- const prop::SatClause* clause,
- std::ostream& os,
- std::ostream& paren) {
- Debug("cnf-pf") << std::endl << std::endl << "LFSCCnfProof::printCnfProofForClause( " << id << " ) starting "
- << std::endl;
-
- os << "(satlem _ _ ";
- std::ostringstream clause_paren;
- printClause(*clause, os, clause_paren);
- os << "(clausify_false ";
-
- // FIXMEEEEEEEEEEEE
- // os <<"trust)";
- // os << clause_paren.str()
- // << " (\\ " << ProofManager::getInputClauseName(id, d_name) << "\n";
- // paren << "))";
-
- // return;
-
- Assert(clause->size() > 0);
-
- // If the clause contains x v ~x, it's easy!
- //
- // It's important to check for this case, because our other logic for
- // recording the location of variables in the clause assumes the clause is
- // not tautological
- Maybe<std::pair<size_t, size_t>> isTrivialTaut =
- detectTrivialTautology(*clause);
- if (isTrivialTaut.just())
- {
- size_t posIndexInClause = isTrivialTaut.value().first;
- size_t negIndexInClause = isTrivialTaut.value().second;
- Trace("cnf-pf") << "; Indices " << posIndexInClause << " (+) and "
- << negIndexInClause << " (-) make this clause a tautology"
- << std::endl;
-
- std::string proofOfPos =
- ProofManager::getLitName((*clause)[negIndexInClause], d_name);
- std::string proofOfNeg =
- ProofManager::getLitName((*clause)[posIndexInClause], d_name);
- os << "(contra _ " << proofOfPos << " " << proofOfNeg << ")";
- }
- else
- {
- Node base_assertion = getDefinitionForClause(id);
-
- // get the assertion for the clause id
- std::map<Node, unsigned> childIndex;
- std::map<Node, bool> childPol;
- Node assertion = clauseToNode(*clause, childIndex, childPol);
- // if there is no reason, construct assertion directly. This can happen
- // for unit clauses.
- if (base_assertion.isNull())
- {
- base_assertion = assertion;
- }
- // os_base is proof of base_assertion
- std::stringstream os_base;
-
- // checks if tautological definitional clause or top-level clause
- // and prints the proof of the top-level formula
- bool is_input = printProofTopLevel(base_assertion, os_base);
-
- if (is_input)
- {
- Debug("cnf-pf") << std::endl
- << "; base assertion is input. proof: " << os_base.str()
- << std::endl;
- }
-
- // get base assertion with polarity
- bool base_pol = base_assertion.getKind() != kind::NOT;
- base_assertion = base_assertion.getKind() == kind::NOT ? base_assertion[0]
- : base_assertion;
-
- std::map<Node, unsigned>::iterator itci = childIndex.find(base_assertion);
- bool is_in_clause = itci != childIndex.end();
- unsigned base_index = is_in_clause ? itci->second : 0;
- Trace("cnf-pf") << std::endl;
- Trace("cnf-pf") << "; input = " << is_input
- << ", is_in_clause = " << is_in_clause << ", id = " << id
- << ", assertion = " << assertion
- << ", base assertion = " << base_assertion << std::endl;
- if (!is_input)
- {
- Assert(is_in_clause);
- prop::SatLiteral blit = (*clause)[base_index];
- os_base << ProofManager::getLitName(blit, d_name);
- base_pol = !childPol[base_assertion]; // WHY? if the case is =>
- }
- Trace("cnf-pf") << "; polarity of base assertion = " << base_pol
- << std::endl;
- Trace("cnf-pf") << "; proof of base : " << os_base.str() << std::endl;
-
- bool success = false;
- if (is_input && is_in_clause && childPol[base_assertion] == base_pol)
- {
- // if both in input and in clause, the proof is trivial. this is the case
- // for unit clauses.
- Trace("cnf-pf") << "; trivial" << std::endl;
- os << "(contra _ ";
- success = true;
- prop::SatLiteral lit = (*clause)[itci->second];
- if (base_pol)
- {
- os << os_base.str() << " " << ProofManager::getLitName(lit, d_name);
- }
- else
- {
- os << ProofManager::getLitName(lit, d_name) << " " << os_base.str();
- }
- os << ")";
- } else if ((base_assertion.getKind()==kind::AND && !base_pol) ||
- ((base_assertion.getKind()==kind::OR ||
- base_assertion.getKind()==kind::IMPLIES) && base_pol)) {
- Trace("cnf-pf") << "; and/or case 1" << std::endl;
- success = true;
- std::stringstream os_main;
- std::stringstream os_paren;
- //eliminate each one
- for (int j = base_assertion.getNumChildren()-2; j >= 0; j--) {
- Trace("cnf-pf-debug") << "; base_assertion[" << j << "] is: " << base_assertion[j]
- << ", and its kind is: " << base_assertion[j].getKind() << std::endl ;
-
- Node child_base = base_assertion[j].getKind()==kind::NOT ?
- base_assertion[j][0] : base_assertion[j];
- bool child_pol = base_assertion[j].getKind()!=kind::NOT;
-
- Trace("cnf-pf-debug") << "; child " << j << " "
- << ", child base: " << child_base
- << ", child pol: " << child_pol
- << ", childPol[child_base] "
- << childPol[child_base] << ", base pol: " << base_pol << std::endl;
-
- std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
-
- if( itcic!=childIndex.end() ){
- //Assert( child_pol==childPol[child_base] );
- os_main << "(or_elim_1 _ _ ";
- prop::SatLiteral lit = (*clause)[itcic->second];
- // Should be if in the original formula it was negated
- // if( childPol[child_base] && base_pol ){
-
- // Adding the below to catch a specific case where the first child of an IMPLIES is negative,
- // in which case we need not_not introduction.
- if (base_assertion.getKind() == kind::IMPLIES && !child_pol && base_pol) {
- os_main << "(not_not_intro _ " << ProofManager::getLitName(lit, d_name) << ") ";
- } else if (childPol[child_base] && base_pol) {
- os_main << ProofManager::getLitName(lit, d_name) << " ";
- }else{
- os_main << "(not_not_intro _ " << ProofManager::getLitName(lit, d_name) << ") ";
- }
- if( base_assertion.getKind()==kind::AND ){
- os_main << "(not_and_elim _ _ ";
- os_paren << ")";
- }
- os_paren << ")";
- }else{
- success = false;
- }
- }
-
- if( success ){
- if( base_assertion.getKind()==kind::IMPLIES ){
- os_main << "(impl_elim _ _ ";
- }
- os_main << os_base.str();
- if( base_assertion.getKind()==kind::IMPLIES ){
- os_main << ")";
- }
- os_main << os_paren.str();
- int last_index = base_assertion.getNumChildren()-1;
- Node child_base = base_assertion[last_index].getKind()==kind::NOT ? base_assertion[last_index][0] : base_assertion[last_index];
- //bool child_pol = base_assertion[last_index].getKind()!=kind::NOT;
- std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
- if( itcic!=childIndex.end() ){
- os << "(contra _ ";
- prop::SatLiteral lit = (*clause)[itcic->second];
- if( childPol[child_base] && base_pol){
- os << os_main.str() << " " << ProofManager::getLitName(lit, d_name);
- }else{
- os << ProofManager::getLitName(lit, d_name) << " " << os_main.str();
- }
- os << ")";
- }else{
- success = false;
- }
- }
- }else if ((base_assertion.getKind()==kind::AND && base_pol) ||
- ((base_assertion.getKind()==kind::OR ||
- base_assertion.getKind()==kind::IMPLIES) && !base_pol)) {
-
- std::stringstream os_main;
-
- Node iatom;
- if (is_in_clause) {
- Assert(assertion.getNumChildren() == 2);
- iatom = assertion[ base_index==0 ? 1 : 0];
- } else {
- Assert(assertion.getNumChildren() == 1);
- iatom = assertion[0];
- }
-
- Trace("cnf-pf") << "; and/or case 2, iatom = " << iatom << std::endl;
- Node e_base = iatom.getKind()==kind::NOT ? iatom[0] : iatom;
- bool e_pol = iatom.getKind()!=kind::NOT;
- std::map< Node, unsigned >::iterator itcic = childIndex.find( e_base );
- if( itcic!=childIndex.end() ){
- prop::SatLiteral lit = (*clause)[itcic->second];
- //eliminate until we find iatom
- for( unsigned j=0; j<base_assertion.getNumChildren(); j++ ){
- Node child_base = base_assertion[j].getKind()==kind::NOT ? base_assertion[j][0] : base_assertion[j];
- bool child_pol = base_assertion[j].getKind()!=kind::NOT;
- if( j==0 && base_assertion.getKind()==kind::IMPLIES ){
- child_pol = !child_pol;
- }
- if( e_base==child_base && (e_pol==child_pol)==(base_assertion.getKind()==kind::AND) ){
- success = true;
- bool elimNn =( ( base_assertion.getKind()==kind::OR || ( base_assertion.getKind()==kind::IMPLIES && j==1 ) ) && e_pol );
- if( elimNn ){
- os_main << "(not_not_elim _ ";
- }
- std::stringstream os_paren;
- if( j+1<base_assertion.getNumChildren() ){
- os_main << "(and_elim_1 _ _ ";
- if( base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES ){
- os_main << "(not_" << ( base_assertion.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
- os_paren << ")";
- }
- os_paren << ")";
- }
- for( unsigned k=0; k<j; k++ ){
- os_main << "(and_elim_2 _ _ ";
- if( base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES ){
- os_main << "(not_" << ( base_assertion.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
- os_paren << ")";
- }
- os_paren << ")";
- }
- os_main << os_base.str() << os_paren.str();
- if( elimNn ){
- os_main << ")";
- }
- break;
- }
- }
- if( success ){
- os << "(contra _ ";
- if( !e_pol ){
- os << ProofManager::getLitName(lit, d_name) << " " << os_main.str();
- }else{
- os << os_main.str() << " " << ProofManager::getLitName(lit, d_name);
- }
- os << ")";
- }
- }
- }else if( base_assertion.getKind()==kind::XOR || ( base_assertion.getKind()==kind::EQUAL && base_assertion[0].getType().isBoolean() ) ){
- //eliminate negation
- int num_nots_2 = 0;
- int num_nots_1 = 0;
- Kind k;
- if( !base_pol ){
- if( base_assertion.getKind()==kind::EQUAL ){
- num_nots_2 = 1;
- }
- k = kind::EQUAL;
- }else{
- k = base_assertion.getKind();
- }
- std::vector< unsigned > indices;
- std::vector< bool > pols;
- success = true;
- int elimNum = 0;
- for( unsigned i=0; i<2; i++ ){
- Node child_base = base_assertion[i].getKind()==kind::NOT ? base_assertion[i][0] : base_assertion[i];
- bool child_pol = base_assertion[i].getKind()!=kind::NOT;
- std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
- if( itcic!=childIndex.end() ){
- indices.push_back( itcic->second );
- pols.push_back( childPol[child_base] );
- if( i==0 ){
- //figure out which way to elim
- elimNum = child_pol==childPol[child_base] ? 2 : 1;
- if( (elimNum==2)==(k==kind::EQUAL) ){
- num_nots_2++;
- }
- if( elimNum==1 ){
- num_nots_1++;
- }
- }
- }else{
- success = false;
- break;
- }
- }
- Trace("cnf-pf") << std::endl << "; num nots = " << num_nots_2 << std::endl;
- if( success ){
- os << "(contra _ ";
- std::stringstream os_base_n;
- if( num_nots_2==2 ){
- os_base_n << "(not_not_elim _ ";
- }
- os_base_n << "(or_elim_1 _ _ ";
- prop::SatLiteral lit1 = (*clause)[indices[0]];
- if( !pols[0] || num_nots_1==1 ){
- os_base_n << "(not_not_intro _ " << ProofManager::getLitName(lit1, d_name) << ") ";
- }else{
- Trace("cnf-pf-debug") << "CALLING getlitname" << std::endl;
- os_base_n << ProofManager::getLitName(lit1, d_name) << " ";
- }
- Assert(elimNum != 0);
- os_base_n << "(" << ( k==kind::EQUAL ? "iff" : "xor" ) << "_elim_" << elimNum << " _ _ ";
- if( !base_pol ){
- os_base_n << "(not_" << ( base_assertion.getKind()==kind::EQUAL ? "iff" : "xor" ) << "_elim _ _ " << os_base.str() << ")";
- }else{
- os_base_n << os_base.str();
- }
- os_base_n << "))";
- if( num_nots_2==2 ){
- os_base_n << ")";
- num_nots_2 = 0;
- }
- prop::SatLiteral lit2 = (*clause)[indices[1]];
- if( pols[1]==(num_nots_2==0) ){
- os << os_base_n.str() << " ";
- if( num_nots_2==1 ){
- os << "(not_not_intro _ " << ProofManager::getLitName(lit2, d_name) << ")";
- }else{
- os << ProofManager::getLitName(lit2, d_name);
- }
- }else{
- os << ProofManager::getLitName(lit2, d_name) << " " << os_base_n.str();
- }
- os << ")";
- }
- }else if( base_assertion.getKind()==kind::ITE ){
- std::map< unsigned, unsigned > appears;
- std::map< unsigned, Node > appears_expr;
- unsigned appears_count = 0;
- for( unsigned r=0; r<3; r++ ){
- Node child_base = base_assertion[r].getKind()==kind::NOT ? base_assertion[r][0] : base_assertion[r];
- std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
- if( itcic!=childIndex.end() ){
- appears[r] = itcic->second;
- appears_expr[r] = child_base;
- appears_count++;
- }
- }
- if( appears_count==2 ){
- success = true;
- int elimNum = 1;
- unsigned index1 = 0;
- unsigned index2 = 1;
- if( appears.find( 0 )==appears.end() ){
- elimNum = 3;
- index1 = 1;
- index2 = 2;
- }else if( appears.find( 1 )==appears.end() ){
- elimNum = 2;
- index1 = 0;
- index2 = 2;
- }
- std::stringstream os_main;
- os_main << "(or_elim_1 _ _ ";
- prop::SatLiteral lit1 = (*clause)[appears[index1]];
- if( !childPol[appears_expr[index1]] || elimNum==1 || ( elimNum==3 && !base_pol ) ){
- os_main << "(not_not_intro _ " << ProofManager::getLitName(lit1, d_name) << ") ";
- }else{
- os_main << ProofManager::getLitName(lit1, d_name) << " ";
- }
- os_main << "(" << ( base_pol ? "" : "not_" ) << "ite_elim_" << elimNum << " _ _ _ ";
- os_main << os_base.str() << "))";
- os << "(contra _ ";
- prop::SatLiteral lit2 = (*clause)[appears[index2]];
- if( !childPol[appears_expr[index2]] || !base_pol ){
- os << ProofManager::getLitName(lit2, d_name) << " " << os_main.str();
- }else{
- os << os_main.str() << " " << ProofManager::getLitName(lit2, d_name);
- }
- os << ")";
- }
- }else if( base_assertion.isConst() ){
- bool pol = base_assertion==NodeManager::currentNM()->mkConst( true );
- if( pol!=base_pol ){
- success = true;
- if( pol ){
- os << "(contra _ truth " << os_base.str() << ")";
- }else{
- os << os_base.str();
- }
- }
- }
-
- if( !success ){
- Trace("cnf-pf") << std::endl;
- Trace("cnf-pf") << ";!!!!!!!!! CnfProof : Can't process " << assertion << ", base = " << base_assertion << ", id = " << id << std::endl;
- Trace("cnf-pf") << ";!!!!!!!!! Clause is : ";
- for (unsigned i = 0; i < clause->size(); ++i) {
- Trace("cnf-pf") << (*clause)[i] << " ";
- }
- Trace("cnf-pf") << std::endl;
- os << "trust-bad";
- }
- }
-
- os << ")" << clause_paren.str()
- << " (\\ " << ProofManager::getInputClauseName(id, d_name) << "\n";
-
- paren << "))";
-}
-
-void LFSCCnfProof::printClause(const prop::SatClause& clause,
- std::ostream& os,
- std::ostream& paren) {
- for (unsigned i = 0; i < clause.size(); ++i) {
- prop::SatLiteral lit = clause[i];
- prop::SatVariable var = lit.getSatVariable();
- if (lit.isNegated()) {
- os << "(ast _ _ _ " << ProofManager::getAtomName(var, d_name) <<" (\\ " << ProofManager::getLitName(lit, d_name) << " ";
- paren << "))";
- } else {
- os << "(asf _ _ _ " << ProofManager::getAtomName(var, d_name) <<" (\\ " << ProofManager::getLitName(lit, d_name) << " ";
- paren << "))";
- }
- }
-}
-
-// print a proof of the top-level formula e, based on the input assertions
-bool LFSCCnfProof::printProofTopLevel(Node e, std::ostream& out) {
- if (!isAssertion(e)) {
- // check if deduced by CNF
- // dependence on top level fact i.e. a depends on (a and b)
- NodeToNode::const_iterator itd = d_cnfDeps.find(e);
- if (itd != d_cnfDeps.end()) {
- TNode parent = itd->second;
- //check if parent is an input assertion
- std::stringstream out_parent;
- if (printProofTopLevel(parent, out_parent)) {
- if(parent.getKind()==kind::AND ||
- (parent.getKind()==kind::NOT && (parent[0].getKind()==kind::IMPLIES ||
- parent[0].getKind()==kind::OR))) {
- Node parent_base = parent.getKind()==kind::NOT ? parent[0] : parent;
- Node e_base = e.getKind()==kind::NOT ? e[0] : e;
- bool e_pol = e.getKind()!=kind::NOT;
- for( unsigned i=0; i<parent_base.getNumChildren(); i++ ){
- Node child_base = parent_base[i].getKind()==kind::NOT ? parent_base[i][0] : parent_base[i];
- bool child_pol = parent_base[i].getKind()!=kind::NOT;
- if( parent_base.getKind()==kind::IMPLIES && i==0 ){
- child_pol = !child_pol;
- }
- if (e_base==child_base &&
- (e_pol==child_pol)==(parent_base.getKind()==kind::AND)) {
- bool elimNn = ((parent_base.getKind()==kind::OR ||
- (parent_base.getKind()==kind::IMPLIES && i==1)) && e_pol);
- if (elimNn) {
- out << "(not_not_elim _ ";
- }
- std::stringstream out_paren;
- if (i+1 < parent_base.getNumChildren()) {
- out << "(and_elim_1 _ _ ";
- if( parent_base.getKind()==kind::OR ||
- parent_base.getKind()==kind::IMPLIES ){
- out << "(not_" << ( parent_base.getKind()==kind::OR ? "or" : "impl" )
- << "_elim _ _ ";
- out_paren << ")";
- }
- out_paren << ")";
- }
- for( unsigned j=0; j<i; j++ ){
- out << "(and_elim_2 _ _ ";
- if( parent_base.getKind()==kind::OR || parent_base.getKind()==kind::IMPLIES ){
- out << "(not_" << ( parent_base.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
- out_paren << ")";
- }
- out_paren << ")";
- }
- out << out_parent.str();
- out << out_paren.str();
- if( elimNn ){
- out << ")";
- }
- return true;
- }
- }
- } else {
- Trace("cnf-pf-debug") << "; isInputAssertion : parent of " << e
- << " is not correct type (" << parent << ")" << std::endl;
- }
- } else {
- Trace("cnf-pf-debug") << "; isInputAssertion : parent of " << e
- << " is not input" << std::endl;
- }
- } else {
- Trace("cnf-pf-debug") << "; isInputAssertion : " << e
- << " has no parent" << std::endl;
- }
- return false;
- } else {
- out << ProofManager::getPreprocessedAssertionName(e);
- return true;
- }
+ return d_currentAssertionStack.back().second;
}
} /* CVC4 namespace */
diff --git a/src/proof/cnf_proof.h b/src/proof/cnf_proof.h
index 56993583e..e437ef722 100644
--- a/src/proof/cnf_proof.h
+++ b/src/proof/cnf_proof.h
@@ -27,10 +27,8 @@
#include "context/cdhashmap.h"
#include "proof/clause_id.h"
-#include "proof/lemma_proof.h"
#include "proof/sat_proof.h"
#include "util/maybe.h"
-#include "util/proof.h"
namespace CVC4 {
namespace prop {
@@ -44,11 +42,11 @@ typedef std::unordered_map<Node, Node, NodeHashFunction> NodeToNode;
typedef std::unordered_set<ClauseId> ClauseIdSet;
typedef context::CDHashMap<ClauseId, Node> ClauseIdToNode;
-typedef context::CDHashMap<Node, ProofRule, NodeHashFunction> NodeToProofRule;
-typedef std::map<std::set<Node>, LemmaProofRecipe> LemmaToRecipe;
typedef std::pair<Node, Node> NodePair;
typedef std::set<NodePair> NodePairSet;
+typedef std::unordered_set<Node, NodeHashFunction> NodeSet;
+
class CnfProof {
protected:
CVC4::prop::CnfStream* d_cnfStream;
@@ -56,23 +54,9 @@ protected:
/** Map from ClauseId to the assertion that lead to adding this clause **/
ClauseIdToNode d_clauseToAssertion;
- /** Map from assertion to reason for adding assertion **/
- NodeToProofRule d_assertionToProofRule;
-
- /** Map from lemma to the recipe for proving it **/
- LemmaToRecipe d_lemmaToProofRecipe;
-
- /** Top of stack is assertion currently being converted to CNF **/
- std::vector<Node> d_currentAssertionStack;
-
- /** Top of stack is top-level fact currently being converted to CNF **/
- std::vector<Node> d_currentDefinitionStack;
-
- /** Map from ClauseId to the top-level fact that lead to adding this clause **/
- ClauseIdToNode d_clauseToDefinition;
-
- /** Top-level facts that follow from assertions during convertAndAssert **/
- NodeSet d_definitions;
+ /** Top of stack is assertion currently being converted to CNF. Also saves
+ * whether it is input (rather than a lemma). **/
+ std::vector<std::pair<Node, bool>> d_currentAssertionStack;
/** Map from top-level fact to facts/assertion that it follows from **/
NodeToNode d_cnfDeps;
@@ -84,132 +68,36 @@ protected:
// The clause ID of the unit clause defining the false SAT literal.
ClauseId d_falseUnitClause;
- bool isDefinition(Node node);
-
- Node getDefinitionForClause(ClauseId clause);
-
std::string d_name;
public:
CnfProof(CVC4::prop::CnfStream* cnfStream,
context::Context* ctx,
const std::string& name);
-
-
- Node getAtom(prop::SatVariable var);
- prop::SatLiteral getLiteral(TNode node);
- bool hasLiteral(TNode node);
- void ensureLiteral(TNode node, bool noPreregistration = false);
-
- void collectAtoms(const prop::SatClause* clause,
- std::set<Node>& atoms);
- void collectAtomsForClauses(const IdToSatClause& clauses,
- std::set<Node>& atoms);
- void collectAtomsAndRewritesForLemmas(const IdToSatClause& lemmaClauses,
- std::set<Node>& atoms,
- NodePairSet& rewrites);
- void collectAssertionsForClauses(const IdToSatClause& clauses,
- NodeSet& assertions);
+ ~CnfProof();
/** Methods for logging what the CnfStream does **/
// map the clause back to the current assertion where it came from
- // if it is an explanation, it does not have a CNF proof since it is
- // 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);
+ void registerConvertedClause(ClauseId clause);
/** Clause is one of the clauses defining top-level assertion node*/
void setClauseAssertion(ClauseId clause, Node node);
- void registerAssertion(Node assertion, ProofRule reason);
- void setCnfDependence(Node from, Node to);
-
- void pushCurrentAssertion(Node assertion); // the current assertion being converted
+ /** Current assertion being converted and whether it is an input (rather than
+ * a lemma) */
+ void pushCurrentAssertion(Node assertion, bool isInput = false);
void popCurrentAssertion();
Node getCurrentAssertion();
-
- void pushCurrentDefinition(Node assertion); // the current Tseitin definition being converted
- void popCurrentDefinition();
- Node getCurrentDefinition();
+ bool getCurrentAssertionKind();
/**
* Checks whether the assertion stack is empty.
*/
bool isAssertionStackEmpty() const { return d_currentAssertionStack.empty(); }
- void setProofRecipe(LemmaProofRecipe* proofRecipe);
- LemmaProofRecipe getProofRecipe(const std::set<Node> &lemma);
- bool haveProofRecipe(const std::set<Node> &lemma);
-
// accessors for the leaf assertions that are being converted to CNF
- bool isAssertion(Node node);
- ProofRule getProofRule(Node assertion);
- ProofRule getProofRule(ClauseId clause);
Node getAssertionForClause(ClauseId clause);
-
- /** Virtual methods for printing things **/
- virtual void printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren) = 0;
- virtual void printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap &letMap) = 0;
-
- // Detects whether a clause has x v ~x for some x
- // If so, returns the positive occurence's idx first, then the negative's
- static Maybe<std::pair<size_t, size_t>> detectTrivialTautology(
- const prop::SatClause& clause);
- virtual void printClause(const prop::SatClause& clause,
- std::ostream& os,
- std::ostream& paren) = 0;
- virtual void printCnfProofForClause(ClauseId id,
- const prop::SatClause* clause,
- std::ostream& os,
- std::ostream& paren) = 0;
- virtual ~CnfProof();
};/* class CnfProof */
-class LFSCCnfProof : public CnfProof {
- Node clauseToNode( const prop::SatClause& clause,
- std::map<Node, unsigned>& childIndex,
- std::map<Node, bool>& childPol );
- bool printProofTopLevel(Node e, std::ostream& out);
-public:
- LFSCCnfProof(CVC4::prop::CnfStream* cnfStream,
- context::Context* ctx,
- const std::string& name)
- : CnfProof(cnfStream, ctx, name)
- {}
- ~LFSCCnfProof() {}
-
- void printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren) override;
-
- void printAtomMapping(const std::set<Node>& atoms,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap& letMap) override;
-
- void printClause(const prop::SatClause& clause,
- std::ostream& os,
- std::ostream& paren) override;
- void printCnfProofForClause(ClauseId id,
- const prop::SatClause* clause,
- std::ostream& os,
- std::ostream& paren) override;
-};/* class LFSCCnfProof */
-
} /* CVC4 namespace */
#endif /* CVC4__CNF_PROOF_H */
diff --git a/src/proof/dimacs.cpp b/src/proof/dimacs.cpp
deleted file mode 100644
index d9d9f8c1c..000000000
--- a/src/proof/dimacs.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/********************* */
-/*! \file dimacs.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief DIMACS SAT Problem Format
- **
- ** Defines serialization for SAT problems as DIMACS
- **/
-
-#include "proof/dimacs.h"
-
-#include "base/check.h"
-
-#include <iostream>
-
-namespace CVC4 {
-namespace proof {
-
-// Prints the literal as a (+) or (-) int
-// Not operator<< b/c that represents negation as ~
-std::ostream& textOut(std::ostream& o, const prop::SatLiteral& l)
-{
- if (l.isNegated())
- {
- o << "-";
- }
- return o << l.getSatVariable() + 1;
-}
-
-// 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 prop::SatClause& c)
-{
- for (const auto& l : c)
- {
- textOut(o, l) << " ";
- }
- return o << "0";
-}
-
-void printDimacs(std::ostream& o,
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIndices)
-{
- size_t maxVar = 0;
- for (const ClauseId i : usedIndices)
- {
- const prop::SatClause& c = clauses.at(i);
- for (const auto& l : c)
- {
- if (l.getSatVariable() + 1 > maxVar)
- {
- maxVar = l.getSatVariable() + 1;
- }
- }
- }
- o << "p cnf " << maxVar << " " << usedIndices.size() << '\n';
- for (const ClauseId i : usedIndices)
- {
- const prop::SatClause& c = clauses.at(i);
- for (const auto& l : c)
- {
- if (l.isNegated())
- {
- o << '-';
- }
- o << l.getSatVariable() + 1 << " ";
- }
- o << "0\n";
- }
-}
-
-std::vector<prop::SatClause> parseDimacs(std::istream& in)
-{
- std::string tag;
- uint64_t nVars;
- uint64_t nClauses;
-
- in >> tag;
- Assert(in.good());
- Assert(tag == "p");
-
- in >> tag;
- Assert(in.good());
- Assert(tag == "cnf");
-
- in >> nVars;
- Assert(nVars >= 0);
-
- in >> nClauses;
- Assert(nClauses >= 0);
-
- std::vector<prop::SatClause> cnf;
- for (uint64_t i = 0; i < nClauses; ++i)
- {
- cnf.emplace_back();
- int64_t lit;
- in >> lit;
- Assert(in.good());
- while (lit != 0)
- {
- cnf.back().emplace_back(std::abs(lit) - 1, lit < 0);
- in >> lit;
- Assert(static_cast<uint64_t>(std::abs(lit)) <= nVars);
- Assert(in.good());
- }
- }
-
- return cnf;
-}
-
-} // namespace proof
-} // namespace CVC4
diff --git a/src/proof/dimacs.h b/src/proof/dimacs.h
deleted file mode 100644
index 405b33208..000000000
--- a/src/proof/dimacs.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/********************* */
-/*! \file dimacs.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief DIMACS SAT Problem Format
- **
- ** Defines serialization/deserialization for SAT problems as DIMACS
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__DIMACS_H
-#define CVC4__PROOF__DIMACS_H
-
-#include <iosfwd>
-#include <memory>
-#include <unordered_map>
-
-#include "proof/clause_id.h"
-#include "prop/sat_solver_types.h"
-
-namespace CVC4 {
-namespace proof {
-
-/**
- * Prints the literal as a (+) or (-) int
- * Not operator<< b/c that represents negation as ~
- *
- * @param o where to print
- * @param l the literal to print
- *
- * @return the original stream
- */
-std::ostream& textOut(std::ostream& o, const prop::SatLiteral& l);
-
-/**
- * Prints the clause as a space-separated list of ints
- * Not operator<< b/c that represents literal negation as ~
- *
- * @param o where to print
- * @param c the clause to print
- *
- * @return the original stream
- */
-std::ostream& textOut(std::ostream& o, const prop::SatClause& c);
-
-/**
- * Prints a CNF formula in DIMACS format
- *
- * @param o where to print to
- * @param usedClauses the CNF formula
- */
-void printDimacs(std::ostream& o,
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIndices);
-
-std::vector<prop::SatClause> parseDimacs(std::istream& i);
-
-} // namespace proof
-} // namespace CVC4
-
-#endif // CVC4__PROOF__DIMACS_H
diff --git a/src/proof/drat/drat_proof.cpp b/src/proof/drat/drat_proof.cpp
deleted file mode 100644
index ee9c42d77..000000000
--- a/src/proof/drat/drat_proof.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-/********************* */
-/*! \file drat_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief 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 errmsg;
- errmsg << "Invalid instruction in Drat proof. Instruction bits: "
- << std::bitset<8>(*i)
- << ". Expected 'a' (01100001) or 'd' "
- "(01100100).";
- throw InvalidDratProofException(errmsg.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(), "bb") << ") ";
- }
- 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
deleted file mode 100644
index 1213c80c7..000000000
--- a/src/proof/drat/drat_proof.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/********************* */
-/*! \file drat_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief 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/er/er_proof.cpp b/src/proof/er/er_proof.cpp
deleted file mode 100644
index 54b0fd879..000000000
--- a/src/proof/er/er_proof.cpp
+++ /dev/null
@@ -1,399 +0,0 @@
-/********************* */
-/*! \file er_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Andres Noetzli, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief ER Proof Format
- **
- ** Declares C++ types that represent an ER/TRACECHECK proof.
- ** Defines serialization for these types.
- **
- ** You can find details about the way ER is encoded in the TRACECHECK
- ** format at these locations:
- ** https://github.com/benjaminkiesl/drat2er
- ** http://www.cs.utexas.edu/users/marijn/publications/ijcar18.pdf
- **/
-
-#include "proof/er/er_proof.h"
-
-#include <unistd.h>
-#include <algorithm>
-#include <fstream>
-#include <iostream>
-#include <iterator>
-#include <sstream>
-#include <unordered_set>
-
-#include "base/check.h"
-#include "base/map_util.h"
-#include "proof/dimacs.h"
-#include "proof/lfsc_proof_printer.h"
-#include "proof/proof_manager.h"
-
-#if CVC4_USE_DRAT2ER
-#include "drat2er.h"
-#include "drat2er_options.h"
-#endif
-
-namespace CVC4 {
-namespace proof {
-namespace er {
-
-TraceCheckProof TraceCheckProof::fromText(std::istream& in)
-{
- TraceCheckProof pf;
- TraceCheckIdx idx = 0;
- int64_t token = 0;
-
- // For each line of the proof, start with the idx
- // If there is no idx, then you're done!
- in >> idx;
- for (; !in.eof(); in >> idx)
- {
- Assert(in.good());
-
- // Then parse the clause (it's 0-terminated)
- std::vector<prop::SatLiteral> clause;
- in >> token;
- for (; token != 0; in >> token)
- {
- clause.emplace_back(std::abs(token) - 1, token < 0);
- }
-
- // Then parse the chain of literals (it's also 0-terminated)
- std::vector<TraceCheckIdx> chain;
- in >> token;
- for (; token != 0; in >> token)
- {
- Assert(token > 0);
- chain.push_back(token);
- }
-
- // Add the line to the proof
- pf.d_lines.emplace_back(idx, std::move(clause), std::move(chain));
- }
- return pf;
-}
-
-ErProof ErProof::fromBinaryDratProof(
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIds,
- const std::string& dratBinary,
- TimerStat& toolTimer)
-{
- std::string formulaFilename("cvc4-dimacs-XXXXXX");
- std::string dratFilename("cvc4-drat-XXXXXX");
- std::string tracecheckFilename("cvc4-tracecheck-er-XXXXXX");
-
- // Write the formula
- std::unique_ptr<std::fstream> formStream = openTmpFile(&formulaFilename);
- printDimacs(*formStream, clauses, usedIds);
- formStream->close();
-
- // Write the (binary) DRAT proof
- std::unique_ptr<std::fstream> dratStream = openTmpFile(&dratFilename);
- (*dratStream) << dratBinary;
- dratStream->close();
-
- std::unique_ptr<std::fstream> tracecheckStream =
- openTmpFile(&tracecheckFilename);
-
- // Invoke drat2er
- {
- CodeTimer blockTimer{toolTimer};
-#if CVC4_USE_DRAT2ER
- drat2er::TransformDRATToExtendedResolution(formulaFilename,
- dratFilename,
- tracecheckFilename,
- false,
- drat2er::options::QUIET,
- false);
-#else
- Unimplemented()
- << "ER proof production requires drat2er.\n"
- << "Run contrib/get-drat2er, reconfigure with --drat2er, and rebuild";
-#endif
- }
-
- // Parse the resulting TRACECHECK proof into an ER proof.
- TraceCheckProof pf = TraceCheckProof::fromText(*tracecheckStream);
- ErProof proof(clauses, usedIds, std::move(pf));
- tracecheckStream->close();
-
- remove(formulaFilename.c_str());
- remove(dratFilename.c_str());
- remove(tracecheckFilename.c_str());
-
- return proof;
-}
-
-ErProof::ErProof(const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIds,
- TraceCheckProof&& tracecheck)
- : d_inputClauseIds(), d_definitions(), d_tracecheck(tracecheck)
-{
- // Step zero, save input clause Ids for future printing
- d_inputClauseIds = usedIds;
-
- // Make a list of (idx, clause pairs), the used ones.
- std::vector<std::pair<ClauseId, prop::SatClause>> usedClauses;
- std::transform(
- usedIds.begin(),
- usedIds.end(),
- std::back_inserter(usedClauses),
- [&](const ClauseId& i) { return make_pair(i, clauses.at(i)); });
-
- // Step one, verify the formula starts the proof
- if (Configuration::isAssertionBuild())
- {
- for (size_t i = 0, n = usedClauses.size(); i < n; ++i)
- {
- Assert(d_tracecheck.d_lines[i].d_idx = i + 1);
- Assert(d_tracecheck.d_lines[i].d_chain.size() == 0);
- std::unordered_set<prop::SatLiteral, prop::SatLiteralHashFunction>
- traceCheckClause{d_tracecheck.d_lines[i].d_clause.begin(),
- d_tracecheck.d_lines[i].d_clause.end()};
- std::unordered_set<prop::SatLiteral, prop::SatLiteralHashFunction>
- originalClause{usedClauses[i].second.begin(),
- usedClauses[i].second.end()};
- Assert(traceCheckClause == originalClause);
- }
- }
-
- // Step two, identify definitions. They correspond to lines that follow the
- // input lines, are in bounds, and have no justifying chain.
- for (size_t i = usedClauses.size(), n = d_tracecheck.d_lines.size();
- i < n && d_tracecheck.d_lines[i].d_chain.size() == 0;)
- {
- prop::SatClause c = d_tracecheck.d_lines[i].d_clause;
- Assert(c.size() > 0);
- Assert(!c[0].isNegated());
-
- // Get the new variable of the definition -- the first variable of the
- // first clause
- prop::SatVariable newVar = c[0].getSatVariable();
-
- // The rest of the literals in the clause of the 'other literals' of the def
- std::vector<prop::SatLiteral> otherLiterals{++c.begin(), c.end()};
-
- size_t nLinesForThisDef = 2 + otherLiterals.size();
- // Look at the negation of the second literal in the second clause to get
- // the old literal
- AlwaysAssert(d_tracecheck.d_lines.size() > i + 1)
- << "Malformed definition in TRACECHECK proof from drat2er";
- d_definitions.emplace_back(newVar,
- ~d_tracecheck.d_lines[i + 1].d_clause[1],
- std::move(otherLiterals));
-
- // Advance over the lines for this definition
- i += nLinesForThisDef;
- }
-}
-
-void ErProof::outputAsLfsc(std::ostream& os) const
-{
- // How many parens to close?
- size_t parenCount = 0;
- std::unordered_set<prop::SatVariable> newVariables;
-
- // Print Definitions
- for (const ErDefinition& def : d_definitions)
- {
- os << "\n (decl_definition ("
- << (def.d_oldLiteral.isNegated() ? "neg " : "pos ")
- << ProofManager::getVarName(def.d_oldLiteral.getSatVariable(), "bb")
- << ") ";
- LFSCProofPrinter::printSatClause(def.d_otherLiterals, os, "bb");
- os << " (\\ er.v" << def.d_newVariable << " (\\ er.def"
- << def.d_newVariable;
- newVariables.insert(def.d_newVariable);
- }
- parenCount += 3 * d_definitions.size();
-
- // Clausify Definitions
- TraceCheckIdx firstDefClause = d_inputClauseIds.size() + 1;
- for (const ErDefinition& def : d_definitions)
- {
- os << "\n (clausify_definition _ _ _ "
- << "er.def" << def.d_newVariable << " _ (\\ er.c" << firstDefClause
- << " (\\ er.c" << (firstDefClause + 1) << " (\\ er.cnf"
- << def.d_newVariable;
-
- firstDefClause += 2 + def.d_otherLiterals.size();
- }
- parenCount += 4 * d_definitions.size();
-
- // Unroll proofs of CNF to proofs of clauses
- firstDefClause = d_inputClauseIds.size() + 1;
- for (const ErDefinition& def : d_definitions)
- {
- for (size_t i = 0, n = def.d_otherLiterals.size(); i < n; ++i)
- {
- // Compute the name of the CNF proof we're unrolling in this step
- std::ostringstream previousCnfProof;
- previousCnfProof << "er.cnf" << def.d_newVariable;
- if (i != 0)
- {
- // For all but the first unrolling, the previous CNF has an unrolling
- // number attached
- previousCnfProof << ".u" << i;
- }
-
- // Prove the first clause in the CNF
- os << "\n (@ ";
- os << "er.c" << (firstDefClause + 2 + i);
- os << " (common_tail_cnf_prove_head _ _ _ " << previousCnfProof.str()
- << ")";
-
- // Prove the rest of the CNF
- os << "\n (@ ";
- os << "er.cnf" << def.d_newVariable << ".u" << (i + 1);
- os << " (common_tail_cnf_prove_tail _ _ _ " << previousCnfProof.str()
- << ")";
- }
- parenCount += 2 * def.d_otherLiterals.size();
-
- firstDefClause += 2 + def.d_otherLiterals.size();
- }
-
- // NB: At this point `firstDefClause` points to the first clause resulting
- // from a resolution chain
-
- // Now, elaborate each resolution chain
- for (size_t cId = firstDefClause, nLines = d_tracecheck.d_lines.size();
- cId <= nLines;
- ++cId)
- {
- const std::vector<TraceCheckIdx>& chain =
- d_tracecheck.d_lines[cId - 1].d_chain;
- const std::vector<prop::SatLiteral> pivots = computePivotsForChain(chain);
- Assert(chain.size() > 0);
- Assert(chain.size() == pivots.size() + 1);
-
- os << "\n (satlem_simplify _ _ _ ";
- parenCount += 1;
-
- // Print resolution openings (reverse order)
- for (int64_t i = pivots.size() - 1; i >= 0; --i)
- {
- prop::SatLiteral pivot = pivots[i];
- os << "(" << (pivot.isNegated() ? 'Q' : 'R') << " _ _ ";
- }
-
- // Print resolution start
- writeIdForClauseProof(os, chain[0]);
- os << " ";
-
- // Print resolution closings (forward order)
- for (size_t i = 0, n = pivots.size(); i < n; ++i)
- {
- prop::SatVariable pivotVar = pivots[i].getSatVariable();
- TraceCheckIdx clauseId = chain[i + 1];
- writeIdForClauseProof(os, clauseId);
- os << " ";
- if (ContainsKey(newVariables, pivotVar))
- {
- // This is a defined variable
- os << "er.v" << pivotVar;
- }
- else
- {
- os << ProofManager::getVarName(pivotVar, "bb");
- }
- os << ") ";
- }
- os << "(\\ er.c" << cId;
- parenCount += 1;
- }
-
- // Write proof of bottom
- Assert(d_tracecheck.d_lines.back().d_clause.size() == 0)
- << "The TRACECHECK proof from drat2er did not prove bottom.";
- os << "\n er.c" << d_tracecheck.d_lines.back().d_idx
- << " ; (holds cln)\n";
-
- // Finally, close the parentheses!
- std::fill_n(std::ostream_iterator<char>(os), parenCount, ')');
-}
-
-namespace {
-/**
- * Resolves two clauses
- *
- * @param dest one of the inputs, and the output too. **This is an input and
- * output**
- * @param src the other input
- *
- * @return the unique literal that was resolved on, with the polarization that
- * it originally had in `dest`.
- *
- * For example, if dest = (1 3 -4 5) and src = (1 -3 5), then 3 is returned and
- * after the call dest = (1 -4 5).
- */
-prop::SatLiteral resolveModify(
- std::unordered_set<prop::SatLiteral, prop::SatLiteralHashFunction>& dest,
- const prop::SatClause& src)
-{
- CVC4_UNUSED bool foundPivot = false;
- prop::SatLiteral pivot(0, false);
-
- for (prop::SatLiteral lit : src)
- {
- auto negationLocation = dest.find(~lit);
- if (negationLocation != dest.end())
- {
-#ifdef CVC4_ASSERTIONS
- Assert(!foundPivot);
- foundPivot = true;
-#endif
- dest.erase(negationLocation);
- pivot = ~lit;
- }
- dest.insert(lit);
- }
-
- Assert(foundPivot);
- return pivot;
-}
-} // namespace
-
-std::vector<prop::SatLiteral> ErProof::computePivotsForChain(
- const std::vector<TraceCheckIdx>& chain) const
-{
- std::vector<prop::SatLiteral> pivots;
-
- const prop::SatClause& first = d_tracecheck.d_lines[chain[0] - 1].d_clause;
- std::unordered_set<prop::SatLiteral, prop::SatLiteralHashFunction>
- runningClause{first.begin(), first.end()};
-
- for (auto idx = ++chain.cbegin(), end = chain.cend(); idx != end; ++idx)
- {
- pivots.push_back(
- resolveModify(runningClause, d_tracecheck.d_lines[*idx - 1].d_clause));
- }
- return pivots;
-}
-
-void ErProof::writeIdForClauseProof(std::ostream& o, TraceCheckIdx i) const
-{
- if (i <= d_inputClauseIds.size())
- {
- // This clause is an input clause! Ask the ProofManager for its name
- o << ProofManager::getInputClauseName(d_inputClauseIds[i - 1], "bb");
- }
- else
- {
- // This clause was introduced by a definition or resolution chain
- o << "er.c" << i;
- }
-}
-
-} // namespace er
-} // namespace proof
-} // namespace CVC4
diff --git a/src/proof/er/er_proof.h b/src/proof/er/er_proof.h
deleted file mode 100644
index 6f7239ef2..000000000
--- a/src/proof/er/er_proof.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/********************* */
-/*! \file er_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief ER Proof Format
- **
- ** Declares C++ types that represent an ER/TRACECHECK proof.
- ** Defines serialization for these types.
- **
- ** You can find details about the way ER is encoded in the TRACECHECK
- ** format at these locations:
- ** https://github.com/benjaminkiesl/drat2er
- ** http://www.cs.utexas.edu/users/marijn/publications/ijcar18.pdf
- **
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__ER__ER_PROOF_H
-#define CVC4__PROOF__ER__ER_PROOF_H
-
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-#include "proof/clause_id.h"
-#include "prop/sat_solver_types.h"
-#include "util/statistics_registry.h"
-
-namespace CVC4 {
-namespace proof {
-namespace er {
-
-/**
- * A definition of the form:
- * newVar <-> p v (~x_1 ^ ~x_2 ^ ... ^ ~x_n)
- */
-struct ErDefinition
-{
- ErDefinition(prop::SatVariable newVariable,
- prop::SatLiteral oldLiteral,
- std::vector<prop::SatLiteral>&& otherLiterals)
- : d_newVariable(newVariable),
- d_oldLiteral(oldLiteral),
- d_otherLiterals(otherLiterals)
- {
- }
-
- // newVar
- prop::SatVariable d_newVariable;
- // p
- prop::SatLiteral d_oldLiteral;
- // A list of the x_i's
- std::vector<prop::SatLiteral> d_otherLiterals;
-};
-
-// For representing a clause's index within a TRACECHECK proof.
-using TraceCheckIdx = size_t;
-
-/**
- * A single line in a TRACECHECK proof.
- *
- * Consists of the index of a new clause, the literals of that clause, and the
- * indices for preceding clauses which can be combined in a resolution chain to
- * produce this new clause.
- */
-struct TraceCheckLine
-{
- TraceCheckLine(TraceCheckIdx idx,
- std::vector<prop::SatLiteral>&& clause,
- std::vector<TraceCheckIdx>&& chain)
- : d_idx(idx), d_clause(clause), d_chain(chain)
- {
- }
-
- // The index of the new clause
- TraceCheckIdx d_idx;
- // The new clause
- std::vector<prop::SatLiteral> d_clause;
- /**
- * Indices of clauses which must be resolved to produce this new clause.
- * While the TRACECHECK format does not specify the order, we require them to
- * be in resolution-order.
- */
- std::vector<TraceCheckIdx> d_chain;
-};
-
-/**
- * A TRACECHECK proof -- just a list of lines
- */
-struct TraceCheckProof
-{
- static TraceCheckProof fromText(std::istream& in);
- TraceCheckProof() : d_lines() {}
-
- // The lines of this proof.
- std::vector<TraceCheckLine> d_lines;
-};
-
-/**
- * An extended resolution proof.
- * It supports resolution, along with extensions of the form
- *
- * newVar <-> p v (~x_1 ^ ~x_2 ^ ... ^ ~x_n)
- */
-class ErProof
-{
- public:
- /**
- * Construct an ER proof from a DRAT proof, using drat2er
- *
- * @param clauses A store of clauses that might be in our formula
- * @param usedIds the ids of clauses that are actually in our formula
- * @param dratBinary The DRAT proof from the SAT solver, as a binary stream
- *
- * @return the Er proof and a timer of the execution of drat2er
- */
- static ErProof fromBinaryDratProof(
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIds,
- const std::string& dratBinary,
- TimerStat& toolTimer
- );
-
- /**
- * Construct an ER proof from a TRACECHECK ER proof
- *
- * This basically just identifies groups of lines which correspond to
- * definitions, and extracts them.
- *
- * @param clauses A store of clauses that might be in our formula
- * @param usedIds the ids of clauses that are actually in our formula
- * @param tracecheck The TRACECHECK proof, as a stream.
- */
- ErProof(const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId>& usedIds,
- TraceCheckProof&& tracecheck);
-
- /**
- * Write the ER proof as an LFSC value of type (holds cln).
- * The format is from the LFSC signature er.plf
- *
- * Reads the current `ProofManager` to determine what the variables should be
- * named.
- *
- * @param os the stream to write to
- */
- void outputAsLfsc(std::ostream& os) const;
-
- const std::vector<ClauseId>& getInputClauseIds() const
- {
- return d_inputClauseIds;
- }
-
- const std::vector<ErDefinition>& getDefinitions() const
- {
- return d_definitions;
- }
-
- const TraceCheckProof& getTraceCheckProof() const { return d_tracecheck; }
-
- private:
- /**
- * Creates an empty ErProof.
- */
- ErProof() : d_inputClauseIds(), d_definitions(), d_tracecheck() {}
-
- /**
- * Computes the pivots on the basis of which an in-order resolution chain is
- * resolved.
- *
- * c0 c1
- * \ / Clauses c_i being resolved in a chain around
- * v1 c2 pivots v_i.
- * \ /
- * v2 c3
- * \ /
- * v3 c4
- * \ /
- * v4
- *
- *
- * @param chain the chain, of N clause indices
- *
- * @return a list of N - 1 variables, the list ( v_i ) from i = 1 to N - 1
- */
- std::vector<prop::SatLiteral> computePivotsForChain(
- const std::vector<TraceCheckIdx>& chain) const;
-
- /**
- * Write the LFSC identifier for the proof of a clause
- *
- * @param o where to write to
- * @param i the TRACECHECK index for the clause whose proof identifier to
- * print
- */
- void writeIdForClauseProof(std::ostream& o, TraceCheckIdx i) const;
-
- // A list of the Ids for the input clauses, in order.
- std::vector<ClauseId> d_inputClauseIds;
- // A list of new variable definitions, in order.
- std::vector<ErDefinition> d_definitions;
- // The underlying TRACECHECK proof.
- TraceCheckProof d_tracecheck;
-};
-
-} // namespace er
-} // namespace proof
-} // namespace CVC4
-
-#endif // CVC4__PROOF__ER__ER_PROOF_H
diff --git a/src/proof/lemma_proof.cpp b/src/proof/lemma_proof.cpp
deleted file mode 100644
index bdebb6cfc..000000000
--- a/src/proof/lemma_proof.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/********************* */
-/*! \file lemma_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** A class for recoding the steps required in order to prove a theory lemma.
-
-**/
-
-#include "proof/lemma_proof.h"
-#include "theory/rewriter.h"
-
-namespace CVC4 {
-
-LemmaProofRecipe::ProofStep::ProofStep(theory::TheoryId theory, Node literalToProve) :
- d_theory(theory), d_literalToProve(literalToProve) {
-}
-
-theory::TheoryId LemmaProofRecipe::ProofStep::getTheory() const {
- return d_theory;
-}
-
-Node LemmaProofRecipe::ProofStep::getLiteral() const {
- return d_literalToProve;
-}
-
-void LemmaProofRecipe::ProofStep::addAssertion(const Node& assertion) {
- d_assertions.insert(assertion);
-}
-
-std::set<Node> LemmaProofRecipe::ProofStep::getAssertions() const {
- return d_assertions;
-}
-
-void LemmaProofRecipe::addStep(ProofStep& proofStep) {
- d_proofSteps.push_back(proofStep);
-}
-
-std::set<Node> LemmaProofRecipe::getMissingAssertionsForStep(unsigned index) const {
- Assert(index < d_proofSteps.size());
-
- std::set<Node> existingAssertions = getBaseAssertions();
-
- // The literals for all the steps "before" (i.e. behind) the step indicated
- // by the index are considered "existing"
- size_t revIndex = d_proofSteps.size() - 1 - index;
- for (size_t i = d_proofSteps.size() - 1; i != revIndex; --i)
- {
- existingAssertions.insert(d_proofSteps[i].getLiteral().negate());
- }
-
- std::set<Node> neededAssertions = d_proofSteps[revIndex].getAssertions();
-
- std::set<Node> result;
- std::set_difference(neededAssertions.begin(), neededAssertions.end(),
- existingAssertions.begin(), existingAssertions.end(),
- std::inserter(result, result.begin()));
- return result;
-}
-
-void LemmaProofRecipe::dump(const char *tag) const {
-
- if (d_proofSteps.size() == 1) {
- Debug(tag) << std::endl << "[Simple lemma]" << std::endl << std::endl;
- }
-
- if (d_originalLemma != Node()) {
- Debug(tag) << std::endl << "Original lemma: " << d_originalLemma << std::endl << std::endl;
- }
-
- unsigned count = 1;
- Debug(tag) << "Base assertions:" << std::endl;
- for (std::set<Node>::iterator baseIt = d_baseAssertions.begin();
- baseIt != d_baseAssertions.end();
- ++baseIt) {
- Debug(tag) << "\t#" << count << ": " << "\t" << *baseIt << std::endl;
- ++count;
- }
-
- Debug(tag) << std::endl << std::endl << "Proof steps:" << std::endl;
-
- count = 1;
- for (const auto& step : (*this)) {
- Debug(tag) << "\tStep #" << count << ": " << "\t[" << step.getTheory() << "] ";
- if (step.getLiteral() == Node()) {
- Debug(tag) << "Contradiction";
- } else {
- Debug(tag) << step.getLiteral();
- }
-
- Debug(tag) << std::endl;
-
- std::set<Node> missingAssertions = getMissingAssertionsForStep(count - 1);
- for (std::set<Node>::const_iterator it = missingAssertions.begin(); it != missingAssertions.end(); ++it) {
- Debug(tag) << "\t\t\tMissing assertion for step: " << *it << std::endl;
- }
-
- Debug(tag) << std::endl;
- ++count;
- }
-
- if (!d_assertionToExplanation.empty()) {
- Debug(tag) << std::endl << "Rewrites used:" << std::endl;
- count = 1;
- for (std::map<Node, Node>::const_iterator rewrite = d_assertionToExplanation.begin();
- rewrite != d_assertionToExplanation.end();
- ++rewrite) {
- Debug(tag) << "\tRewrite #" << count << ":" << std::endl
- << "\t\t" << rewrite->first
- << std::endl << "\t\trewritten into" << std::endl
- << "\t\t" << rewrite->second
- << std::endl << std::endl;
- ++count;
- }
- }
-}
-
-void LemmaProofRecipe::addBaseAssertion(Node baseAssertion) {
- d_baseAssertions.insert(baseAssertion);
-}
-
-std::set<Node> LemmaProofRecipe::getBaseAssertions() const {
- return d_baseAssertions;
-}
-
-theory::TheoryId LemmaProofRecipe::getTheory() const {
- Assert(d_proofSteps.size() > 0);
- return d_proofSteps.back().getTheory();
-}
-
-void LemmaProofRecipe::addRewriteRule(Node assertion, Node explanation) {
- if (d_assertionToExplanation.find(assertion) != d_assertionToExplanation.end()) {
- Assert(d_assertionToExplanation[assertion] == explanation);
- }
-
- d_assertionToExplanation[assertion] = explanation;
-}
-
-bool LemmaProofRecipe::wasRewritten(Node assertion) const {
- return d_assertionToExplanation.find(assertion) != d_assertionToExplanation.end();
-}
-
-Node LemmaProofRecipe::getExplanation(Node assertion) const {
- Assert(d_assertionToExplanation.find(assertion)
- != d_assertionToExplanation.end());
- return d_assertionToExplanation.find(assertion)->second;
-}
-
-LemmaProofRecipe::RewriteIterator LemmaProofRecipe::rewriteBegin() const {
- return d_assertionToExplanation.begin();
-}
-
-LemmaProofRecipe::RewriteIterator LemmaProofRecipe::rewriteEnd() const {
- return d_assertionToExplanation.end();
-}
-
-LemmaProofRecipe::iterator LemmaProofRecipe::begin() {
- return d_proofSteps.rbegin();
-}
-
-LemmaProofRecipe::iterator LemmaProofRecipe::end() {
- return d_proofSteps.rend();
-}
-
-LemmaProofRecipe::const_iterator LemmaProofRecipe::begin() const {
- return d_proofSteps.crbegin();
-}
-
-LemmaProofRecipe::const_iterator LemmaProofRecipe::end() const {
- return d_proofSteps.crend();
-}
-
-bool LemmaProofRecipe::operator<(const LemmaProofRecipe& other) const {
- return d_baseAssertions < other.d_baseAssertions;
- }
-
-bool LemmaProofRecipe::simpleLemma() const {
- return d_proofSteps.size() == 1;
-}
-
-bool LemmaProofRecipe::compositeLemma() const {
- return !simpleLemma();
-}
-
-const LemmaProofRecipe::ProofStep* LemmaProofRecipe::getStep(unsigned index) const {
- Assert(index < d_proofSteps.size());
-
- size_t revIndex = d_proofSteps.size() - 1 - index;
-
- return &d_proofSteps[revIndex];
-}
-
-LemmaProofRecipe::ProofStep* LemmaProofRecipe::getStep(unsigned index) {
- Assert(index < d_proofSteps.size());
-
- size_t revIndex = d_proofSteps.size() - 1 - index;
-
- return &d_proofSteps[revIndex];
-}
-
-unsigned LemmaProofRecipe::getNumSteps() const {
- return d_proofSteps.size();
-}
-
-void LemmaProofRecipe::setOriginalLemma(Node lemma) {
- d_originalLemma = lemma;
-}
-
-Node LemmaProofRecipe::getOriginalLemma() const {
- return d_originalLemma;
-}
-
-std::ostream& operator<<(std::ostream& out,
- const LemmaProofRecipe::ProofStep& step)
-{
- out << "Proof Step(";
- out << " lit = " << step.getLiteral() << ",";
- out << " assertions = " << step.getAssertions() << ",";
- out << " theory = " << step.getTheory();
- out << " )";
- return out;
-}
-
-std::ostream& operator<<(std::ostream& out, const LemmaProofRecipe& recipe)
-{
- out << "LemmaProofRecipe(";
- out << "\n original lemma = " << recipe.getOriginalLemma();
- out << "\n actual clause = " << recipe.getBaseAssertions();
- out << "\n theory = " << recipe.getTheory();
- out << "\n steps = ";
- for (const auto& step : recipe)
- {
- out << "\n " << step;
- }
- out << "\n rewrites = ";
- for (LemmaProofRecipe::RewriteIterator i = recipe.rewriteBegin(),
- end = recipe.rewriteEnd();
- i != end;
- ++i)
- {
- out << "\n Rewrite(" << i->first << ", explanation = " << i->second
- << ")";
- }
- out << "\n)";
- return out;
-}
-
-} /* namespace CVC4 */
diff --git a/src/proof/lemma_proof.h b/src/proof/lemma_proof.h
deleted file mode 100644
index ffc6655a6..000000000
--- a/src/proof/lemma_proof.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/********************* */
-/*! \file lemma_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** A class for recoding the steps required in order to prove a theory lemma.
-
-**/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__LEMMA_PROOF_H
-#define CVC4__LEMMA_PROOF_H
-
-#include "expr/expr.h"
-#include "proof/clause_id.h"
-#include "prop/sat_solver_types.h"
-#include "util/proof.h"
-#include "expr/node.h"
-#include <iosfwd>
-
-namespace CVC4 {
-
-class LemmaProofRecipe {
-public:
- class ProofStep {
- public:
- ProofStep(theory::TheoryId theory, Node literalToProve);
- theory::TheoryId getTheory() const;
- Node getLiteral() const;
- void addAssertion(const Node& assertion);
- std::set<Node> getAssertions() const;
-
- private:
- theory::TheoryId d_theory;
- Node d_literalToProve;
- std::set<Node> d_assertions;
- };
-
- //* The lemma assertions and owner */
- void addBaseAssertion(Node baseAssertion);
- std::set<Node> getBaseAssertions() const;
- theory::TheoryId getTheory() const;
-
- //* Rewrite rules */
- using RewriteIterator = std::map<Node, Node>::const_iterator;
- RewriteIterator rewriteBegin() const;
- RewriteIterator rewriteEnd() const;
-
- // Steps iterator
- // The default iterator for a LemmaProofRecipe
- using iterator = std::vector<ProofStep>::reverse_iterator;
- std::vector<ProofStep>::reverse_iterator begin();
- std::vector<ProofStep>::reverse_iterator end();
-
- using const_iterator = std::vector<ProofStep>::const_reverse_iterator;
- std::vector<ProofStep>::const_reverse_iterator begin() const;
- std::vector<ProofStep>::const_reverse_iterator end() const;
-
- using difference_type = ptrdiff_t;
- using size_type = size_t;
- using value_type = ProofStep;
- using pointer = ProofStep *;
- using const_pointer = const ProofStep *;
- using reference = ProofStep &;
- using const_reference = const ProofStep &;
-
- void addRewriteRule(Node assertion, Node explanation);
- bool wasRewritten(Node assertion) const;
- Node getExplanation(Node assertion) const;
-
- //* Original lemma */
- void setOriginalLemma(Node lemma);
- Node getOriginalLemma() const;
-
- //* Proof Steps */
- void addStep(ProofStep& proofStep);
- const ProofStep* getStep(unsigned index) const;
- ProofStep* getStep(unsigned index);
- unsigned getNumSteps() const;
- std::set<Node> getMissingAssertionsForStep(unsigned index) const;
- bool simpleLemma() const;
- bool compositeLemma() const;
-
- void dump(const char *tag) const;
- bool operator<(const LemmaProofRecipe& other) const;
-
-private:
- //* The list of assertions for this lemma */
- std::set<Node> d_baseAssertions;
-
- //* The various steps needed to derive the empty clause */
- // The "first" step is actually at the back.
- std::vector<ProofStep> d_proofSteps;
-
- //* A map from assertions to their rewritten explanations (toAssert --> toExplain) */
- std::map<Node, Node> d_assertionToExplanation;
-
- //* The original lemma, as asserted by the owner theory solver */
- Node d_originalLemma;
-};
-
-std::ostream& operator<<(std::ostream & out, const LemmaProofRecipe::ProofStep & step);
-
-std::ostream& operator<<(std::ostream & out, const LemmaProofRecipe & recipe);
-
-} /* CVC4 namespace */
-
-#endif /* CVC4__LEMMA_PROOF_H */
diff --git a/src/proof/lfsc_proof_printer.cpp b/src/proof/lfsc_proof_printer.cpp
deleted file mode 100644
index 464083841..000000000
--- a/src/proof/lfsc_proof_printer.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/********************* */
-/*! \file lfsc_proof_printer.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Andres Noetzli, Alex Ozdemir, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Prints proofs in the LFSC format
- **
- ** Prints proofs in the LFSC format.
- **/
-
-#include "proof/lfsc_proof_printer.h"
-
-#include <algorithm>
-#include <iostream>
-#include <iterator>
-
-#include "prop/bvminisat/core/Solver.h"
-#include "prop/minisat/core/Solver.h"
-
-namespace CVC4 {
-namespace proof {
-
-template <class Solver>
-std::string LFSCProofPrinter::clauseName(TSatProof<Solver>* satProof,
- ClauseId id)
-{
- std::ostringstream os;
- if (satProof->isInputClause(id))
- {
- os << ProofManager::getInputClauseName(id, satProof->getName());
- }
- else if (satProof->isLemmaClause(id))
- {
- os << ProofManager::getLemmaClauseName(id, satProof->getName());
- }
- else
- {
- os << ProofManager::getLearntClauseName(id, satProof->getName());
- }
- return os.str();
-}
-
-template <class Solver>
-void LFSCProofPrinter::printResolution(TSatProof<Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren)
-{
- out << "(satlem_simplify _ _ _";
- paren << ")";
-
- const ResChain<Solver>& res = satProof->getResolutionChain(id);
- const typename ResChain<Solver>::ResSteps& steps = res.getSteps();
-
- for (int i = steps.size() - 1; i >= 0; i--)
- {
- out << " (";
- out << (steps[i].sign ? "R" : "Q") << " _ _";
- }
-
- ClauseId start_id = res.getStart();
- out << " " << clauseName(satProof, start_id);
-
- for (unsigned i = 0; i < steps.size(); i++)
- {
- prop::SatVariable v =
- prop::MinisatSatSolver::toSatVariable(var(steps[i].lit));
- out << " " << clauseName(satProof, steps[i].id) << " "
- << ProofManager::getVarName(v, satProof->getName()) << ")";
- }
-
- if (id == satProof->getEmptyClauseId())
- {
- out << " (\\ empty empty)";
- return;
- }
-
- out << " (\\ " << clauseName(satProof, id) << "\n"; // bind to lemma name
- paren << ")";
-}
-
-template <class Solver>
-void LFSCProofPrinter::printAssumptionsResolution(TSatProof<Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren)
-{
- Assert(satProof->isAssumptionConflict(id));
- // print the resolution proving the assumption conflict
- printResolution(satProof, id, out, paren);
- // resolve out assumptions to prove empty clause
- out << "(satlem_simplify _ _ _ ";
- const std::vector<typename Solver::TLit>& confl =
- *(satProof->getAssumptionConflicts().at(id));
-
- Assert(confl.size());
-
- for (unsigned i = 0; i < confl.size(); ++i)
- {
- prop::SatLiteral lit = toSatLiteral<Solver>(confl[i]);
- out << "(";
- out << (lit.isNegated() ? "Q" : "R") << " _ _ ";
- }
-
- out << clauseName(satProof, id) << " ";
- for (int i = confl.size() - 1; i >= 0; --i)
- {
- prop::SatLiteral lit = toSatLiteral<Solver>(confl[i]);
- prop::SatVariable v = lit.getSatVariable();
- out << "unit" << v << " ";
- out << ProofManager::getVarName(v, satProof->getName()) << ")";
- }
- out << "(\\ e e)\n";
- paren << ")";
-}
-
-template <class Solver>
-void LFSCProofPrinter::printResolutions(TSatProof<Solver>* satProof,
- std::ostream& out,
- std::ostream& paren)
-{
- Debug("bv-proof") << "; print resolutions" << std::endl;
- std::set<ClauseId>::iterator it = satProof->getSeenLearnt().begin();
- for (; it != satProof->getSeenLearnt().end(); ++it)
- {
- if (*it != satProof->getEmptyClauseId())
- {
- Debug("bv-proof") << "; print resolution for " << *it << std::endl;
- printResolution(satProof, *it, out, paren);
- }
- }
- Debug("bv-proof") << "; done print resolutions" << std::endl;
-}
-
-template <class Solver>
-void LFSCProofPrinter::printResolutionEmptyClause(TSatProof<Solver>* satProof,
- std::ostream& out,
- std::ostream& paren)
-{
- 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,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren);
-template void LFSCProofPrinter::printResolutions(
- TSatProof<CVC4::Minisat::Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-template void LFSCProofPrinter::printResolutionEmptyClause(
- TSatProof<CVC4::Minisat::Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-
-template void LFSCProofPrinter::printAssumptionsResolution(
- TSatProof<CVC4::BVMinisat::Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren);
-template void LFSCProofPrinter::printResolutions(
- TSatProof<CVC4::BVMinisat::Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-template void LFSCProofPrinter::printResolutionEmptyClause(
- TSatProof<CVC4::BVMinisat::Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-} // namespace proof
-} // namespace CVC4
diff --git a/src/proof/lfsc_proof_printer.h b/src/proof/lfsc_proof_printer.h
deleted file mode 100644
index 62547676f..000000000
--- a/src/proof/lfsc_proof_printer.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/********************* */
-/*! \file lfsc_proof_printer.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Andres Noetzli, Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Prints proofs in the LFSC format
- **
- ** Prints proofs in the LFSC format.
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__LFSC_PROOF_PRINTER_H
-#define CVC4__PROOF__LFSC_PROOF_PRINTER_H
-
-#include <iosfwd>
-#include <string>
-#include <vector>
-
-#include "proof/clause_id.h"
-#include "proof/proof_manager.h"
-#include "proof/sat_proof.h"
-#include "proof/sat_proof_implementation.h"
-#include "util/proof.h"
-
-namespace CVC4 {
-namespace proof {
-
-class LFSCProofPrinter
-{
- public:
- /**
- * Prints the resolution proof for an assumption conflict.
- *
- * @param satProof The record of the reasoning done by the SAT solver
- * @param id The clause to print a proof for
- * @param out The stream to print to
- * @param paren A stream for the closing parentheses
- */
- template <class Solver>
- static void printAssumptionsResolution(TSatProof<Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren);
-
- /**
- * Prints the resolution proofs for learned clauses that have been used to
- * deduce unsat.
- *
- * @param satProof The record of the reasoning done by the SAT solver
- * @param out The stream to print to
- * @param paren A stream for the closing parentheses
- */
- template <class Solver>
- static void printResolutions(TSatProof<Solver>* satProof,
- std::ostream& out,
- std::ostream& paren);
-
- /**
- * Prints the resolution proof for the empty clause.
- *
- * @param satProof The record of the reasoning done by the SAT solver
- * @param out The stream to print to
- * @param paren A stream for the closing parentheses
- */
- template <class Solver>
- static void printResolutionEmptyClause(TSatProof<Solver>* satProof,
- 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.
- *
- * @param satProof The record of the reasoning done by the SAT solver
- * @param id The clause to map to a string
- */
- template <class Solver>
- static std::string clauseName(TSatProof<Solver>* satProof, ClauseId id);
-
- /**
- * Prints the resolution proof for a given clause.
- *
- * @param satProof The record of the reasoning done by the SAT solver
- * @param id The clause to print a proof for
- * @param out The stream to print to
- * @param paren A stream for the closing parentheses
- */
- template <class Solver>
- static void printResolution(TSatProof<Solver>* satProof,
- ClauseId id,
- std::ostream& out,
- std::ostream& paren);
-};
-
-} // namespace proof
-} // namespace CVC4
-
-#endif /* CVC4__PROOF__LFSC_PROOF_PRINTER_H */
diff --git a/src/proof/lrat/lrat_proof.cpp b/src/proof/lrat/lrat_proof.cpp
deleted file mode 100644
index 69ffa623a..000000000
--- a/src/proof/lrat/lrat_proof.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-/********************* */
-/*! \file lrat_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Andres Noetzli, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief 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/check.h"
-#include "base/output.h"
-#include "proof/dimacs.h"
-#include "proof/lfsc_proof_printer.h"
-#include "util/utility.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 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)
-{
- Assert(indices.size() > 0);
- // 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, prop::SatClause>& clauses,
- const std::vector<ClauseId> usedIds,
- const std::string& dratBinary,
- TimerStat& toolTimer)
-{
- std::ostringstream cmd;
- std::string formulaFilename("cvc4-dimacs-XXXXXX");
- std::string dratFilename("cvc4-drat-XXXXXX");
- std::string lratFilename("cvc4-lrat-XXXXXX");
-
- std::unique_ptr<std::fstream> formStream = openTmpFile(&formulaFilename);
- printDimacs(*formStream, clauses, usedIds);
- formStream->close();
-
- std::unique_ptr<std::fstream> dratStream = openTmpFile(&dratFilename);
- (*dratStream) << dratBinary;
- dratStream->close();
-
- std::unique_ptr<std::fstream> lratStream = openTmpFile(&lratFilename);
-
- {
- CodeTimer blockTimer{toolTimer};
-#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
- }
-
- LratProof lrat(*lratStream);
- remove(formulaFilename.c_str());
- remove(dratFilename.c_str());
- remove(lratFilename.c_str());
- 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);
- }
- if (clauses.size() > 0)
- {
- 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
deleted file mode 100644
index 1c065a08e..000000000
--- a/src/proof/lrat/lrat_proof.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/********************* */
-/*! \file lrat_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief 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 <utility>
-#include <vector>
-
-#include "proof/clause_id.h"
-// Included because we need operator<< for the SAT types
-#include "prop/sat_solver.h"
-#include "util/statistics_registry.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 clauses A store of clauses that might be in our formula
- * @param usedIds the ids of clauses that are actually in our formula
- * @param dratBinary The DRAT proof from the SAT solver, as a binary stream.
- *
- * @return an LRAT proof an a timer for how long it took to run drat-trim
- */
- static LratProof fromDratProof(
- const std::unordered_map<ClauseId, prop::SatClause>& clauses,
- const std::vector<ClauseId> usedIds,
- const std::string& dratBinary,
- TimerStat& toolTimer);
- /**
- * @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/proof.h b/src/proof/proof.h
deleted file mode 100644
index be5af32db..000000000
--- a/src/proof/proof.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/********************* */
-/*! \file proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Tim King, Liana Hadarean, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Proof macros
- **
- ** Proof macros
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__PROOF_H
-#define CVC4__PROOF__PROOF_H
-
-#include "options/smt_options.h"
-
-
-/* Do NOT use #ifdef CVC4_PROOF to check if proofs are enabled.
- * We cannot assume users will use -DCVC4_PROOFS if they have a proofs build.
- * The preferred way of checking that proofs are enabled is to use:
- * #if IS_PROOFS_BUILD
- * ...
- * #endif
- *
- * The macro IS_PROOFS_BUILD is defined in base/configuration_private.h
- *
- * This has the effect of forcing that location to have included this header
- * *before* performing this test. This includes C preprocessing expansion.
- * This forces the inclusion of "cvc4_private.h". This is intentional!
- *
- * See bug 688 for more details:
- * https://github.com/CVC4/CVC4/issues/907
- *
- * If you want to check CVC4_PROOF, you should have a very good reason
- * and should list the exceptions here:
- * - Makefile.am
- * - proof/proofs.h
- * - base/configuration_private.h
- */
-
-#ifdef CVC4_PROOF
-# define PROOF(x) if(CVC4::options::proof() || CVC4::options::unsatCores()) { x; }
-# define NULLPROOF(x) (CVC4::options::proof() || CVC4::options::unsatCores()) ? x : NULL
-# define PROOF_ON() (CVC4::options::proof() || CVC4::options::unsatCores())
-# define THEORY_PROOF(x) if(CVC4::options::proof()) { x; }
-# define THEORY_NULLPROOF(x) CVC4::options::proof() ? x : NULL
-# define THEORY_PROOF_ON() CVC4::options::proof()
-#else /* CVC4_PROOF */
-# define PROOF(x)
-# define NULLPROOF(x) NULL
-# define PROOF_ON() false
-# define THEORY_PROOF(x)
-# define THEORY_NULLPROOF(x) NULL
-# define THEORY_PROOF_ON() false
-#endif /* CVC4_PROOF */
-
-#ifdef CVC4_PROOF_STATS /* CVC4_PROOF_STATS */
-# define PSTATS(x) { x; }
-#else
-# define PSTATS(x)
-#endif /* CVC4_PROOF_STATS */
-
-#endif /* CVC4__PROOF__PROOF_H */
diff --git a/src/proof/proof_manager.cpp b/src/proof/proof_manager.cpp
index 99e3010b4..3e6cc9c69 100644
--- a/src/proof/proof_manager.cpp
+++ b/src/proof/proof_manager.cpp
@@ -21,14 +21,10 @@
#include "context/context.h"
#include "expr/node_visitor.h"
#include "options/bv_options.h"
-#include "options/proof_options.h"
+#include "options/smt_options.h"
#include "proof/clause_id.h"
#include "proof/cnf_proof.h"
-#include "proof/lfsc_proof_printer.h"
-#include "proof/proof_utils.h"
-#include "proof/resolution_bitvector_proof.h"
#include "proof/sat_proof_implementation.h"
-#include "proof/theory_proof.h"
#include "smt/smt_engine.h"
#include "smt/smt_engine_scope.h"
#include "smt/smt_statistics_registry.h"
@@ -39,36 +35,16 @@
#include "theory/uf/theory_uf.h"
#include "theory/valuation.h"
#include "util/hash.h"
-#include "util/proof.h"
namespace CVC4 {
-std::string nodeSetToString(const std::set<Node>& nodes) {
- std::ostringstream os;
- std::set<Node>::const_iterator it;
- for (it = nodes.begin(); it != nodes.end(); ++it) {
- os << *it << " ";
- }
- return os.str();
-}
-
-std::string append(const std::string& str, uint64_t num) {
- std::ostringstream os;
- os << str << num;
- return os.str();
-}
-
-ProofManager::ProofManager(context::Context* context, ProofFormat format)
+ProofManager::ProofManager(context::Context* context)
: d_context(context),
d_satProof(nullptr),
d_cnfProof(nullptr),
- d_theoryProof(nullptr),
- d_inputFormulas(),
d_inputCoreFormulas(context),
d_outputCoreFormulas(context),
d_nextId(0),
- d_fullProof(),
- d_format(format),
d_deps(context)
{
}
@@ -78,19 +54,6 @@ ProofManager::~ProofManager() {}
ProofManager* ProofManager::currentPM() {
return smt::currentProofManager();
}
-const Proof& ProofManager::getProof(SmtEngine* smt)
-{
- if (!currentPM()->d_fullProof)
- {
- Assert(currentPM()->d_format == LFSC);
- currentPM()->d_fullProof.reset(new LFSCProof(
- smt,
- getSatProof(),
- static_cast<LFSCCnfProof*>(getCnfProof()),
- static_cast<LFSCTheoryProofEngine*>(getTheoryProofEngine())));
- }
- return *(currentPM()->d_fullProof);
-}
CoreSatProof* ProofManager::getSatProof()
{
@@ -104,45 +67,8 @@ CnfProof* ProofManager::getCnfProof()
return currentPM()->d_cnfProof.get();
}
-TheoryProofEngine* ProofManager::getTheoryProofEngine()
-{
- Assert(currentPM()->d_theoryProof != NULL);
- return currentPM()->d_theoryProof.get();
-}
-
-UFProof* ProofManager::getUfProof() {
- Assert(options::proof());
- TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_UF);
- return (UFProof*)pf;
-}
-
-proof::ResolutionBitVectorProof* ProofManager::getBitVectorProof()
-{
- Assert(options::proof());
- TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_BV);
- return static_cast<proof::ResolutionBitVectorProof*>(pf);
-}
-
-ArrayProof* ProofManager::getArrayProof() {
- Assert(options::proof());
- TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_ARRAYS);
- return (ArrayProof*)pf;
-}
-
-ArithProof* ProofManager::getArithProof() {
- Assert(options::proof());
- TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_ARITH);
- return (ArithProof*)pf;
-}
-
-SkolemizationManager* ProofManager::getSkolemizationManager() {
- Assert(options::proof() || options::unsatCores());
- return &(currentPM()->d_skolemizationManager);
-}
-
void ProofManager::initSatProof(Minisat::Solver* solver)
{
- Assert(d_format == LFSC);
// Destroy old instance before initializing new one to avoid issues with
// registering stats
d_satProof.reset();
@@ -153,150 +79,22 @@ void ProofManager::initCnfProof(prop::CnfStream* cnfStream,
context::Context* ctx)
{
Assert(d_satProof != nullptr);
- Assert(d_format == LFSC);
- d_cnfProof.reset(new LFSCCnfProof(cnfStream, ctx, ""));
+ d_cnfProof.reset(new CnfProof(cnfStream, ctx, ""));
// 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_satProof->getTrueUnit());
d_cnfProof->popCurrentAssertion();
- d_cnfProof->popCurrentDefinition();
d_cnfProof->pushCurrentAssertion(false_node);
- d_cnfProof->pushCurrentDefinition(false_node);
d_cnfProof->registerConvertedClause(d_satProof->getFalseUnit());
d_cnfProof->popCurrentAssertion();
- d_cnfProof->popCurrentDefinition();
-}
-
-void ProofManager::initTheoryProofEngine()
-{
- Assert(d_theoryProof == NULL);
- Assert(d_format == LFSC);
- d_theoryProof.reset(new LFSCTheoryProofEngine());
-}
-
-std::string ProofManager::getInputClauseName(ClauseId id,
- const std::string& prefix) {
- return append(prefix+".pb", id);
-}
-
-std::string ProofManager::getLemmaClauseName(ClauseId id,
- const std::string& prefix) {
- return append(prefix+".lemc", id);
}
-std::string ProofManager::getLemmaName(ClauseId id, const std::string& prefix) {
- return append(prefix+"lem", id);
-}
-
-std::string ProofManager::getLearntClauseName(ClauseId id,
- const std::string& prefix) {
- return append(prefix+".cl", id);
-}
-std::string ProofManager::getVarName(prop::SatVariable var,
- const std::string& prefix) {
- return append(prefix+".v", var);
-}
-std::string ProofManager::getAtomName(prop::SatVariable var,
- const std::string& prefix) {
- return append(prefix+".a", var);
-}
-std::string ProofManager::getLitName(prop::SatLiteral lit,
- const std::string& prefix) {
- return append(prefix+".l", lit.toInt());
-}
-
-std::string ProofManager::getPreprocessedAssertionName(Node node,
- const std::string& prefix) {
- if (currentPM()->d_assertionFilters.find(node) != currentPM()->d_assertionFilters.end()) {
- return currentPM()->d_assertionFilters[node];
- }
-
- node = node.getKind() == kind::BITVECTOR_EAGER_ATOM ? node[0] : node;
- return append(prefix+".PA", node.getId());
-}
-std::string ProofManager::getAssertionName(Node node,
- const std::string& prefix) {
- return append(prefix+".A", node.getId());
-}
-std::string ProofManager::getInputFormulaName(const Expr& expr) {
- return currentPM()->d_inputFormulaToName[expr];
-}
-
-std::string ProofManager::getAtomName(TNode atom,
- const std::string& prefix) {
- prop::SatLiteral lit = currentPM()->d_cnfProof->getLiteral(atom);
- Assert(!lit.isNegated());
- return getAtomName(lit.getSatVariable(), prefix);
-}
-
-std::string ProofManager::getLitName(TNode lit,
- const std::string& prefix) {
- std::string litName = getLitName(currentPM()->d_cnfProof->getLiteral(lit), prefix);
- if (currentPM()->d_rewriteFilters.find(litName) != currentPM()->d_rewriteFilters.end()) {
- return currentPM()->d_rewriteFilters[litName];
- }
-
- return litName;
-}
-
-bool ProofManager::hasLitName(TNode lit) {
- return currentPM()->d_cnfProof->hasLiteral(lit);
-}
-
-std::string ProofManager::sanitize(TNode node) {
- Assert(node.isVar() || node.isConst());
-
- std::string name = node.toString();
- if (node.isVar()) {
- std::replace(name.begin(), name.end(), ' ', '_');
- } else if (node.isConst()) {
- name.erase(std::remove(name.begin(), name.end(), '('), name.end());
- name.erase(std::remove(name.begin(), name.end(), ')'), name.end());
- name.erase(std::remove(name.begin(), name.end(), ' '), name.end());
- name = "const" + name;
- }
-
- return name;
-}
-
-void ProofManager::traceDeps(TNode n, ExprSet* coreAssertions) {
- Debug("cores") << "trace deps " << n << std::endl;
- if ((n.isConst() && n == NodeManager::currentNM()->mkConst<bool>(true)) ||
- (n.getKind() == kind::NOT && n[0] == NodeManager::currentNM()->mkConst<bool>(false))) {
- return;
- }
- if(d_inputCoreFormulas.find(n.toExpr()) != d_inputCoreFormulas.end()) {
- // originating formula was in core set
- Debug("cores") << " -- IN INPUT CORE LIST!" << std::endl;
- coreAssertions->insert(n.toExpr());
- } else {
- Debug("cores") << " -- NOT IN INPUT CORE LIST!" << std::endl;
- if(d_deps.find(n) == d_deps.end()) {
- if (options::allowEmptyDependencies()) {
- Debug("cores") << " -- Could not track cause assertion. Failing silently." << std::endl;
- return;
- }
- InternalError()
- << "Cannot trace dependence information back to input assertion:\n`"
- << n << "'";
- }
- Assert(d_deps.find(n) != d_deps.end());
- std::vector<Node> deps = (*d_deps.find(n)).second;
- for(std::vector<Node>::const_iterator i = deps.begin(); i != deps.end(); ++i) {
- Debug("cores") << " + tracing deps: " << n << " -deps-on- " << *i << std::endl;
- if( !(*i).isNull() ){
- traceDeps(*i, coreAssertions);
- }
- }
- }
-}
void ProofManager::traceDeps(TNode n, CDExprSet* coreAssertions) {
Debug("cores") << "trace deps " << n << std::endl;
@@ -311,10 +109,6 @@ void ProofManager::traceDeps(TNode n, CDExprSet* coreAssertions) {
} else {
Debug("cores") << " -- NOT IN INPUT CORE LIST!" << std::endl;
if(d_deps.find(n) == d_deps.end()) {
- if (options::allowEmptyDependencies()) {
- Debug("cores") << " -- Could not track cause assertion. Failing silently." << std::endl;
- return;
- }
InternalError()
<< "Cannot trace dependence information back to input assertion:\n`"
<< n << "'";
@@ -345,16 +139,11 @@ void ProofManager::traceUnsatCore() {
IdToSatClause::const_iterator it = used_inputs.begin();
for(; it != used_inputs.end(); ++it) {
Node node = d_cnfProof->getAssertionForClause(it->first);
- ProofRule rule = d_cnfProof->getProofRule(node);
- Debug("cores") << "core input assertion " << node << std::endl;
- Debug("cores") << "with proof rule " << rule << std::endl;
- if (rule == RULE_TSEITIN ||
- rule == RULE_GIVEN) {
- // trace dependences back to actual assertions
- // (this adds them to the unsat core)
- traceDeps(node, &d_outputCoreFormulas);
- }
+ Debug("cores") << "core input assertion " << node << "\n";
+ // trace dependences back to actual assertions
+ // (this adds them to the unsat core)
+ traceDeps(node, &d_outputCoreFormulas);
}
}
@@ -373,150 +162,32 @@ std::vector<Expr> ProofManager::extractUnsatCore() {
return result;
}
-void ProofManager::constructSatProof() {
- if (!d_satProof->proofConstructed()) {
+void ProofManager::constructSatProof()
+{
+ if (!d_satProof->proofConstructed())
+ {
d_satProof->constructProof();
}
}
-void ProofManager::getLemmasInUnsatCore(theory::TheoryId theory, std::vector<Node> &lemmas) {
- Assert(PROOF_ON()) << "Cannot compute unsat core when proofs are off";
- Assert(unsatCoreAvailable())
- << "Cannot get unsat core at this time. Mabye the input is SAT?";
-
- constructSatProof();
-
- IdToSatClause used_lemmas;
- IdToSatClause used_inputs;
- d_satProof->collectClausesUsed(used_inputs, used_lemmas);
-
- IdToSatClause::const_iterator it;
- std::set<Node> seen;
-
- Debug("pf::lemmasUnsatCore") << "Dumping all lemmas in unsat core" << std::endl;
- for (it = used_lemmas.begin(); it != used_lemmas.end(); ++it) {
- std::set<Node> lemma = satClauseToNodeSet(it->second);
- Debug("pf::lemmasUnsatCore") << nodeSetToString(lemma);
-
- // TODO: we should be able to drop the "haveProofRecipe" check.
- // however, there are some rewrite issues with the arith solver, resulting
- // in non-registered recipes. For now we assume no one is requesting arith lemmas.
- LemmaProofRecipe recipe;
- if (!getCnfProof()->haveProofRecipe(lemma)) {
- Debug("pf::lemmasUnsatCore") << "\t[no recipe]" << std::endl;
- continue;
- }
-
- recipe = getCnfProof()->getProofRecipe(lemma);
- Debug("pf::lemmasUnsatCore") << "\t[owner = " << recipe.getTheory()
- << ", original = " << recipe.getOriginalLemma() << "]" << std::endl;
- if (recipe.simpleLemma() && recipe.getTheory() == theory && seen.find(recipe.getOriginalLemma()) == seen.end()) {
- lemmas.push_back(recipe.getOriginalLemma());
- seen.insert(recipe.getOriginalLemma());
- }
- }
-}
-
-std::set<Node> ProofManager::satClauseToNodeSet(prop::SatClause* clause) {
- std::set<Node> result;
- for (unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = getCnfProof()->getAtom(lit.getSatVariable());
- Expr atom = node.toExpr();
- if (atom != utils::mkTrue())
- result.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- return result;
-}
-
-Node ProofManager::getWeakestImplicantInUnsatCore(Node lemma) {
- Assert(PROOF_ON()) << "Cannot compute unsat core when proofs are off";
+void ProofManager::getLemmasInUnsatCore(std::vector<Node>& lemmas)
+{
+ Assert(options::unsatCores())
+ << "Cannot compute unsat core when proofs are off";
Assert(unsatCoreAvailable())
<< "Cannot get unsat core at this time. Mabye the input is SAT?";
-
- // If we're doing aggressive minimization, work on all lemmas, not just conjunctions.
- if (!options::aggressiveCoreMin() && (lemma.getKind() != kind::AND))
- return lemma;
-
constructSatProof();
-
- NodeBuilder<> builder(kind::AND);
-
IdToSatClause used_lemmas;
IdToSatClause used_inputs;
d_satProof->collectClausesUsed(used_inputs, used_lemmas);
-
+ Debug("pf::lemmasUnsatCore") << "Retrieving all lemmas in unsat core\n";
IdToSatClause::const_iterator it;
- std::set<Node>::iterator lemmaIt;
-
- if (!options::aggressiveCoreMin()) {
- for (it = used_lemmas.begin(); it != used_lemmas.end(); ++it) {
- std::set<Node> currentLemma = satClauseToNodeSet(it->second);
-
- // TODO: we should be able to drop the "haveProofRecipe" check.
- // however, there are some rewrite issues with the arith solver, resulting
- // in non-registered recipes. For now we assume no one is requesting arith lemmas.
- LemmaProofRecipe recipe;
- if (!getCnfProof()->haveProofRecipe(currentLemma))
- continue;
-
- recipe = getCnfProof()->getProofRecipe(currentLemma);
- if (recipe.getOriginalLemma() == lemma) {
- for (lemmaIt = currentLemma.begin(); lemmaIt != currentLemma.end(); ++lemmaIt) {
- builder << *lemmaIt;
-
- // Check that each conjunct appears in the original lemma.
- bool found = false;
- for (unsigned i = 0; i < lemma.getNumChildren(); ++i) {
- if (lemma[i] == *lemmaIt)
- found = true;
- }
-
- if (!found)
- return lemma;
- }
- }
- }
- } else {
- // Aggressive mode
- for (it = used_lemmas.begin(); it != used_lemmas.end(); ++it) {
- std::set<Node> currentLemma = satClauseToNodeSet(it->second);
-
- // TODO: we should be able to drop the "haveProofRecipe" check.
- // however, there are some rewrite issues with the arith solver, resulting
- // in non-registered recipes. For now we assume no one is requesting arith lemmas.
- LemmaProofRecipe recipe;
- if (!getCnfProof()->haveProofRecipe(currentLemma))
- continue;
-
- recipe = getCnfProof()->getProofRecipe(currentLemma);
- if (recipe.getOriginalLemma() == lemma) {
- NodeBuilder<> disjunction(kind::OR);
- for (lemmaIt = currentLemma.begin(); lemmaIt != currentLemma.end(); ++lemmaIt) {
- disjunction << *lemmaIt;
- }
-
- Node conjunct = (disjunction.getNumChildren() == 1) ? disjunction[0] : disjunction;
- builder << conjunct;
- }
- }
+ for (it = used_lemmas.begin(); it != used_lemmas.end(); ++it)
+ {
+ Node lemma = d_cnfProof->getAssertionForClause(it->first);
+ Debug("pf::lemmasUnsatCore") << "Retrieved lemma " << lemma << "\n";
+ lemmas.push_back(lemma);
}
-
- AlwaysAssert(builder.getNumChildren() != 0);
-
- if (builder.getNumChildren() == 1)
- return builder[0];
-
- return builder;
-}
-
-void ProofManager::addAssertion(Expr formula) {
- Debug("proof:pm") << "assert: " << formula << std::endl;
- d_inputFormulas.insert(formula);
- std::ostringstream name;
- name << "A" << d_inputFormulaToName.size();
- d_inputFormulaToName[formula] = name.str();
}
void ProofManager::addCoreAssertion(Expr formula) {
@@ -542,665 +213,4 @@ void ProofManager::addUnsatCore(Expr formula) {
d_outputCoreFormulas.insert(formula);
}
-void ProofManager::addAssertionFilter(const Node& node, const std::string& rewritten) {
- d_assertionFilters[node] = rewritten;
-}
-
-void ProofManager::setLogic(const LogicInfo& logic) {
- d_logic = logic;
-}
-
-LFSCProof::LFSCProof(SmtEngine* smtEngine,
- CoreSatProof* sat,
- LFSCCnfProof* cnf,
- LFSCTheoryProofEngine* theory)
- : d_satProof(sat),
- d_cnfProof(cnf),
- d_theoryProof(theory),
- d_smtEngine(smtEngine)
-{}
-
-void LFSCProof::toStream(std::ostream& out, const ProofLetMap& map) const
-{
- Unreachable();
-}
-
-void collectAtoms(TNode node, std::set<Node>& seen, CnfProof* cnfProof)
-{
- Debug("pf::pm::atoms") << "collectAtoms: Colleting atoms from " << node
- << "\n";
- if (seen.find(node) != seen.end())
- {
- Debug("pf::pm::atoms") << "collectAtoms:\t already seen\n";
- return;
- }
- // if I have a SAT literal for a node, save it, unless this node is a
- // negation, in which case its underlying will be collected downstream
- if (cnfProof->hasLiteral(node) && node.getKind() != kind::NOT)
- {
- Debug("pf::pm::atoms") << "collectAtoms: has SAT literal, save\n";
- seen.insert(node);
- }
- for (unsigned i = 0; i < node.getNumChildren(); ++i)
- {
- Debug("pf::pm::atoms") << push;
- collectAtoms(node[i], seen, cnfProof);
- Debug("pf::pm::atoms") << pop;
- }
-}
-
-void LFSCProof::toStream(std::ostream& out) const
-{
- TimerStat::CodeTimer proofProductionTimer(
- ProofManager::currentPM()->getStats().d_proofProductionTime);
-
- IdToSatClause used_lemmas;
- IdToSatClause used_inputs;
- std::set<Node> atoms;
- NodePairSet rewrites;
- NodeSet used_assertions;
-
- {
- CodeTimer skeletonProofTimer{
- ProofManager::currentPM()->getStats().d_skeletonProofTraceTime};
- Assert(!d_satProof->proofConstructed());
-
- // Here we give our SAT solver a chance to flesh out the resolution proof.
- // It proves bottom from a set of clauses.
- d_satProof->constructProof();
-
- // We ask the SAT solver which clauses are used in that proof.
- // For a resolution proof, these are the leaves of the tree.
- d_satProof->collectClausesUsed(used_inputs, used_lemmas);
-
- IdToSatClause::iterator it2;
- Debug("pf::pm") << std::endl << "Used inputs: " << std::endl;
- for (it2 = used_inputs.begin(); it2 != used_inputs.end(); ++it2)
- {
- Debug("pf::pm") << "\t input = " << *(it2->second) << std::endl;
- }
- Debug("pf::pm") << std::endl;
-
- Debug("pf::pm") << std::endl << "Used lemmas: " << std::endl;
- for (it2 = used_lemmas.begin(); it2 != used_lemmas.end(); ++it2)
- {
- std::vector<Expr> clause_expr;
- for (unsigned i = 0; i < it2->second->size(); ++i)
- {
- prop::SatLiteral lit = (*(it2->second))[i];
- Expr atom = d_cnfProof->getAtom(lit.getSatVariable()).toExpr();
- if (atom.isConst())
- {
- Assert(atom == utils::mkTrue());
- continue;
- }
- Expr expr_lit = lit.isNegated() ? atom.notExpr() : atom;
- clause_expr.push_back(expr_lit);
- }
-
- Debug("pf::pm") << "\t lemma " << it2->first << " = " << *(it2->second)
- << std::endl;
- Debug("pf::pm") << "\t";
- for (unsigned i = 0; i < clause_expr.size(); ++i)
- {
- Debug("pf::pm") << clause_expr[i] << " ";
- }
- Debug("pf::pm") << std::endl;
- }
- Debug("pf::pm") << std::endl;
-
- // collecting assertions that lead to the clauses being asserted
- d_cnfProof->collectAssertionsForClauses(used_inputs, used_assertions);
-
- NodeSet::iterator it3;
- Debug("pf::pm") << std::endl << "Used assertions: " << std::endl;
- for (it3 = used_assertions.begin(); it3 != used_assertions.end(); ++it3)
- Debug("pf::pm") << "\t assertion = " << *it3 << std::endl;
-
- // collects the atoms in the clauses
- d_cnfProof->collectAtomsAndRewritesForLemmas(used_lemmas, atoms, rewrites);
-
- if (!rewrites.empty())
- {
- Debug("pf::pm") << std::endl << "Rewrites used in lemmas: " << std::endl;
- NodePairSet::const_iterator rewriteIt;
- for (rewriteIt = rewrites.begin(); rewriteIt != rewrites.end();
- ++rewriteIt)
- {
- Debug("pf::pm") << "\t" << rewriteIt->first << " --> "
- << rewriteIt->second << std::endl;
- }
- Debug("pf::pm") << std::endl << "Rewrite printing done" << std::endl;
- }
- else
- {
- Debug("pf::pm") << "No rewrites in lemmas found" << std::endl;
- }
-
- // The derived/unrewritten atoms may not have CNF literals required later
- // on. If they don't, add them.
- std::set<Node>::const_iterator it;
- for (it = atoms.begin(); it != atoms.end(); ++it)
- {
- Debug("pf::pm") << "Ensure literal for atom: " << *it << std::endl;
- if (!d_cnfProof->hasLiteral(*it))
- {
- // For arithmetic: these literals are not normalized, causing an error
- // in Arith.
- if (theory::Theory::theoryOf(*it) == theory::THEORY_ARITH)
- {
- d_cnfProof->ensureLiteral(
- *it,
- true); // This disables preregistration with the theory solver.
- }
- else
- {
- d_cnfProof->ensureLiteral(
- *it); // Normal method, with theory solver preregisteration.
- }
- }
- }
-
- // From the clauses, compute the atoms (atomic theory predicates in
- // assertions and lemmas).
- d_cnfProof->collectAtomsForClauses(used_inputs, atoms);
- d_cnfProof->collectAtomsForClauses(used_lemmas, atoms);
-
- // collects the atoms in the assertions
- Debug("pf::pm") << std::endl
- << "LFSCProof::toStream: Colleting atoms from assertions "
- << used_assertions << "\n"
- << push;
- for (TNode used_assertion : used_assertions)
- {
- collectAtoms(used_assertion, atoms, d_cnfProof);
- }
- Debug("pf::pm") << pop;
-
- std::set<Node>::iterator atomIt;
- Debug("pf::pm") << std::endl
- << "Dumping atoms from lemmas, inputs and assertions: "
- << std::endl
- << std::endl;
- for (atomIt = atoms.begin(); atomIt != atoms.end(); ++atomIt)
- {
- Debug("pf::pm") << "\tAtom: " << *atomIt << std::endl;
- }
- }
-
- smt::SmtScope scope(d_smtEngine);
- ProofLetMap globalLetMap;
- std::ostringstream paren;
- {
- CodeTimer declTimer{
- ProofManager::currentPM()->getStats().d_proofDeclarationsTime};
- out << "(check\n";
- paren << ")";
- out << " ;; Declarations\n";
-
- // declare the theory atoms
- Debug("pf::pm") << "LFSCProof::toStream: registering terms:" << std::endl;
- for (std::set<Node>::const_iterator it = atoms.begin(); it != atoms.end(); ++it)
- {
- Debug("pf::pm") << "\tTerm: " << (*it).toExpr() << std::endl;
- d_theoryProof->registerTerm((*it).toExpr());
- }
-
- Debug("pf::pm") << std::endl
- << "Term registration done!" << std::endl
- << std::endl;
-
- Debug("pf::pm") << std::endl
- << "LFSCProof::toStream: starting to print assertions"
- << std::endl;
-
- // print out all the original assertions
- d_theoryProof->registerTermsFromAssertions();
- d_theoryProof->printSortDeclarations(out, paren);
- d_theoryProof->printTermDeclarations(out, paren);
- d_theoryProof->printAssertions(out, paren);
-
- Debug("pf::pm") << std::endl
- << "LFSCProof::toStream: print assertions DONE"
- << std::endl;
-
- out << "(: (holds cln)\n\n";
- paren << ")";
-
- // Have the theory proofs print deferred declarations, e.g. for skolem
- // variables.
- out << " ;; Printing deferred declarations \n\n";
- d_theoryProof->printDeferredDeclarations(out, paren);
-
- out << "\n ;; Printing the global let map";
- d_theoryProof->finalizeBvConflicts(used_lemmas, out);
- ProofManager::getBitVectorProof()->calculateAtomsInBitblastingProof();
- if (options::lfscLetification())
- {
- ProofManager::currentPM()->printGlobalLetMap(
- atoms, globalLetMap, out, paren);
- }
-
- out << " ;; Printing aliasing declarations \n\n";
- d_theoryProof->printAliasingDeclarations(out, paren, globalLetMap);
-
- out << " ;; Rewrites for Lemmas \n";
- d_theoryProof->printLemmaRewrites(rewrites, out, paren);
-
- // print trust that input assertions are their preprocessed form
- printPreprocessedAssertions(used_assertions, out, paren, globalLetMap);
- }
-
- {
- CodeTimer cnfProofTimer{
- ProofManager::currentPM()->getStats().d_cnfProofTime};
- // print mapping between theory atoms and internal SAT variables
- out << ";; Printing mapping from preprocessed assertions into atoms \n";
- d_cnfProof->printAtomMapping(atoms, out, paren, globalLetMap);
-
- Debug("pf::pm") << std::endl
- << "Printing cnf proof for clauses" << std::endl;
-
- IdToSatClause::const_iterator cl_it = used_inputs.begin();
- // print CNF conversion proof for each clause
- for (; cl_it != used_inputs.end(); ++cl_it)
- {
- d_cnfProof->printCnfProofForClause(
- cl_it->first, cl_it->second, out, paren);
- }
- }
-
- {
- CodeTimer theoryLemmaTimer{
- ProofManager::currentPM()->getStats().d_theoryLemmaTime};
- Debug("pf::pm") << std::endl
- << "Printing cnf proof for clauses DONE" << std::endl;
-
- Debug("pf::pm") << "Proof manager: printing theory lemmas" << std::endl;
- d_theoryProof->printTheoryLemmas(used_lemmas, out, paren, globalLetMap);
- Debug("pf::pm") << "Proof manager: printing theory lemmas DONE!"
- << std::endl;
- }
-
- {
- CodeTimer finalProofTimer{
- ProofManager::currentPM()->getStats().d_finalProofTime};
- out << ";; Printing final unsat proof \n";
- if (options::bitblastMode() == options::BitblastMode::EAGER
- && ProofManager::getBitVectorProof())
- {
- ProofManager::getBitVectorProof()->printEmptyClauseProof(out, paren);
- }
- else
- {
- // print actual resolution proof
- proof::LFSCProofPrinter::printResolutions(d_satProof, out, paren);
- proof::LFSCProofPrinter::printResolutionEmptyClause(
- d_satProof, out, paren);
- }
- }
-
- out << paren.str();
- out << "\n;;\n";
-}
-
-void LFSCProof::printPreprocessedAssertions(const NodeSet& assertions,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap& globalLetMap) const
-{
- os << "\n ;; In the preprocessor we trust \n";
- NodeSet::const_iterator it = assertions.begin();
- NodeSet::const_iterator end = assertions.end();
-
- Debug("pf::pm") << "LFSCProof::printPreprocessedAssertions starting" << std::endl;
-
- if (options::fewerPreprocessingHoles()) {
- // Check for assertions that did not get rewritten, and update the printing filter.
- checkUnrewrittenAssertion(assertions);
-
- // For the remaining assertions, bind them to input assertions.
- for (; it != end; ++it) {
- // Rewrite preprocessing step if it cannot be eliminated
- if (!ProofManager::currentPM()->have_input_assertion((*it).toExpr())) {
- os << "(th_let_pf _ (trust_f (iff ";
-
- Expr inputAssertion;
-
- if (((*it).isConst() && *it == NodeManager::currentNM()->mkConst<bool>(true)) ||
- ((*it).getKind() == kind::NOT && (*it)[0] == NodeManager::currentNM()->mkConst<bool>(false))) {
- inputAssertion = NodeManager::currentNM()->mkConst<bool>(true).toExpr();
- } else {
- // Figure out which input assertion led to this assertion
- ExprSet inputAssertions;
- ProofManager::currentPM()->traceDeps(*it, &inputAssertions);
-
- Debug("pf::pm") << "Original assertions for " << *it << " are: " << std::endl;
-
- ProofManager::assertions_iterator assertionIt;
- for (assertionIt = inputAssertions.begin(); assertionIt != inputAssertions.end(); ++assertionIt) {
- Debug("pf::pm") << "\t" << *assertionIt << std::endl;
- }
-
- if (inputAssertions.size() == 0) {
- Debug("pf::pm") << "LFSCProof::printPreprocessedAssertions: Count NOT find the assertion that caused this PA. Picking an arbitrary one..." << std::endl;
- // For now just use the first assertion...
- inputAssertion = *(ProofManager::currentPM()->begin_assertions());
- } else {
- if (inputAssertions.size() != 1) {
- Debug("pf::pm") << "LFSCProof::printPreprocessedAssertions: Attention: more than one original assertion was found. Picking just one." << std::endl;
- }
- inputAssertion = *inputAssertions.begin();
- }
- }
-
- if (!ProofManager::currentPM()->have_input_assertion(inputAssertion)) {
- // The thing returned by traceDeps does not appear in the input assertions...
- Debug("pf::pm") << "LFSCProof::printPreprocessedAssertions: Count NOT find the assertion that caused this PA. Picking an arbitrary one..." << std::endl;
- // For now just use the first assertion...
- inputAssertion = *(ProofManager::currentPM()->begin_assertions());
- }
-
- Debug("pf::pm") << "Original assertion for " << *it
- << " is: "
- << inputAssertion
- << ", AKA "
- << ProofManager::currentPM()->getInputFormulaName(inputAssertion)
- << std::endl;
-
- ProofManager::currentPM()->getTheoryProofEngine()->printTheoryTerm(inputAssertion, os, globalLetMap);
- os << " ";
- ProofManager::currentPM()->printTrustedTerm(*it, os, globalLetMap);
- os << "))";
- os << "(\\ "<< ProofManager::getPreprocessedAssertionName(*it, "") << "\n";
- paren << "))";
-
- std::ostringstream rewritten;
-
- rewritten << "(or_elim_1 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << ProofManager::currentPM()->getInputFormulaName(inputAssertion);
- rewritten << ") (iff_elim_1 _ _ ";
- rewritten << ProofManager::getPreprocessedAssertionName(*it, "");
- rewritten << "))";
-
- ProofManager::currentPM()->addAssertionFilter(*it, rewritten.str());
- }
- }
- } else {
- for (; it != end; ++it) {
- os << "(th_let_pf _ ";
-
- //TODO
- os << "(trust_f ";
- ProofManager::currentPM()->printTrustedTerm(*it, os, globalLetMap);
- os << ") ";
-
- os << "(\\ "<< ProofManager::getPreprocessedAssertionName(*it, "") << "\n";
- paren << "))";
- }
- }
-
- os << "\n";
-}
-
-void LFSCProof::checkUnrewrittenAssertion(const NodeSet& rewrites) const
-{
- Debug("pf::pm") << "LFSCProof::checkUnrewrittenAssertion starting" << std::endl;
-
- NodeSet::const_iterator rewrite;
- for (rewrite = rewrites.begin(); rewrite != rewrites.end(); ++rewrite) {
- Debug("pf::pm") << "LFSCProof::checkUnrewrittenAssertion: handling " << *rewrite << std::endl;
- if (ProofManager::currentPM()->have_input_assertion((*rewrite).toExpr())) {
- Assert(
- ProofManager::currentPM()->have_input_assertion((*rewrite).toExpr()));
- Debug("pf::pm") << "LFSCProof::checkUnrewrittenAssertion: this assertion was NOT rewritten!" << std::endl
- << "\tAdding filter: "
- << ProofManager::getPreprocessedAssertionName(*rewrite, "")
- << " --> "
- << ProofManager::currentPM()->getInputFormulaName((*rewrite).toExpr())
- << std::endl;
- ProofManager::currentPM()->addAssertionFilter(*rewrite,
- ProofManager::currentPM()->getInputFormulaName((*rewrite).toExpr()));
- } else {
- Debug("pf::pm") << "LFSCProof::checkUnrewrittenAssertion: this assertion WAS rewritten! " << *rewrite << std::endl;
- }
- }
-}
-
-//---from Morgan---
-
-bool ProofManager::hasOp(TNode n) const {
- return d_bops.find(n) != d_bops.end();
-}
-
-Node ProofManager::lookupOp(TNode n) const {
- std::map<Node, Node>::const_iterator i = d_bops.find(n);
- Assert(i != d_bops.end());
- return (*i).second;
-}
-
-Node ProofManager::mkOp(TNode n) {
- Trace("mgd-pm-mkop") << "MkOp : " << n << " " << n.getKind() << std::endl;
- if(n.getKind() != kind::BUILTIN) {
- return n;
- }
-
- Node& op = d_ops[n];
- if(op.isNull()) {
- Assert((n.getConst<Kind>() == kind::SELECT)
- || (n.getConst<Kind>() == kind::STORE));
-
- Debug("mgd-pm-mkop") << "making an op for " << n << "\n";
-
- std::stringstream ss;
- ss << n;
- std::string s = ss.str();
- Debug("mgd-pm-mkop") << " : " << s << std::endl;
- std::vector<TypeNode> v;
- v.push_back(NodeManager::currentNM()->integerType());
- if(n.getConst<Kind>() == kind::SELECT) {
- v.push_back(NodeManager::currentNM()->integerType());
- v.push_back(NodeManager::currentNM()->integerType());
- } else if(n.getConst<Kind>() == kind::STORE) {
- v.push_back(NodeManager::currentNM()->integerType());
- v.push_back(NodeManager::currentNM()->integerType());
- v.push_back(NodeManager::currentNM()->integerType());
- }
- TypeNode type = NodeManager::currentNM()->mkFunctionType(v);
- Debug("mgd-pm-mkop") << "typenode is: " << type << "\n";
- op = NodeManager::currentNM()->mkSkolem(s, type, " ignore", NodeManager::SKOLEM_NO_NOTIFY);
- d_bops[op] = n;
- }
- Debug("mgd-pm-mkop") << "returning the op: " << op << "\n";
- return op;
-}
-//---end from Morgan---
-
-bool ProofManager::wasPrinted(const Type& type) const {
- return d_printedTypes.find(type) != d_printedTypes.end();
-}
-
-void ProofManager::markPrinted(const Type& type) {
- d_printedTypes.insert(type);
-}
-
-void ProofManager::addRewriteFilter(const std::string &original, const std::string &substitute) {
- d_rewriteFilters[original] = substitute;
-}
-
-bool ProofManager::haveRewriteFilter(TNode lit) {
- std::string litName = getLitName(currentPM()->d_cnfProof->getLiteral(lit));
- return d_rewriteFilters.find(litName) != d_rewriteFilters.end();
-}
-
-void ProofManager::clearRewriteFilters() {
- d_rewriteFilters.clear();
-}
-
-std::ostream& operator<<(std::ostream& out, CVC4::ProofRule k) {
- switch(k) {
- case RULE_GIVEN:
- out << "RULE_GIVEN";
- break;
- case RULE_DERIVED:
- out << "RULE_DERIVED";
- break;
- case RULE_RECONSTRUCT:
- out << "RULE_RECONSTRUCT";
- break;
- case RULE_TRUST:
- out << "RULE_TRUST";
- break;
- case RULE_INVALID:
- out << "RULE_INVALID";
- break;
- case RULE_CONFLICT:
- out << "RULE_CONFLICT";
- break;
- case RULE_TSEITIN:
- out << "RULE_TSEITIN";
- break;
- case RULE_SPLIT:
- out << "RULE_SPLIT";
- break;
- case RULE_ARRAYS_EXT:
- out << "RULE_ARRAYS";
- break;
- case RULE_ARRAYS_ROW:
- out << "RULE_ARRAYS";
- break;
- default:
- out << "ProofRule Unknown! [" << unsigned(k) << "]";
- }
-
- return out;
-}
-
-void ProofManager::registerRewrite(unsigned ruleId, Node original, Node result){
- Assert(currentPM()->d_theoryProof != NULL);
- currentPM()->d_rewriteLog.push_back(RewriteLogEntry(ruleId, original, result));
-}
-
-void ProofManager::clearRewriteLog() {
- Assert(currentPM()->d_theoryProof != NULL);
- currentPM()->d_rewriteLog.clear();
-}
-
-std::vector<RewriteLogEntry> ProofManager::getRewriteLog() {
- return currentPM()->d_rewriteLog;
-}
-
-void ProofManager::dumpRewriteLog() const {
- Debug("pf::rr") << "Dumpign rewrite log:" << std::endl;
-
- for (unsigned i = 0; i < d_rewriteLog.size(); ++i) {
- Debug("pf::rr") << "\tRule " << d_rewriteLog[i].getRuleId()
- << ": "
- << d_rewriteLog[i].getOriginal()
- << " --> "
- << d_rewriteLog[i].getResult() << std::endl;
- }
-}
-
-void bind(Expr term, ProofLetMap& map, Bindings& letOrder) {
- ProofLetMap::iterator it = map.find(term);
- if (it != map.end())
- return;
-
- for (unsigned i = 0; i < term.getNumChildren(); ++i)
- bind(term[i], map, letOrder);
-
- // Special case: chain operators. If we have and(a,b,c), it will be prineted as and(a,and(b,c)).
- // The subterm and(b,c) may repeat elsewhere, so we need to bind it, too.
- Kind k = term.getKind();
- if (((k == kind::OR) || (k == kind::AND)) && term.getNumChildren() > 2) {
- Node currentExpression = term[term.getNumChildren() - 1];
- for (int i = term.getNumChildren() - 2; i >= 0; --i) {
- NodeBuilder<> builder(k);
- builder << term[i];
- builder << currentExpression.toExpr();
- currentExpression = builder;
- bind(currentExpression.toExpr(), map, letOrder);
- }
- } else {
- unsigned newId = ProofLetCount::newId();
- ProofLetCount letCount(newId);
- map[term] = letCount;
- letOrder.push_back(LetOrderElement(term, newId));
- }
-}
-
-void ProofManager::printGlobalLetMap(std::set<Node>& atoms,
- ProofLetMap& letMap,
- std::ostream& out,
- std::ostringstream& paren) {
- Bindings letOrder;
- std::set<Node>::const_iterator atom;
- for (atom = atoms.begin(); atom != atoms.end(); ++atom) {
- bind(atom->toExpr(), letMap, letOrder);
- }
-
- // TODO: give each theory a chance to add atoms. For now, just query BV directly...
- const std::set<Node>* additionalAtoms = ProofManager::getBitVectorProof()->getAtomsInBitblastingProof();
- for (atom = additionalAtoms->begin(); atom != additionalAtoms->end(); ++atom) {
- bind(atom->toExpr(), letMap, letOrder);
- }
-
- for (unsigned i = 0; i < letOrder.size(); ++i) {
- Expr currentExpr = letOrder[i].expr;
- unsigned letId = letOrder[i].id;
- ProofLetMap::iterator it = letMap.find(currentExpr);
- Assert(it != letMap.end());
- out << "\n(@ let" << letId << " ";
- d_theoryProof->printBoundTerm(currentExpr, out, letMap);
- paren << ")";
- it->second.increment();
- }
-
- out << std::endl << std::endl;
-}
-
-void ProofManager::ensureLiteral(Node node) {
- d_cnfProof->ensureLiteral(node);
-}
-void ProofManager::printTrustedTerm(Node term,
- std::ostream& os,
- ProofLetMap& globalLetMap)
-{
- TheoryProofEngine* tpe = ProofManager::currentPM()->getTheoryProofEngine();
- if (tpe->printsAsBool(term)) os << "(p_app ";
- tpe->printTheoryTerm(term.toExpr(), os, globalLetMap);
- if (tpe->printsAsBool(term)) os << ")";
-}
-
-ProofManager::ProofManagerStatistics::ProofManagerStatistics()
- : d_proofProductionTime("proof::ProofManager::proofProductionTime"),
- d_theoryLemmaTime(
- "proof::ProofManager::proofProduction::theoryLemmaTime"),
- d_skeletonProofTraceTime(
- "proof::ProofManager::proofProduction::skeletonProofTraceTime"),
- d_proofDeclarationsTime(
- "proof::ProofManager::proofProduction::proofDeclarationsTime"),
- d_cnfProofTime("proof::ProofManager::proofProduction::cnfProofTime"),
- d_finalProofTime("proof::ProofManager::proofProduction::finalProofTime")
-{
- smtStatisticsRegistry()->registerStat(&d_proofProductionTime);
- smtStatisticsRegistry()->registerStat(&d_theoryLemmaTime);
- smtStatisticsRegistry()->registerStat(&d_skeletonProofTraceTime);
- smtStatisticsRegistry()->registerStat(&d_proofDeclarationsTime);
- smtStatisticsRegistry()->registerStat(&d_cnfProofTime);
- smtStatisticsRegistry()->registerStat(&d_finalProofTime);
-}
-
-ProofManager::ProofManagerStatistics::~ProofManagerStatistics()
-{
- smtStatisticsRegistry()->unregisterStat(&d_proofProductionTime);
- smtStatisticsRegistry()->unregisterStat(&d_theoryLemmaTime);
- smtStatisticsRegistry()->unregisterStat(&d_skeletonProofTraceTime);
- smtStatisticsRegistry()->unregisterStat(&d_proofDeclarationsTime);
- smtStatisticsRegistry()->unregisterStat(&d_cnfProofTime);
- smtStatisticsRegistry()->unregisterStat(&d_finalProofTime);
-}
-
} /* CVC4 namespace */
diff --git a/src/proof/proof_manager.h b/src/proof/proof_manager.h
index 45bde4dcb..3013c9b55 100644
--- a/src/proof/proof_manager.h
+++ b/src/proof/proof_manager.h
@@ -28,59 +28,27 @@
#include "context/cdhashset.h"
#include "expr/node.h"
#include "proof/clause_id.h"
-#include "proof/proof.h"
-#include "proof/proof_utils.h"
-#include "proof/skolemization_manager.h"
-#include "theory/logic_info.h"
-#include "theory/substitutions.h"
-#include "util/proof.h"
#include "util/statistics_registry.h"
namespace CVC4 {
-class SmtGlobals;
-
// forward declarations
namespace Minisat {
class Solver;
}/* Minisat namespace */
-namespace BVMinisat {
- class Solver;
-}/* BVMinisat namespace */
-
namespace prop {
class CnfStream;
}/* CVC4::prop namespace */
class SmtEngine;
-const ClauseId ClauseIdEmpty(-1);
-const ClauseId ClauseIdUndef(-2);
-const ClauseId ClauseIdError(-3);
-
template <class Solver> class TSatProof;
typedef TSatProof< CVC4::Minisat::Solver> CoreSatProof;
class CnfProof;
-class RewriterProof;
-class TheoryProofEngine;
-class TheoryProof;
-class UFProof;
-class ArithProof;
-class ArrayProof;
-
-namespace proof {
-class ResolutionBitVectorProof;
-}
-
-template <class Solver> class LFSCSatProof;
-typedef TSatProof<CVC4::Minisat::Solver> CoreSatProof;
-class LFSCCnfProof;
-class LFSCTheoryProofEngine;
-class LFSCUFProof;
-class LFSCRewriterProof;
+typedef TSatProof<CVC4::Minisat::Solver> CoreSatProof;
namespace prop {
typedef uint64_t SatVariable;
@@ -88,291 +56,72 @@ namespace prop {
typedef std::vector<SatLiteral> SatClause;
}/* CVC4::prop namespace */
-// different proof modes
-enum ProofFormat {
- LFSC,
- NATIVE
-};/* enum ProofFormat */
-
-std::string append(const std::string& str, uint64_t num);
-
typedef std::unordered_map<ClauseId, prop::SatClause*> IdToSatClause;
typedef context::CDHashSet<Expr, ExprHashFunction> CDExprSet;
-typedef std::unordered_map<Node, std::vector<Node>, NodeHashFunction> NodeToNodes;
typedef context::CDHashMap<Node, std::vector<Node>, NodeHashFunction> CDNodeToNodes;
typedef std::unordered_set<ClauseId> IdHashSet;
-enum ProofRule {
- RULE_GIVEN, /* input assertion */
- RULE_DERIVED, /* a "macro" rule */
- RULE_RECONSTRUCT, /* prove equivalence using another method */
- RULE_TRUST, /* trust without evidence (escape hatch until proofs are fully supported) */
- RULE_INVALID, /* assert-fail if this is ever needed in proof; use e.g. for split lemmas */
- RULE_CONFLICT, /* re-construct as a conflict */
- RULE_TSEITIN, /* Tseitin CNF transformation */
- RULE_SPLIT, /* A splitting lemma of the form a v ~ a*/
-
- RULE_ARRAYS_EXT, /* arrays, extensional */
- RULE_ARRAYS_ROW, /* arrays, read-over-write */
-};/* enum ProofRules */
-
-class RewriteLogEntry {
-public:
- RewriteLogEntry(unsigned ruleId, Node original, Node result)
- : d_ruleId(ruleId), d_original(original), d_result(result) {
- }
-
- unsigned getRuleId() const {
- return d_ruleId;
- }
-
- Node getOriginal() const {
- return d_original;
- }
-
- Node getResult() const {
- return d_result;
- }
-
-private:
- unsigned d_ruleId;
- Node d_original;
- Node d_result;
-};
-
class ProofManager {
context::Context* d_context;
std::unique_ptr<CoreSatProof> d_satProof;
std::unique_ptr<CnfProof> d_cnfProof;
- std::unique_ptr<TheoryProofEngine> d_theoryProof;
// information that will need to be shared across proofs
- ExprSet d_inputFormulas;
- std::map<Expr, std::string> d_inputFormulaToName;
CDExprSet d_inputCoreFormulas;
CDExprSet d_outputCoreFormulas;
- SkolemizationManager d_skolemizationManager;
-
int d_nextId;
- std::unique_ptr<Proof> d_fullProof;
- ProofFormat d_format; // used for now only in debug builds
-
CDNodeToNodes d_deps;
- std::set<Type> d_printedTypes;
-
- std::map<std::string, std::string> d_rewriteFilters;
- std::map<Node, std::string> d_assertionFilters;
-
- std::vector<RewriteLogEntry> d_rewriteLog;
-
-protected:
- LogicInfo d_logic;
-
public:
- ProofManager(context::Context* context, ProofFormat format = LFSC);
- ~ProofManager();
-
- static ProofManager* currentPM();
-
- // initialization
- void initSatProof(Minisat::Solver* solver);
- void initCnfProof(CVC4::prop::CnfStream* cnfStream, context::Context* ctx);
- void initTheoryProofEngine();
-
- // getting various proofs
- static const Proof& getProof(SmtEngine* smt);
- static CoreSatProof* getSatProof();
- static CnfProof* getCnfProof();
- static TheoryProofEngine* getTheoryProofEngine();
- static TheoryProof* getTheoryProof( theory::TheoryId id );
- static UFProof* getUfProof();
- static proof::ResolutionBitVectorProof* getBitVectorProof();
- static ArrayProof* getArrayProof();
- static ArithProof* getArithProof();
-
- static SkolemizationManager *getSkolemizationManager();
-
- // iterators over data shared by proofs
- typedef ExprSet::const_iterator assertions_iterator;
-
- // iterate over the assertions (these are arbitrary boolean formulas)
- assertions_iterator begin_assertions() const {
- return d_inputFormulas.begin();
- }
- assertions_iterator end_assertions() const { return d_inputFormulas.end(); }
- size_t num_assertions() const { return d_inputFormulas.size(); }
- bool have_input_assertion(const Expr& assertion) {
- return d_inputFormulas.find(assertion) != d_inputFormulas.end();
- }
-
- void ensureLiteral(Node node);
-
-//---from Morgan---
- Node mkOp(TNode n);
- Node lookupOp(TNode n) const;
- bool hasOp(TNode n) const;
-
- std::map<Node, Node> d_ops;
- std::map<Node, Node> d_bops;
-//---end from Morgan---
-
-
- // variable prefixes
- static std::string getInputClauseName(ClauseId id, const std::string& prefix = "");
- static std::string getLemmaClauseName(ClauseId id, const std::string& prefix = "");
- static std::string getLemmaName(ClauseId id, const std::string& prefix = "");
- static std::string getLearntClauseName(ClauseId id, const std::string& prefix = "");
- static std::string getPreprocessedAssertionName(Node node, const std::string& prefix = "");
- static std::string getAssertionName(Node node, const std::string& prefix = "");
- static std::string getInputFormulaName(const Expr& expr);
-
- static std::string getVarName(prop::SatVariable var, const std::string& prefix = "");
- static std::string getAtomName(prop::SatVariable var, const std::string& prefix = "");
- static std::string getAtomName(TNode atom, const std::string& prefix = "");
- static std::string getLitName(prop::SatLiteral lit, const std::string& prefix = "");
- static std::string getLitName(TNode lit, const std::string& prefix = "");
- static bool hasLitName(TNode lit);
-
- // for SMT variable names that have spaces and other things
- static std::string sanitize(TNode var);
-
- // wrap term with (p_app ... ) if the term is printed as a boolean, and print
- // used for "trust" assertions
- static void printTrustedTerm(Node term,
- std::ostream& os,
- ProofLetMap& globalLetMap);
-
- /** Add proof assertion - unlike addCoreAssertion this is post definition expansion **/
- void addAssertion(Expr formula);
-
- /** Public unsat core methods **/
- void addCoreAssertion(Expr formula);
-
- void addDependence(TNode n, TNode dep);
- void addUnsatCore(Expr formula);
-
- // trace dependences back to unsat core
- void traceDeps(TNode n, ExprSet* coreAssertions);
- void traceDeps(TNode n, CDExprSet* coreAssertions);
- void traceUnsatCore();
-
- typedef CDExprSet::const_iterator output_core_iterator;
-
- output_core_iterator begin_unsat_core() const { return d_outputCoreFormulas.begin(); }
- output_core_iterator end_unsat_core() const { return d_outputCoreFormulas.end(); }
- size_t size_unsat_core() const { return d_outputCoreFormulas.size(); }
- std::vector<Expr> extractUnsatCore();
-
- bool unsatCoreAvailable() const;
- void getLemmasInUnsatCore(theory::TheoryId theory, std::vector<Node> &lemmas);
- Node getWeakestImplicantInUnsatCore(Node lemma);
-
- int nextId() { return d_nextId++; }
-
- void setLogic(const LogicInfo& logic);
- const std::string getLogic() const { return d_logic.getLogicString(); }
- LogicInfo & getLogicInfo() { return d_logic; }
-
- void markPrinted(const Type& type);
- bool wasPrinted(const Type& type) const;
-
- void addRewriteFilter(const std::string &original, const std::string &substitute);
- void clearRewriteFilters();
- bool haveRewriteFilter(TNode lit);
-
- void addAssertionFilter(const Node& node, const std::string& rewritten);
-
- static void registerRewrite(unsigned ruleId, Node original, Node result);
- static void clearRewriteLog();
-
- std::vector<RewriteLogEntry> getRewriteLog();
- void dumpRewriteLog() const;
+ ProofManager(context::Context* context);
+ ~ProofManager();
- void printGlobalLetMap(std::set<Node>& atoms,
- ProofLetMap& letMap,
- std::ostream& out,
- std::ostringstream& paren);
-
- struct ProofManagerStatistics
- {
- ProofManagerStatistics();
- ~ProofManagerStatistics();
+ static ProofManager* currentPM();
- /**
- * Time spent producing proofs (i.e. generating the proof from the logging
- * information)
- */
- TimerStat d_proofProductionTime;
+ // initialization
+ void initSatProof(Minisat::Solver* solver);
+ void initCnfProof(CVC4::prop::CnfStream* cnfStream, context::Context* ctx);
- /**
- * Time spent printing proofs of theory lemmas
- */
- TimerStat d_theoryLemmaTime;
+ // getting various proofs
+ static CoreSatProof* getSatProof();
+ static CnfProof* getCnfProof();
- /**
- * Time spent tracing the proof of the boolean skeleton
- * (e.g. figuring out which assertions are needed, etc.)
- */
- TimerStat d_skeletonProofTraceTime;
+ /** Public unsat core methods **/
+ void addCoreAssertion(Expr formula);
- /**
- * Time spent processing and printing declarations in the proof
- */
- TimerStat d_proofDeclarationsTime;
+ void addDependence(TNode n, TNode dep);
+ void addUnsatCore(Expr formula);
- /**
- * Time spent printing the CNF proof
- */
- TimerStat d_cnfProofTime;
+ // trace dependences back to unsat core
+ void traceDeps(TNode n, CDExprSet* coreAssertions);
+ void traceUnsatCore();
- /**
- * Time spent printing the final proof of UNSAT
- */
- TimerStat d_finalProofTime;
+ typedef CDExprSet::const_iterator output_core_iterator;
- }; /* struct ProofManagerStatistics */
+ output_core_iterator begin_unsat_core() const
+ {
+ return d_outputCoreFormulas.begin();
+ }
+ output_core_iterator end_unsat_core() const
+ {
+ return d_outputCoreFormulas.end();
+ }
+ size_t size_unsat_core() const { return d_outputCoreFormulas.size(); }
+ std::vector<Expr> extractUnsatCore();
- ProofManagerStatistics& getStats() { return d_stats; }
+ bool unsatCoreAvailable() const;
+ void getLemmasInUnsatCore(std::vector<Node>& lemmas);
- private:
- void constructSatProof();
- std::set<Node> satClauseToNodeSet(prop::SatClause* clause);
+ int nextId() { return d_nextId++; }
- ProofManagerStatistics d_stats;
+private:
+ void constructSatProof();
};/* class ProofManager */
-class LFSCProof : public Proof
-{
- public:
- LFSCProof(SmtEngine* smtEngine,
- CoreSatProof* sat,
- LFSCCnfProof* cnf,
- LFSCTheoryProofEngine* theory);
- ~LFSCProof() override {}
- void toStream(std::ostream& out) const override;
- void toStream(std::ostream& out, const ProofLetMap& map) const override;
-
- private:
- // FIXME: hack until we get preprocessing
- void printPreprocessedAssertions(const NodeSet& assertions,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap& globalLetMap) const;
-
- void checkUnrewrittenAssertion(const NodeSet& assertions) const;
-
- CoreSatProof* d_satProof;
- LFSCCnfProof* d_cnfProof;
- LFSCTheoryProofEngine* d_theoryProof;
- SmtEngine* d_smtEngine;
-}; /* class LFSCProof */
-
-std::ostream& operator<<(std::ostream& out, CVC4::ProofRule k);
}/* CVC4 namespace */
diff --git a/src/proof/proof_output_channel.cpp b/src/proof/proof_output_channel.cpp
deleted file mode 100644
index 88467aea6..000000000
--- a/src/proof/proof_output_channel.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/********************* */
-/*! \file proof_output_channel.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Tim King, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "proof/proof_output_channel.h"
-
-#include "base/check.h"
-#include "theory/term_registration_visitor.h"
-#include "theory/valuation.h"
-
-namespace CVC4 {
-
-ProofOutputChannel::ProofOutputChannel() : d_conflict(), d_proof(nullptr) {}
-const Proof& ProofOutputChannel::getConflictProof() const
-{
- Assert(hasConflict());
- return *d_proof;
-}
-
-void ProofOutputChannel::conflict(TNode n, std::unique_ptr<Proof> pf)
-{
- Trace("pf::tp") << "ProofOutputChannel: CONFLICT: " << n << std::endl;
- Assert(!hasConflict());
- Assert(!d_proof);
- d_conflict = n;
- d_proof = std::move(pf);
- Assert(hasConflict());
- Assert(d_proof);
-}
-
-bool ProofOutputChannel::propagate(TNode x) {
- Trace("pf::tp") << "ProofOutputChannel: got a propagation: " << x
- << std::endl;
- d_propagations.insert(x);
- return true;
-}
-
-theory::LemmaStatus ProofOutputChannel::lemma(TNode n,
- ProofRule rule,
- theory::LemmaProperty p)
-{
- Trace("pf::tp") << "ProofOutputChannel: new lemma: " << n << std::endl;
- // TODO(#1231): We should transition to supporting multiple lemmas. The
- // following assertion cannot be enabled due to
- // "test/regress/regress0/arrays/swap_t1_np_nf_ai_00005_007.cvc.smt".
- // Assert(
- // d_lemma.isNull()) <<
- // "Multiple calls to ProofOutputChannel::lemma() are not supported.";
- d_lemma = n;
- return theory::LemmaStatus(TNode::null(), 0);
-}
-
-theory::LemmaStatus ProofOutputChannel::splitLemma(TNode, bool) {
- AlwaysAssert(false);
- return theory::LemmaStatus(TNode::null(), 0);
-}
-
-void ProofOutputChannel::requirePhase(TNode n, bool b) {
- Debug("pf::tp") << "ProofOutputChannel::requirePhase called" << std::endl;
- Trace("pf::tp") << "requirePhase " << n << " " << b << std::endl;
-}
-
-void ProofOutputChannel::setIncomplete() {
- Debug("pf::tp") << "ProofOutputChannel::setIncomplete called" << std::endl;
- AlwaysAssert(false);
-}
-
-
-MyPreRegisterVisitor::MyPreRegisterVisitor(theory::Theory* theory)
- : d_theory(theory)
- , d_visited() {
-}
-
-bool MyPreRegisterVisitor::alreadyVisited(TNode current, TNode parent) {
- return d_visited.find(current) != d_visited.end();
-}
-
-void MyPreRegisterVisitor::visit(TNode current, TNode parent) {
- d_theory->preRegisterTerm(current);
- d_visited.insert(current);
-}
-
-void MyPreRegisterVisitor::start(TNode node) {
-}
-
-void MyPreRegisterVisitor::done(TNode node) {
-}
-
-} /* namespace CVC4 */
diff --git a/src/proof/proof_output_channel.h b/src/proof/proof_output_channel.h
deleted file mode 100644
index b68abd44b..000000000
--- a/src/proof/proof_output_channel.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/********************* */
-/*! \file proof_output_channel.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Tim King, Guy Katz, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF_OUTPUT_CHANNEL_H
-#define CVC4__PROOF_OUTPUT_CHANNEL_H
-
-#include <memory>
-#include <set>
-#include <unordered_set>
-
-#include "expr/node.h"
-#include "theory/output_channel.h"
-#include "theory/theory.h"
-#include "util/proof.h"
-
-namespace CVC4 {
-
-class ProofOutputChannel : public theory::OutputChannel {
- public:
- ProofOutputChannel();
- ~ProofOutputChannel() override {}
-
- /**
- * This may be called at most once per ProofOutputChannel.
- * Requires that `n` and `pf` are non-null.
- */
- void conflict(TNode n, std::unique_ptr<Proof> pf) override;
- bool propagate(TNode x) override;
- theory::LemmaStatus lemma(TNode n,
- ProofRule rule,
- theory::LemmaProperty p) override;
- theory::LemmaStatus splitLemma(TNode, bool) override;
- void requirePhase(TNode n, bool b) override;
- void setIncomplete() override;
-
- /** Has conflict() has been called? */
- bool hasConflict() const { return !d_conflict.isNull(); }
-
- /**
- * Returns the proof passed into the conflict() call.
- * Requires hasConflict() to hold.
- */
- const Proof& getConflictProof() const;
- Node getLastLemma() const { return d_lemma; }
-
- private:
- Node d_conflict;
- std::unique_ptr<Proof> d_proof;
- Node d_lemma;
- std::set<Node> d_propagations;
-}; /* class ProofOutputChannel */
-
-class MyPreRegisterVisitor {
- theory::Theory* d_theory;
- std::unordered_set<TNode, TNodeHashFunction> d_visited;
-public:
- typedef void return_type;
- MyPreRegisterVisitor(theory::Theory* theory);
- bool alreadyVisited(TNode current, TNode parent);
- void visit(TNode current, TNode parent);
- void start(TNode node);
- void done(TNode node);
-}; /* class MyPreRegisterVisitor */
-
-} /* CVC4 namespace */
-
-#endif /* CVC4__PROOF_OUTPUT_CHANNEL_H */
diff --git a/src/proof/proof_utils.cpp b/src/proof/proof_utils.cpp
deleted file mode 100644
index cad56db6a..000000000
--- a/src/proof/proof_utils.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/********************* */
-/*! \file proof_utils.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Liana Hadarean, Andrew Reynolds, Guy Katz
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "proof/proof_utils.h"
-#include "theory/theory.h"
-
-namespace CVC4 {
-namespace utils {
-
-std::string toLFSCKind(Kind kind) {
- switch(kind) {
- // core kinds
- case kind::OR : return "or";
- case kind::AND: return "and";
- case kind::XOR: return "xor";
- case kind::EQUAL: return "=";
- case kind::IMPLIES: return "impl";
- case kind::NOT: return "not";
-
- // bit-vector kinds
- case kind::BITVECTOR_AND :
- return "bvand";
- case kind::BITVECTOR_OR :
- return "bvor";
- case kind::BITVECTOR_XOR :
- return "bvxor";
- case kind::BITVECTOR_NAND :
- return "bvnand";
- case kind::BITVECTOR_NOR :
- return "bvnor";
- case kind::BITVECTOR_XNOR :
- return "bvxnor";
- case kind::BITVECTOR_COMP :
- return "bvcomp";
- case kind::BITVECTOR_MULT :
- return "bvmul";
- case kind::BITVECTOR_PLUS :
- return "bvadd";
- case kind::BITVECTOR_SUB :
- return "bvsub";
- case kind::BITVECTOR_UDIV :
- case kind::BITVECTOR_UDIV_TOTAL :
- return "bvudiv";
- case kind::BITVECTOR_UREM :
- case kind::BITVECTOR_UREM_TOTAL :
- return "bvurem";
- case kind::BITVECTOR_SDIV :
- return "bvsdiv";
- case kind::BITVECTOR_SREM :
- return "bvsrem";
- case kind::BITVECTOR_SMOD :
- return "bvsmod";
- case kind::BITVECTOR_SHL :
- return "bvshl";
- case kind::BITVECTOR_LSHR :
- return "bvlshr";
- case kind::BITVECTOR_ASHR :
- return "bvashr";
- case kind::BITVECTOR_CONCAT :
- return "concat";
- case kind::BITVECTOR_NEG :
- return "bvneg";
- case kind::BITVECTOR_NOT :
- return "bvnot";
- case kind::BITVECTOR_ROTATE_LEFT :
- return "rotate_left";
- case kind::BITVECTOR_ROTATE_RIGHT :
- return "rotate_right";
- case kind::BITVECTOR_ULT :
- return "bvult";
- case kind::BITVECTOR_ULE :
- return "bvule";
- case kind::BITVECTOR_UGT :
- return "bvugt";
- case kind::BITVECTOR_UGE :
- return "bvuge";
- case kind::BITVECTOR_SLT :
- return "bvslt";
- case kind::BITVECTOR_SLE :
- return "bvsle";
- case kind::BITVECTOR_SGT :
- return "bvsgt";
- case kind::BITVECTOR_SGE :
- return "bvsge";
- case kind::BITVECTOR_EXTRACT :
- return "extract";
- case kind::BITVECTOR_REPEAT :
- return "repeat";
- case kind::BITVECTOR_ZERO_EXTEND :
- return "zero_extend";
- case kind::BITVECTOR_SIGN_EXTEND :
- return "sign_extend";
- default:
- Unreachable();
- }
-}
-
-std::string toLFSCKindTerm(Expr node) {
- Kind k = node.getKind();
- if( k==kind::EQUAL ){
- if( node[0].getType().isBoolean() ){
- return "iff";
- }else{
- return "=";
- }
- }else{
- return toLFSCKind( k );
- }
-}
-
-} /* namespace CVC4::utils */
-} /* namespace CVC4 */
diff --git a/src/proof/proof_utils.h b/src/proof/proof_utils.h
deleted file mode 100644
index e54edd8b7..000000000
--- a/src/proof/proof_utils.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/********************* */
-/*! \file proof_utils.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Liana Hadarean, Guy Katz, Dejan Jovanovic
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "cvc4_private.h"
-
-#pragma once
-
-#include <set>
-#include <sstream>
-#include <unordered_set>
-#include <vector>
-
-#include "expr/node_manager.h"
-
-namespace CVC4 {
-
-typedef std::unordered_set<Expr, ExprHashFunction> ExprSet;
-typedef std::unordered_set<Node, NodeHashFunction> NodeSet;
-
-typedef std::pair<Node, Node> NodePair;
-typedef std::set<NodePair> NodePairSet;
-
-
-class ProofLetCount {
-public:
- static unsigned counter;
- static void resetCounter() { counter = 0; }
- static unsigned newId() { return ++counter; }
-
- unsigned count;
- unsigned id;
- ProofLetCount()
- : count(0)
- , id(-1)
- {}
-
- void increment() { ++count; }
- ProofLetCount(unsigned i)
- : count(1)
- , id(i)
- {}
-
- ProofLetCount(const ProofLetCount& other)
- : count(other.count)
- , id (other.id)
- {}
-
- bool operator==(const ProofLetCount &other) const {
- return other.id == id && other.count == count;
- }
-
- ProofLetCount& operator=(const ProofLetCount &rhs) {
- if (&rhs == this) return *this;
- id = rhs.id;
- count = rhs.count;
- return *this;
- }
-};
-
-struct LetOrderElement {
- Expr expr;
- unsigned id;
- LetOrderElement(Expr e, unsigned i)
- : expr(e)
- , id(i)
- {}
-
- LetOrderElement()
- : expr()
- , id(-1)
- {}
-};
-
-typedef std::vector<LetOrderElement> Bindings;
-
-namespace utils {
-
-std::string toLFSCKind(Kind kind);
-std::string toLFSCKindTerm(Expr node);
-
-inline unsigned getExtractHigh(Expr node) {
- return node.getOperator().getConst<BitVectorExtract>().d_high;
-}
-
-inline unsigned getExtractLow(Expr node) {
- return node.getOperator().getConst<BitVectorExtract>().d_low;
-}
-
-inline unsigned getSize(Type type) {
- BitVectorType bv(type);
- return bv.getSize();
-}
-
-
-inline unsigned getSize(Expr node) {
- Assert(node.getType().isBitVector());
- return getSize(node.getType());
-}
-
-inline Expr mkTrue() {
- return NodeManager::currentNM()->toExprManager()->mkConst<bool>(true);
-}
-
-inline Expr mkFalse() {
- return NodeManager::currentNM()->toExprManager()->mkConst<bool>(false);
-}
-
-inline Expr mkExpr(Kind k , Expr expr) {
- return NodeManager::currentNM()->toExprManager()->mkExpr(k, expr);
-}
-inline Expr mkExpr(Kind k , Expr e1, Expr e2) {
- return NodeManager::currentNM()->toExprManager()->mkExpr(k, e1, e2);
-}
-inline Expr mkExpr(Kind k , std::vector<Expr>& children) {
- return NodeManager::currentNM()->toExprManager()->mkExpr(k, children);
-}
-
-
-inline Expr mkOnes(unsigned size) {
- BitVector val = BitVector::mkOnes(size);
- return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(val);
-}
-
-inline Expr mkConst(unsigned size, unsigned int value) {
- BitVector val(size, value);
- return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(val);
-}
-
-inline Expr mkConst(const BitVector& value) {
- return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(value);
-}
-
-inline Expr mkOr(const std::vector<Expr>& nodes) {
- std::set<Expr> all;
- all.insert(nodes.begin(), nodes.end());
- Assert(all.size() != 0);
-
- if (all.size() == 1) {
- // All the same, or just one
- return nodes[0];
- }
-
-
- NodeBuilder<> disjunction(kind::OR);
- std::set<Expr>::const_iterator it = all.begin();
- std::set<Expr>::const_iterator it_end = all.end();
- while (it != it_end) {
- disjunction << Node::fromExpr(*it);
- ++ it;
- }
-
- Node res = disjunction;
- return res.toExpr();
-}/* mkOr() */
-
-
-inline Expr mkAnd(const std::vector<Expr>& conjunctions) {
- std::set<Expr> all;
- all.insert(conjunctions.begin(), conjunctions.end());
-
- if (all.size() == 0) {
- return mkTrue();
- }
-
- if (all.size() == 1) {
- // All the same, or just one
- return conjunctions[0];
- }
-
-
- NodeBuilder<> conjunction(kind::AND);
- std::set<Expr>::const_iterator it = all.begin();
- std::set<Expr>::const_iterator it_end = all.end();
- while (it != it_end) {
- conjunction << Node::fromExpr(*it);
- ++ it;
- }
-
- Node res = conjunction;
- return res.toExpr();
-}/* mkAnd() */
-
-inline Expr mkSortedExpr(Kind kind, const std::vector<Expr>& children) {
- std::set<Expr> all;
- all.insert(children.begin(), children.end());
-
- if (all.size() == 0) {
- return mkTrue();
- }
-
- if (all.size() == 1) {
- // All the same, or just one
- return children[0];
- }
-
-
- NodeBuilder<> res(kind);
- std::set<Expr>::const_iterator it = all.begin();
- std::set<Expr>::const_iterator it_end = all.end();
- while (it != it_end) {
- res << Node::fromExpr(*it);
- ++ it;
- }
-
- return ((Node)res).toExpr();
-}/* mkSortedNode() */
-
-inline const bool getBit(Expr expr, unsigned i) {
- Assert(i < utils::getSize(expr) && expr.isConst());
- Integer bit = expr.getConst<BitVector>().extract(i, i).getValue();
- return (bit == 1u);
-}
-
-}
-}
diff --git a/src/proof/resolution_bitvector_proof.cpp b/src/proof/resolution_bitvector_proof.cpp
deleted file mode 100644
index d48789f71..000000000
--- a/src/proof/resolution_bitvector_proof.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-/********************* */
-/*! \file resolution_bitvector_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Liana Hadarean, Guy Katz
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "proof/resolution_bitvector_proof.h"
-#include "options/bv_options.h"
-#include "options/proof_options.h"
-#include "proof/array_proof.h"
-#include "proof/bitvector_proof.h"
-#include "proof/clause_id.h"
-#include "proof/lfsc_proof_printer.h"
-#include "proof/proof_output_channel.h"
-#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"
-
-#include <iostream>
-#include <sstream>
-
-using namespace CVC4::theory;
-using namespace CVC4::theory::bv;
-
-namespace CVC4 {
-
-namespace proof {
-
-ResolutionBitVectorProof::ResolutionBitVectorProof(
- theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine)
- : BitVectorProof(bv, proofEngine),
- d_resolutionProof(),
- d_isAssumptionConflict(false)
-{
-}
-
-void ResolutionBitVectorProof::initSatProof(CVC4::BVMinisat::Solver* solver)
-{
- Assert(d_resolutionProof == NULL);
- d_resolutionProof.reset(new BVSatProof(solver, &d_fakeContext, "bb", true));
-}
-
-void ResolutionBitVectorProof::initCnfProof(prop::CnfStream* cnfStream,
- context::Context* cnf,
- prop::SatVariable trueVar,
- prop::SatVariable falseVar)
-{
- 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::attachToSatSolver(prop::SatSolver& sat_solver)
-{
- sat_solver.setResolutionProofLog(this);
-}
-
-BVSatProof* ResolutionBitVectorProof::getSatProof()
-{
- Assert(d_resolutionProof != NULL);
- return d_resolutionProof.get();
-}
-
-void ResolutionBitVectorProof::startBVConflict(
- CVC4::BVMinisat::Solver::TCRef cr)
-{
- d_resolutionProof->startResChain(cr);
-}
-
-void ResolutionBitVectorProof::startBVConflict(
- CVC4::BVMinisat::Solver::TLit lit)
-{
- d_resolutionProof->startResChain(lit);
-}
-
-void ResolutionBitVectorProof::endBVConflict(
- const CVC4::BVMinisat::Solver::TLitVec& confl)
-{
- Debug("pf::bv") << "ResolutionBitVectorProof::endBVConflict called"
- << std::endl;
-
- std::vector<Expr> expr_confl;
- for (int i = 0; i < confl.size(); ++i)
- {
- prop::SatLiteral lit = prop::BVMinisatSatSolver::toSatLiteral(confl[i]);
- Expr atom = d_cnfProof->getAtom(lit.getSatVariable()).toExpr();
- Expr expr_lit = lit.isNegated() ? atom.notExpr() : atom;
- expr_confl.push_back(expr_lit);
- }
-
- Expr conflict = utils::mkSortedExpr(kind::OR, expr_confl);
- Debug("pf::bv") << "Make conflict for " << conflict << std::endl;
-
- if (d_bbConflictMap.find(conflict) != d_bbConflictMap.end())
- {
- Debug("pf::bv") << "Abort...already conflict for " << conflict << std::endl;
- // This can only happen when we have eager explanations in the bv solver
- // if we don't get to propagate p before ~p is already asserted
- d_resolutionProof->cancelResChain();
- return;
- }
-
- // we don't need to check for uniqueness in the sat solver then
- ClauseId clause_id = d_resolutionProof->registerAssumptionConflict(confl);
- d_bbConflictMap[conflict] = clause_id;
- d_resolutionProof->endResChain(clause_id);
- Debug("pf::bv") << "ResolutionBitVectorProof::endBVConflict id" << clause_id
- << " => " << conflict << "\n";
- d_isAssumptionConflict = false;
-}
-
-void ResolutionBitVectorProof::finalizeConflicts(std::vector<Expr>& conflicts)
-{
- if (options::bitblastMode() == options::BitblastMode::EAGER)
- {
- Debug("pf::bv") << "Construct full proof." << std::endl;
- d_resolutionProof->constructProof();
- return;
- }
-
- for (unsigned i = 0; i < conflicts.size(); ++i)
- {
- Expr confl = conflicts[i];
- Debug("pf::bv") << "Finalize conflict #" << i << ": " << confl << std::endl;
-
- // Special case: if the conflict has a (true) or a (not false) in it, it is
- // trivial...
- bool ignoreConflict = false;
- if ((confl.isConst() && confl.getConst<bool>())
- || (confl.getKind() == kind::NOT && confl[0].isConst()
- && !confl[0].getConst<bool>()))
- {
- ignoreConflict = true;
- }
- else if (confl.getKind() == kind::OR)
- {
- for (unsigned k = 0; k < confl.getNumChildren(); ++k)
- {
- if ((confl[k].isConst() && confl[k].getConst<bool>())
- || (confl[k].getKind() == kind::NOT && confl[k][0].isConst()
- && !confl[k][0].getConst<bool>()))
- {
- ignoreConflict = true;
- }
- }
- }
- if (ignoreConflict)
- {
- Debug("pf::bv") << "Ignoring conflict due to (true) or (not false)"
- << std::endl;
- continue;
- }
-
- if (d_bbConflictMap.find(confl) != d_bbConflictMap.end())
- {
- ClauseId id = d_bbConflictMap[confl];
- d_resolutionProof->collectClauses(id);
- }
- else
- {
- // There is no exact match for our conflict, but maybe it is a subset of
- // another conflict
- ExprToClauseId::const_iterator it;
- bool matchFound = false;
- for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it)
- {
- Expr possibleMatch = it->first;
- if (possibleMatch.getKind() != kind::OR)
- {
- // This is a single-node conflict. If this node is in the conflict
- // we're trying to prove, we have a match.
- for (unsigned k = 0; k < confl.getNumChildren(); ++k)
- {
- if (confl[k] == possibleMatch)
- {
- matchFound = true;
- d_resolutionProof->collectClauses(it->second);
- break;
- }
- }
- }
- else
- {
- if (possibleMatch.getNumChildren() > confl.getNumChildren()) continue;
-
- unsigned k = 0;
- bool matching = true;
- for (unsigned j = 0; j < possibleMatch.getNumChildren(); ++j)
- {
- // j is the index in possibleMatch
- // k is the index in confl
- while (k < confl.getNumChildren() && confl[k] != possibleMatch[j])
- {
- ++k;
- }
- if (k == confl.getNumChildren())
- {
- // We couldn't find a match for possibleMatch[j], so not a match
- matching = false;
- break;
- }
- }
-
- if (matching)
- {
- Debug("pf::bv")
- << "Collecting info from a sub-conflict" << std::endl;
- d_resolutionProof->collectClauses(it->second);
- matchFound = true;
- break;
- }
- }
- }
-
- if (!matchFound)
- {
- Debug("pf::bv") << "Do not collect clauses for " << confl << std::endl
- << "Dumping existing conflicts:" << std::endl;
-
- i = 0;
- for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it)
- {
- ++i;
- Debug("pf::bv") << "\tConflict #" << i << ": " << it->first
- << std::endl;
- }
-
- Unreachable();
- }
- }
- }
-}
-
-void LfscResolutionBitVectorProof::printTheoryLemmaProof(
- std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map)
-{
- Debug("pf::bv")
- << "(pf::bv) LfscResolutionBitVectorProof::printTheoryLemmaProof called"
- << std::endl;
- Expr conflict = utils::mkSortedExpr(kind::OR, lemma);
- Debug("pf::bv") << "\tconflict = " << conflict << std::endl;
-
- if (d_bbConflictMap.find(conflict) != d_bbConflictMap.end())
- {
- std::ostringstream lemma_paren;
- for (unsigned i = 0; i < lemma.size(); ++i)
- {
- Expr lit = lemma[i];
-
- if (lit.getKind() == kind::NOT)
- {
- os << "(intro_assump_t _ _ _ ";
- }
- else
- {
- os << "(intro_assump_f _ _ _ ";
- }
- lemma_paren << ")";
- // print corresponding literal in main sat solver
- ProofManager* pm = ProofManager::currentPM();
- CnfProof* cnf = pm->getCnfProof();
- prop::SatLiteral main_lit = cnf->getLiteral(lit);
- os << pm->getLitName(main_lit);
- os << " ";
- // print corresponding literal in bv sat solver
- prop::SatVariable bb_var = d_cnfProof->getLiteral(lit).getSatVariable();
- os << pm->getAtomName(bb_var, "bb");
- os << "(\\ unit" << bb_var << "\n";
- lemma_paren << ")";
- }
- Expr lem = utils::mkOr(lemma);
- Assert(d_bbConflictMap.find(lem) != d_bbConflictMap.end());
- ClauseId lemma_id = d_bbConflictMap[lem];
- proof::LFSCProofPrinter::printAssumptionsResolution(
- d_resolutionProof.get(), lemma_id, os, lemma_paren);
- os << lemma_paren.str();
- }
- else
- {
- Debug("pf::bv") << "Found a non-recorded conflict. Looking for a matching "
- "sub-conflict..."
- << std::endl;
-
- bool matching;
-
- ExprToClauseId::const_iterator it;
- unsigned i = 0;
- for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it)
- {
- // Our conflict is sorted, and the records are also sorted.
- ++i;
- Expr possibleMatch = it->first;
-
- if (possibleMatch.getKind() != kind::OR)
- {
- // This is a single-node conflict. If this node is in the conflict we're
- // trying to prove, we have a match.
- matching = false;
-
- for (unsigned k = 0; k < conflict.getNumChildren(); ++k)
- {
- if (conflict[k] == possibleMatch)
- {
- matching = true;
- break;
- }
- }
- }
- else
- {
- if (possibleMatch.getNumChildren() > conflict.getNumChildren())
- continue;
-
- unsigned k = 0;
-
- matching = true;
- for (unsigned j = 0; j < possibleMatch.getNumChildren(); ++j)
- {
- // j is the index in possibleMatch
- // k is the index in conflict
- while (k < conflict.getNumChildren()
- && conflict[k] != possibleMatch[j])
- {
- ++k;
- }
- if (k == conflict.getNumChildren())
- {
- // We couldn't find a match for possibleMatch[j], so not a match
- matching = false;
- break;
- }
- }
- }
-
- if (matching)
- {
- Debug("pf::bv") << "Found a match with conflict #" << i << ": "
- << std::endl
- << possibleMatch << std::endl;
- // The rest is just a copy of the usual handling, if a precise match is
- // found. We only use the literals that appear in the matching conflict,
- // though, and not in the original lemma - as these may not have even
- // been bit blasted!
- std::ostringstream lemma_paren;
-
- if (possibleMatch.getKind() == kind::OR)
- {
- for (const Expr& lit : possibleMatch)
- {
- if (lit.getKind() == kind::NOT)
- {
- os << "(intro_assump_t _ _ _ ";
- }
- else
- {
- os << "(intro_assump_f _ _ _ ";
- }
- lemma_paren << ")";
- // print corresponding literal in main sat solver
- ProofManager* pm = ProofManager::currentPM();
- CnfProof* cnf = pm->getCnfProof();
- prop::SatLiteral main_lit = cnf->getLiteral(lit);
- os << pm->getLitName(main_lit);
- os << " ";
- // print corresponding literal in bv sat solver
- prop::SatVariable bb_var =
- d_cnfProof->getLiteral(lit).getSatVariable();
- os << pm->getAtomName(bb_var, "bb");
- os << "(\\ unit" << bb_var << "\n";
- lemma_paren << ")";
- }
- }
- else
- {
- // The conflict only consists of one node, either positive or
- // negative.
- Expr lit = possibleMatch;
- if (lit.getKind() == kind::NOT)
- {
- os << "(intro_assump_t _ _ _ ";
- }
- else
- {
- os << "(intro_assump_f _ _ _ ";
- }
- lemma_paren << ")";
- // print corresponding literal in main sat solver
- ProofManager* pm = ProofManager::currentPM();
- CnfProof* cnf = pm->getCnfProof();
- prop::SatLiteral main_lit = cnf->getLiteral(lit);
- os << pm->getLitName(main_lit);
- os << " ";
- // print corresponding literal in bv sat solver
- prop::SatVariable bb_var =
- d_cnfProof->getLiteral(lit).getSatVariable();
- os << pm->getAtomName(bb_var, "bb");
- os << "(\\ unit" << bb_var << "\n";
- lemma_paren << ")";
- }
-
- ClauseId lemma_id = it->second;
- proof::LFSCProofPrinter::printAssumptionsResolution(
- d_resolutionProof.get(), lemma_id, os, lemma_paren);
- os << lemma_paren.str();
-
- return;
- }
- }
-
- // We failed to find a matching sub conflict. The last hope is that the
- // conflict has a FALSE assertion in it; this can happen in some corner
- // cases, where the FALSE is the result of a rewrite.
-
- for (const Expr& lit : lemma)
- {
- if (lit.getKind() == kind::NOT && lit[0] == utils::mkFalse())
- {
- Debug("pf::bv") << "Lemma has a (not false) literal" << std::endl;
- os << "(clausify_false ";
- os << ProofManager::getLitName(lit);
- os << ")";
- return;
- }
- }
-
- Debug("pf::bv") << "Failed to find a matching sub-conflict..." << std::endl
- << "Dumping existing conflicts:" << std::endl;
-
- i = 0;
- for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it)
- {
- ++i;
- Debug("pf::bv") << "\tConflict #" << i << ": " << it->first << std::endl;
- }
-
- Unreachable();
- }
-}
-
-void LfscResolutionBitVectorProof::calculateAtomsInBitblastingProof()
-{
- // Collect the input clauses used
- IdToSatClause used_lemmas;
- IdToSatClause used_inputs;
- d_resolutionProof->collectClausesUsed(used_inputs, used_lemmas);
- d_cnfProof->collectAtomsForClauses(used_inputs, d_atomsInBitblastingProof);
- Assert(used_lemmas.empty());
-}
-
-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;
-
- std::set<Node>::iterator atomIt;
- Debug("pf::bv") << std::endl
- << "BV Dumping atoms from inputs: " << std::endl
- << std::endl;
- for (atomIt = d_atomsInBitblastingProof.begin();
- atomIt != d_atomsInBitblastingProof.end();
- ++atomIt)
- {
- Debug("pf::bv") << "\tAtom: " << *atomIt << std::endl;
- }
- Debug("pf::bv") << std::endl;
-
- // first print bit-blasting
- printBitblasting(os, paren);
-
- // print CNF conversion proof for bit-blasted facts
- IdToSatClause used_lemmas;
- IdToSatClause used_inputs;
- d_resolutionProof->collectClausesUsed(used_inputs, used_lemmas);
-
- d_cnfProof->printAtomMapping(d_atomsInBitblastingProof, os, paren, letMap);
- os << std::endl << ";; Bit-blasting definitional clauses \n" << std::endl;
- for (IdToSatClause::iterator it = used_inputs.begin();
- it != used_inputs.end();
- ++it)
- {
- d_cnfProof->printCnfProofForClause(it->first, it->second, os, paren);
- }
-
- os << std::endl << " ;; Bit-blasting learned clauses \n" << std::endl;
- proof::LFSCProofPrinter::printResolutions(d_resolutionProof.get(), os, paren);
-}
-
-void LfscResolutionBitVectorProof::printEmptyClauseProof(std::ostream& os,
- std::ostream& paren)
-{
- Assert(options::bitblastMode() == options::BitblastMode::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
deleted file mode 100644
index a1b0b0d59..000000000
--- a/src/proof/resolution_bitvector_proof.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/********************* */
-/*! \file resolution_bitvector_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Mathias Preiner, Liana Hadarean
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Bitvector proof
- **
- ** Bitvector proof
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__PROOF__RESOLUTION_BITVECTOR_PROOF_H
-#define CVC4__PROOF__RESOLUTION_BITVECTOR_PROOF_H
-
-#include <iosfwd>
-
-#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 {
-
-typedef TSatProof<CVC4::BVMinisat::Solver> BVSatProof;
-
-namespace proof {
-
-/**
- * Represents a bitvector proof which is backed by
- * (a) bitblasting and
- * (b) a resolution unsat proof.
- *
- * Contains tools for constructing BV conflicts
- */
-class ResolutionBitVectorProof : public BitVectorProof
-{
- public:
- ResolutionBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine);
-
- /**
- * Create an (internal) SAT proof object
- * Must be invoked before manipulating BV conflicts,
- * or initializing a BNF proof
- */
- void initSatProof(CVC4::BVMinisat::Solver* solver);
-
- BVSatProof* getSatProof();
-
- void finalizeConflicts(std::vector<Expr>& conflicts) override;
-
- void startBVConflict(CVC4::BVMinisat::Solver::TCRef cr);
- void startBVConflict(CVC4::BVMinisat::Solver::TLit lit);
- void endBVConflict(const BVMinisat::Solver::TLitVec& confl);
-
- void markAssumptionConflict() { d_isAssumptionConflict = true; }
- bool isAssumptionConflict() const { return d_isAssumptionConflict; }
-
- 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.
- // This is that proof.
- std::unique_ptr<BVSatProof> d_resolutionProof;
-
- bool d_isAssumptionConflict;
-
-};
-
-class LfscResolutionBitVectorProof : public ResolutionBitVectorProof
-{
- public:
- LfscResolutionBitVectorProof(theory::bv::TheoryBV* bv,
- TheoryProofEngine* proofEngine)
- : ResolutionBitVectorProof(bv, proofEngine)
- {
- }
- 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;
- void calculateAtomsInBitblastingProof() override;
-};
-
-} // namespace proof
-
-} // namespace CVC4
-
-#endif /* CVC4__PROOF__RESOLUTIONBITVECTORPROOF_H */
diff --git a/src/proof/sat_proof.h b/src/proof/sat_proof.h
index 83e4d3930..38aea0673 100644
--- a/src/proof/sat_proof.h
+++ b/src/proof/sat_proof.h
@@ -32,7 +32,6 @@
#include "expr/expr.h"
#include "proof/clause_id.h"
#include "proof/proof_manager.h"
-#include "util/proof.h"
#include "util/statistics_registry.h"
// Forward declarations.
diff --git a/src/proof/sat_proof_implementation.h b/src/proof/sat_proof_implementation.h
index 897a5c452..7ce18ae4a 100644
--- a/src/proof/sat_proof_implementation.h
+++ b/src/proof/sat_proof_implementation.h
@@ -20,10 +20,7 @@
#define CVC4__SAT__PROOF_IMPLEMENTATION_H
#include "proof/clause_id.h"
-#include "proof/cnf_proof.h"
#include "proof/sat_proof.h"
-#include "prop/bvminisat/bvminisat.h"
-#include "prop/bvminisat/core/Solver.h"
#include "prop/minisat/core/Solver.h"
#include "prop/minisat/minisat.h"
#include "prop/sat_solver_types.h"
@@ -712,11 +709,6 @@ void TSatProof<Solver>::registerResolution(ClauseId id, ResChain<Solver>* res) {
Assert(checkResolution(id));
}
- PSTATS(uint64_t resolutionSteps =
- static_cast<uint64_t>(res.getSteps().size());
- d_statistics.d_resChainLengths << resolutionSteps;
- d_statistics.d_avgChainLength.addEntry(resolutionSteps);
- ++(d_statistics.d_numLearnedClauses);)
}
/// recording resolutions
@@ -912,14 +904,6 @@ void TSatProof<Solver>::markDeleted(typename Solver::TCRef clause) {
}
}
-// template<>
-// void toSatClause< ::BVMinisat::Solver> (const BVMinisat::Solver::TClause&
-// minisat_cl,
-// prop::SatClause& sat_cl) {
-
-// prop::BVMinisatSatSolver::toSatClause(minisat_cl, sat_cl);
-// }
-
template <class Solver>
void TSatProof<Solver>::constructProof(ClauseId conflict) {
d_satProofConstructed = true;
@@ -1002,9 +986,6 @@ void TSatProof<Solver>::collectClauses(ClauseId id) {
const ResolutionChain& res = getResolutionChain(id);
const typename ResolutionChain::ResSteps& steps = res.getSteps();
- PSTATS(d_statistics.d_usedResChainLengths
- << ((uint64_t)steps.size());
- d_statistics.d_usedClauseGlue << ((uint64_t)d_glueMap[id]););
ClauseId start = res.getStart();
collectClauses(start);
@@ -1018,8 +999,6 @@ void TSatProof<Solver>::collectClausesUsed(IdToSatClause& inputs,
IdToSatClause& lemmas) {
inputs = d_seenInputs;
lemmas = d_seenLemmas;
- PSTATS(d_statistics.d_numLearnedInProof.setData(d_seenLearnt.size());
- d_statistics.d_numLemmasInProof.setData(d_seenLemmas.size()););
}
template <class Solver>
diff --git a/src/proof/simplify_boolean_node.cpp b/src/proof/simplify_boolean_node.cpp
deleted file mode 100644
index 5f1943654..000000000
--- a/src/proof/simplify_boolean_node.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/********************* */
-/*! \file simplify_boolean_node.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Liana Hadarean, Andrew Reynolds
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Simplifying a boolean node, needed for constructing LFSC proofs.
- **
- **/
-
-#include "cvc4_private.h"
-
-#include "proof_manager.h"
-
-namespace CVC4 {
-
-inline static Node eqNode(TNode n1, TNode n2) {
- return NodeManager::currentNM()->mkNode(kind::EQUAL, n1, n2);
-}
-
-Node simplifyBooleanNode(const Node &n) {
- if (n.isNull())
- return n;
-
- // Only simplify boolean nodes
- if (!n.getType().isBoolean())
- return n;
-
- // Sometimes we get sent intermediate nodes that we shouldn't simplify.
- // If a node doesn't have a literal, it's clearly intermediate - ignore.
- if (!ProofManager::hasLitName(n))
- return n;
-
- // If we already simplified the node, ignore.
- if (ProofManager::currentPM()->haveRewriteFilter(n.negate()))
- return n;
-
-
- std::string litName = ProofManager::getLitName(n.negate());
- Node falseNode = NodeManager::currentNM()->mkConst(false);
- Node trueNode = NodeManager::currentNM()->mkConst(true);
- Node simplified = n;
-
- // (not (= false b)), (not (= true b)))
- if ((n.getKind() == kind::NOT) && (n[0].getKind() == kind::EQUAL) &&
- (n[0][0].getKind() == kind::BOOLEAN_TERM_VARIABLE || n[0][1].getKind() == kind::BOOLEAN_TERM_VARIABLE)) {
- Node lhs = n[0][0];
- Node rhs = n[0][1];
-
- if (lhs == falseNode) {
- Assert(rhs != falseNode);
- Assert(rhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (not (= false b)) --> true = b
-
- simplified = eqNode(trueNode, rhs);
-
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_not_iff_f _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if (rhs == falseNode) {
- Assert(lhs != falseNode);
- Assert(lhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (not (= b false)) --> b = true
-
- simplified = eqNode(lhs, trueNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_not_iff_f_2 _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if (lhs == trueNode) {
- Assert(rhs != trueNode);
- Assert(rhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (not (= true b)) --> b = false
-
- simplified = eqNode(falseNode, rhs);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_not_iff_t _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if (rhs == trueNode) {
- Assert(lhs != trueNode);
- Assert(lhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (not (= b true)) --> b = false
-
- simplified = eqNode(lhs, falseNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_not_iff_t_2 _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
- }
-
- } else if ((n.getKind() == kind::EQUAL) &&
- (n[0].getKind() == kind::BOOLEAN_TERM_VARIABLE || n[1].getKind() == kind::BOOLEAN_TERM_VARIABLE)) {
- Node lhs = n[0];
- Node rhs = n[1];
-
- if (lhs == falseNode) {
- Assert(rhs != falseNode);
- Assert(rhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (= false b)
-
- std::stringstream newLitName;
- newLitName << "(pred_iff_f _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(litName, newLitName.str());
-
- } else if (rhs == falseNode) {
- Assert(lhs != falseNode);
- Assert(lhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (= b false))
-
- std::stringstream newLitName;
- newLitName << "(pred_iff_f_2 _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(litName, newLitName.str());
-
- } else if (lhs == trueNode) {
- Assert(rhs != trueNode);
- Assert(rhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (= true b)
-
- std::stringstream newLitName;
- newLitName << "(pred_iff_t _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(litName, newLitName.str());
-
- } else if (rhs == trueNode) {
- Assert(lhs != trueNode);
- Assert(lhs.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- // (= b true)
-
-
- std::stringstream newLitName;
- newLitName << "(pred_iff_t_2 _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(litName, newLitName.str());
- }
-
- } else if ((n.getKind() == kind::NOT) && (n[0].getKind() == kind::BOOLEAN_TERM_VARIABLE)) {
- // (not b) --> b = false
- simplified = eqNode(n[0], falseNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_eq_f _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if (n.getKind() == kind::BOOLEAN_TERM_VARIABLE) {
- // (b) --> b = true
- simplified = eqNode(n, trueNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_eq_t _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if ((n.getKind() == kind::NOT) && (n[0].getKind() == kind::SELECT)) {
- // not(a[x]) --> a[x] = false
- simplified = eqNode(n[0], falseNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_eq_f _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
-
- } else if (n.getKind() == kind::SELECT) {
- // a[x] --> a[x] = true
- simplified = eqNode(n, trueNode);
- std::string simplifiedLitName = ProofManager::getLitName(simplified.negate());
- std::stringstream newLitName;
- newLitName << "(pred_eq_t _ " << litName << ")";
- ProofManager::currentPM()->addRewriteFilter(simplifiedLitName, newLitName.str());
- }
-
- if (simplified != n)
- Debug("pf::simplify") << "simplifyBooleanNode: " << n << " --> " << simplified << std::endl;
-
- return simplified;
-}
-
-}/* CVC4 namespace */
diff --git a/src/proof/skolemization_manager.cpp b/src/proof/skolemization_manager.cpp
deleted file mode 100644
index 1bb14598d..000000000
--- a/src/proof/skolemization_manager.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/********************* */
-/*! \file skolemization_manager.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Paul Meng, Tim King, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
- **/
-
-#include "proof/skolemization_manager.h"
-
-namespace CVC4 {
-
-void SkolemizationManager::registerSkolem(Node disequality, Node skolem) {
- Debug("pf::pm") << "SkolemizationManager: registerSkolem: disequality = " << disequality << ", skolem = " << skolem << std::endl;
-
- if (isSkolem(skolem)) {
- Assert(d_skolemToDisequality[skolem] == disequality);
- return;
- }
-
- d_disequalityToSkolem[disequality] = skolem;
- d_skolemToDisequality[skolem] = disequality;
-}
-
-bool SkolemizationManager::hasSkolem(Node disequality) {
- return (d_disequalityToSkolem.find(disequality) != d_disequalityToSkolem.end());
-}
-
-Node SkolemizationManager::getSkolem(Node disequality) {
- Debug("pf::pm") << "SkolemizationManager: getSkolem( ";
- Assert(d_disequalityToSkolem.find(disequality)
- != d_disequalityToSkolem.end());
- Debug("pf::pm") << disequality << " ) = " << d_disequalityToSkolem[disequality] << std::endl;
- return d_disequalityToSkolem[disequality];
-}
-
-Node SkolemizationManager::getDisequality(Node skolem) {
- Assert(d_skolemToDisequality.find(skolem) != d_skolemToDisequality.end());
- return d_skolemToDisequality[skolem];
-}
-
-bool SkolemizationManager::isSkolem(Node skolem) {
- return (d_skolemToDisequality.find(skolem) != d_skolemToDisequality.end());
-}
-
-void SkolemizationManager::clear() {
- Debug("pf::pm") << "SkolemizationManager: clear" << std::endl;
- d_disequalityToSkolem.clear();
- d_skolemToDisequality.clear();
-}
-
-std::unordered_map<Node, Node, NodeHashFunction>::const_iterator SkolemizationManager::begin() {
- return d_disequalityToSkolem.begin();
-}
-
-std::unordered_map<Node, Node, NodeHashFunction>::const_iterator SkolemizationManager::end() {
- return d_disequalityToSkolem.end();
-}
-
-} /* CVC4 namespace */
diff --git a/src/proof/skolemization_manager.h b/src/proof/skolemization_manager.h
deleted file mode 100644
index a2c61db4d..000000000
--- a/src/proof/skolemization_manager.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/********************* */
-/*! \file skolemization_manager.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Tim King, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__SKOLEMIZATION_MANAGER_H
-#define CVC4__SKOLEMIZATION_MANAGER_H
-
-#include <iostream>
-#include <unordered_map>
-
-#include "proof/proof.h"
-#include "util/proof.h"
-#include "expr/node.h"
-#include "theory/logic_info.h"
-#include "theory/substitutions.h"
-
-namespace CVC4 {
-
-class SkolemizationManager {
-public:
- void registerSkolem(Node disequality, Node skolem);
- bool hasSkolem(Node disequality);
- Node getSkolem(Node disequality);
- Node getDisequality(Node skolem);
- bool isSkolem(Node skolem);
- void clear();
-
- std::unordered_map<Node, Node, NodeHashFunction>::const_iterator begin();
- std::unordered_map<Node, Node, NodeHashFunction>::const_iterator end();
-
-private:
- std::unordered_map<Node, Node, NodeHashFunction> d_disequalityToSkolem;
- std::unordered_map<Node, Node, NodeHashFunction> d_skolemToDisequality;
-};
-
-}/* CVC4 namespace */
-
-
-
-#endif /* CVC4__SKOLEMIZATION_MANAGER_H */
diff --git a/src/proof/theory_proof.cpp b/src/proof/theory_proof.cpp
deleted file mode 100644
index b47fd6a1e..000000000
--- a/src/proof/theory_proof.cpp
+++ /dev/null
@@ -1,1756 +0,0 @@
-/********************* */
-/*! \file theory_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Liana Hadarean, Yoni Zohar
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief [[ Add one-line brief description here ]]
- **
- ** [[ Add lengthier description here ]]
- ** \todo document this file
- **/
-#include "proof/theory_proof.h"
-
-#include "base/check.h"
-#include "context/context.h"
-#include "expr/node_visitor.h"
-#include "options/bv_options.h"
-#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"
-#include "proof/proof_output_channel.h"
-#include "proof/proof_utils.h"
-#include "proof/resolution_bitvector_proof.h"
-#include "proof/sat_proof.h"
-#include "proof/simplify_boolean_node.h"
-#include "proof/uf_proof.h"
-#include "prop/sat_solver_types.h"
-#include "smt/smt_engine.h"
-#include "smt/smt_engine_scope.h"
-#include "theory/arrays/theory_arrays.h"
-#include "theory/bv/theory_bv.h"
-#include "theory/output_channel.h"
-#include "theory/term_registration_visitor.h"
-#include "theory/uf/theory_uf.h"
-#include "theory/valuation.h"
-#include "util/hash.h"
-#include "util/proof.h"
-
-namespace CVC4 {
-
-using proof::LfscResolutionBitVectorProof;
-using proof::ResolutionBitVectorProof;
-
-unsigned CVC4::ProofLetCount::counter = 0;
-static unsigned LET_COUNT = 1;
-
-TheoryProofEngine::TheoryProofEngine()
- : d_registrationCache()
- , d_theoryProofTable()
-{
- d_theoryProofTable[theory::THEORY_BOOL] = new LFSCBooleanProof(this);
-}
-
-TheoryProofEngine::~TheoryProofEngine() {
- TheoryProofTable::iterator it = d_theoryProofTable.begin();
- TheoryProofTable::iterator end = d_theoryProofTable.end();
- for (; it != end; ++it) {
- delete it->second;
- }
-}
-
-void TheoryProofEngine::registerTheory(theory::Theory* th) {
- if (th) {
- theory::TheoryId id = th->getId();
- if(d_theoryProofTable.find(id) == d_theoryProofTable.end()) {
-
- Trace("pf::tp") << "TheoryProofEngine::registerTheory: " << id << std::endl;
-
- if (id == theory::THEORY_UF) {
- d_theoryProofTable[id] = new LFSCUFProof((theory::uf::TheoryUF*)th, this);
- return;
- }
-
- if (id == theory::THEORY_BV) {
- auto thBv = static_cast<theory::bv::TheoryBV*>(th);
- if (options::bitblastMode() == options::BitblastMode::EAGER
- && options::bvSatSolver() == options::SatSolverMode::CRYPTOMINISAT)
- {
- proof::BitVectorProof* bvp = nullptr;
- switch (options::bvProofFormat())
- {
- case options::BvProofFormat::DRAT:
- {
- bvp = new proof::LfscDratBitVectorProof(thBv, this);
- break;
- }
- case options::BvProofFormat::LRAT:
- {
- bvp = new proof::LfscLratBitVectorProof(thBv, this);
- break;
- }
- case options::BvProofFormat::ER:
- {
- bvp = new proof::LfscErBitVectorProof(thBv, this);
- break;
- }
- default:
- {
- Unreachable() << "Invalid BvProofFormat";
- }
- };
- d_theoryProofTable[id] = bvp;
- }
- else
- {
- proof::BitVectorProof* bvp =
- new proof::LfscResolutionBitVectorProof(thBv, this);
- d_theoryProofTable[id] = bvp;
- }
- return;
- }
-
- if (id == theory::THEORY_ARRAYS) {
- d_theoryProofTable[id] = new LFSCArrayProof((theory::arrays::TheoryArrays*)th, this);
- return;
- }
-
- if (id == theory::THEORY_ARITH) {
- d_theoryProofTable[id] = new LFSCArithProof((theory::arith::TheoryArith*)th, this);
- return;
- }
-
- // TODO other theories
- }
- }
-}
-
-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());
- proof::BitVectorProof* bvp =
- static_cast<proof::BitVectorProof*>(d_theoryProofTable[id]);
- bv_th->setProofLog(bvp);
- return;
- }
- }
-}
-
-TheoryProof* TheoryProofEngine::getTheoryProof(theory::TheoryId id) {
- // The UF theory handles queries for the Builtin theory.
- if (id == theory::THEORY_BUILTIN) {
- Debug("pf::tp") << "TheoryProofEngine::getTheoryProof: BUILTIN --> UF" << std::endl;
- id = theory::THEORY_UF;
- }
-
- if (d_theoryProofTable.find(id) == d_theoryProofTable.end()) {
- InternalError()
- << "Error! Proofs not yet supported for the following theory: " << id
- << std::endl;
- }
-
- return d_theoryProofTable[id];
-}
-
-void TheoryProofEngine::markTermForFutureRegistration(Expr term, theory::TheoryId id) {
- d_exprToTheoryIds[term].insert(id);
-}
-
-void TheoryProofEngine::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap) {
- Assert(c1.isConst());
- Assert(c2.isConst());
-
- Assert(theory::Theory::theoryOf(c1) == theory::Theory::theoryOf(c2));
- getTheoryProof(theory::Theory::theoryOf(c1))->printConstantDisequalityProof(os, c1, c2, globalLetMap);
-}
-
-void TheoryProofEngine::printTheoryTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- this->printTheoryTermAsType(term, os, map, expectedType);
-}
-
-TypeNode TheoryProofEngine::equalityType(const Expr& left, const Expr& right)
-{
- // Ask the two theories what they think..
- TypeNode leftType = getTheoryProof(theory::Theory::theoryOf(left))->equalityType(left, right);
- TypeNode rightType = getTheoryProof(theory::Theory::theoryOf(right))->equalityType(left, right);
-
- // Error if the disagree.
- Assert(leftType.isNull() || rightType.isNull() || leftType == rightType)
- << "TheoryProofEngine::equalityType(" << left << ", " << right << "):" << std::endl
- << "theories disagree about the type of an equality:" << std::endl
- << "\tleft: " << leftType << std::endl
- << "\tright:" << rightType;
-
- return leftType.isNull() ? rightType : leftType;
-}
-
-void TheoryProofEngine::registerTerm(Expr term) {
- Debug("pf::tp::register") << "TheoryProofEngine::registerTerm: registering term: " << term << std::endl;
-
- if (d_registrationCache.count(term)) {
- return;
- }
-
- Debug("pf::tp::register") << "TheoryProofEngine::registerTerm: registering NEW term: " << term << std::endl;
-
- theory::TheoryId theory_id = theory::Theory::theoryOf(term);
-
- Debug("pf::tp::register") << "Term's theory( " << term << " ) = " << theory_id << std::endl;
-
- // don't need to register boolean terms
- if (theory_id == theory::THEORY_BUILTIN ||
- term.getKind() == kind::ITE) {
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- registerTerm(term[i]);
- }
- d_registrationCache.insert(term);
- return;
- }
-
- if (!supportedTheory(theory_id)) return;
-
- // Register the term with its owner theory
- getTheoryProof(theory_id)->registerTerm(term);
-
- // A special case: the array theory needs to know of every skolem, even if
- // it belongs to another theory (e.g., a BV skolem)
- if (ProofManager::getSkolemizationManager()->isSkolem(term) && theory_id != theory::THEORY_ARRAYS) {
- Debug("pf::tp::register") << "TheoryProofEngine::registerTerm: registering a non-array skolem: " << term << std::endl;
- getTheoryProof(theory::THEORY_ARRAYS)->registerTerm(term);
- }
-
- d_registrationCache.insert(term);
-}
-
-theory::TheoryId TheoryProofEngine::getTheoryForLemma(const prop::SatClause* clause) {
- ProofManager* pm = ProofManager::currentPM();
-
- std::set<Node> nodes;
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = pm->getCnfProof()->getAtom(lit.getSatVariable());
- Expr atom = node.toExpr();
- if (atom.isConst()) {
- Assert(atom == utils::mkTrue());
- continue;
- }
-
- nodes.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- // Ensure that the lemma is in the database.
- Assert(pm->getCnfProof()->haveProofRecipe(nodes));
- return pm->getCnfProof()->getProofRecipe(nodes).getTheory();
-}
-
-void LFSCTheoryProofEngine::bind(Expr term, ProofLetMap& map, Bindings& let_order) {
- ProofLetMap::iterator it = map.find(term);
- if (it != map.end()) {
- ProofLetCount& count = it->second;
- count.increment();
- return;
- }
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- bind(term[i], map, let_order);
- }
- unsigned new_id = ProofLetCount::newId();
- map[term] = ProofLetCount(new_id);
- let_order.push_back(LetOrderElement(term, new_id));
-}
-
-void LFSCTheoryProofEngine::printLetTerm(Expr term, std::ostream& os) {
- ProofLetMap map;
- Bindings let_order;
- bind(term, map, let_order);
- std::ostringstream paren;
- for (unsigned i = 0; i < let_order.size(); ++i) {
- Expr current_expr = let_order[i].expr;
- unsigned let_id = let_order[i].id;
- ProofLetMap::const_iterator it = map.find(current_expr);
- Assert(it != map.end());
- unsigned let_count = it->second.count;
- Assert(let_count);
- // skip terms that only appear once
- if (let_count <= LET_COUNT) {
- continue;
- }
-
- os << "(@ let" <<let_id << " ";
- printTheoryTerm(current_expr, os, map);
- paren <<")";
- }
- unsigned last_let_id = let_order.back().id;
- Expr last = let_order.back().expr;
- unsigned last_count = map.find(last)->second.count;
- if (last_count <= LET_COUNT) {
- printTheoryTerm(last, os, map);
- }
- else {
- os << " let" << last_let_id;
- }
- os << paren.str();
-}
-
-void LFSCTheoryProofEngine::printTheoryTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- theory::TheoryId theory_id = theory::Theory::theoryOf(term);
-
- // boolean terms and ITEs are special because they
- // are common to all theories
- if (theory_id == theory::THEORY_BUILTIN ||
- term.getKind() == kind::ITE ||
- term.getKind() == kind::EQUAL) {
- printCoreTerm(term, os, map, expectedType);
- return;
- }
- // dispatch to proper theory
- getTheoryProof(theory_id)->printOwnedTerm(term, os, map, expectedType);
-}
-
-void LFSCTheoryProofEngine::printSort(Type type, std::ostream& os) {
- if (type.isSort()) {
- getTheoryProof(theory::THEORY_UF)->printOwnedSort(type, os);
- return;
- }
- if (type.isBitVector()) {
- getTheoryProof(theory::THEORY_BV)->printOwnedSort(type, os);
- return;
- }
-
- if (type.isArray()) {
- getTheoryProof(theory::THEORY_ARRAYS)->printOwnedSort(type, os);
- return;
- }
-
- if (type.isInteger() || type.isReal()) {
- getTheoryProof(theory::THEORY_ARITH)->printOwnedSort(type, os);
- return;
- }
-
- if (type.isBoolean()) {
- getTheoryProof(theory::THEORY_BOOL)->printOwnedSort(type, os);
- return;
- }
-
- Unreachable();
-}
-
-void LFSCTheoryProofEngine::performExtraRegistrations() {
- ExprToTheoryIds::const_iterator it;
- for (it = d_exprToTheoryIds.begin(); it != d_exprToTheoryIds.end(); ++it) {
- if (d_registrationCache.count(it->first)) { // Only register if the term appeared
- TheoryIdSet::const_iterator theoryIt;
- for (theoryIt = it->second.begin(); theoryIt != it->second.end(); ++theoryIt) {
- Debug("pf::tp") << "\tExtra registration of term " << it->first
- << " with theory: " << *theoryIt << std::endl;
- Assert(supportedTheory(*theoryIt));
- getTheoryProof(*theoryIt)->registerTerm(it->first);
- }
- }
- }
-}
-
-void LFSCTheoryProofEngine::registerTermsFromAssertions() {
- ProofManager::assertions_iterator it = ProofManager::currentPM()->begin_assertions();
- ProofManager::assertions_iterator end = ProofManager::currentPM()->end_assertions();
-
- for(; it != end; ++it) {
- registerTerm(*it);
- }
-
- performExtraRegistrations();
-}
-
-void LFSCTheoryProofEngine::printAssertions(std::ostream& os, std::ostream& paren) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printAssertions called" << std::endl << std::endl;
-
- ProofManager::assertions_iterator it = ProofManager::currentPM()->begin_assertions();
- ProofManager::assertions_iterator end = ProofManager::currentPM()->end_assertions();
-
- for (; it != end; ++it) {
- Debug("pf::tp") << "printAssertions: assertion is: " << *it << std::endl;
- os << "(% " << ProofManager::currentPM()->getInputFormulaName(*it) << " (th_holds ";
-
- // Assertions appear before the global let map, so we use a dummpMap to avoid letification here.
- ProofLetMap dummyMap;
-
- bool convertFromBool = (it->getType().isBoolean() && printsAsBool(*it));
- if (convertFromBool) os << "(p_app ";
- printBoundTerm(*it, os, dummyMap);
- if (convertFromBool) os << ")";
-
- os << ")\n";
- paren << ")";
- }
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printAssertions done" << std::endl << std::endl;
-}
-
-void LFSCTheoryProofEngine::printLemmaRewrites(NodePairSet& rewrites,
- std::ostream& os,
- std::ostream& paren) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printLemmaRewrites called" << std::endl << std::endl;
-
- NodePairSet::const_iterator it;
-
- for (it = rewrites.begin(); it != rewrites.end(); ++it) {
- Debug("pf::tp") << "printLemmaRewrites: " << it->first << " --> " << it->second << std::endl;
-
- Node n1 = it->first;
- Node n2 = it->second;
- Assert(n1.toExpr() == utils::mkFalse()
- || theory::Theory::theoryOf(n1) == theory::Theory::theoryOf(n2));
-
- std::ostringstream rewriteRule;
- rewriteRule << ".lrr" << d_assertionToRewrite.size();
-
- os << "(th_let_pf _ ";
- getTheoryProof(theory::Theory::theoryOf(n1))->printRewriteProof(os, n1, n2);
- os << "(\\ " << rewriteRule.str() << "\n";
-
- d_assertionToRewrite[it->first] = rewriteRule.str();
- Debug("pf::tp") << "d_assertionToRewrite[" << it->first << "] = " << rewriteRule.str() << std::endl;
- paren << "))";
- }
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printLemmaRewrites done" << std::endl << std::endl;
-}
-
-void LFSCTheoryProofEngine::printSortDeclarations(std::ostream& os, std::ostream& paren) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printSortDeclarations called" << std::endl << std::endl;
-
- TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
- TheoryProofTable::const_iterator end = d_theoryProofTable.end();
- for (; it != end; ++it) {
- it->second->printSortDeclarations(os, paren);
- }
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printSortDeclarations done" << std::endl << std::endl;
-}
-
-void LFSCTheoryProofEngine::printTermDeclarations(std::ostream& os, std::ostream& paren) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTermDeclarations called" << std::endl << std::endl;
-
- TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
- TheoryProofTable::const_iterator end = d_theoryProofTable.end();
- for (; it != end; ++it) {
- it->second->printTermDeclarations(os, paren);
- }
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTermDeclarations done" << std::endl << std::endl;
-}
-
-void LFSCTheoryProofEngine::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printDeferredDeclarations called" << std::endl;
-
- TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
- TheoryProofTable::const_iterator end = d_theoryProofTable.end();
- for (; it != end; ++it) {
- it->second->printDeferredDeclarations(os, paren);
- }
-}
-
-void LFSCTheoryProofEngine::printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printAliasingDeclarations called" << std::endl;
-
- TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
- TheoryProofTable::const_iterator end = d_theoryProofTable.end();
- for (; it != end; ++it) {
- it->second->printAliasingDeclarations(os, paren, globalLetMap);
- }
-}
-
-void LFSCTheoryProofEngine::dumpTheoryLemmas(const IdToSatClause& lemmas) {
- Debug("pf::dumpLemmas") << "Dumping ALL theory lemmas" << std::endl << std::endl;
-
- ProofManager* pm = ProofManager::currentPM();
- for (IdToSatClause::const_iterator it = lemmas.begin(); it != lemmas.end(); ++it) {
- ClauseId id = it->first;
- Debug("pf::dumpLemmas") << "**** \tLemma ID = " << id << std::endl;
- const prop::SatClause* clause = it->second;
- std::set<Node> nodes;
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = pm->getCnfProof()->getAtom(lit.getSatVariable());
- if (node.isConst()) {
- Assert(node.toExpr() == utils::mkTrue());
- continue;
- }
- nodes.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- LemmaProofRecipe recipe = pm->getCnfProof()->getProofRecipe(nodes);
- recipe.dump("pf::dumpLemmas");
- }
-
- Debug("pf::dumpLemmas") << "Theory lemma printing DONE" << std::endl << std::endl;
-}
-
-// TODO: this function should be moved into the BV prover.
-void LFSCTheoryProofEngine::finalizeBvConflicts(const IdToSatClause& lemmas, std::ostream& os) {
- // BitVector theory is special case: must know all conflicts needed
- // ahead of time for resolution proof lemmas
- std::vector<Expr> bv_lemmas;
-
- for (IdToSatClause::const_iterator it = lemmas.begin(); it != lemmas.end(); ++it) {
- const prop::SatClause* clause = it->second;
-
- std::vector<Expr> conflict;
- std::set<Node> conflictNodes;
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = ProofManager::currentPM()->getCnfProof()->getAtom(lit.getSatVariable());
- Expr atom = node.toExpr();
-
- // The literals (true) and (not false) are omitted from conflicts
- if (atom.isConst()) {
- Assert(atom == utils::mkTrue()
- || (atom == utils::mkFalse() && lit.isNegated()));
- continue;
- }
-
- Expr expr_lit = lit.isNegated() ? atom.notExpr() : atom;
- conflict.push_back(expr_lit);
- conflictNodes.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- LemmaProofRecipe recipe = ProofManager::currentPM()->getCnfProof()->getProofRecipe(conflictNodes);
-
- unsigned numberOfSteps = recipe.getNumSteps();
-
- prop::SatClause currentClause = *clause;
- std::vector<Expr> currentClauseExpr = conflict;
-
- for (unsigned i = 0; i < numberOfSteps; ++i) {
- const LemmaProofRecipe::ProofStep* currentStep = recipe.getStep(i);
-
- if (currentStep->getTheory() != theory::THEORY_BV) {
- continue;
- }
-
- // If any rewrites took place, we need to update the conflict clause accordingly
- std::set<Node> missingAssertions = recipe.getMissingAssertionsForStep(i);
- std::map<Node, Node> explanationToMissingAssertion;
- std::set<Node>::iterator assertionIt;
- for (assertionIt = missingAssertions.begin();
- assertionIt != missingAssertions.end();
- ++assertionIt) {
- Node negated = (*assertionIt).negate();
- explanationToMissingAssertion[recipe.getExplanation(negated)] = negated;
- }
-
- currentClause = *clause;
- currentClauseExpr = conflict;
-
- for (unsigned j = 0; j < i; ++j) {
- // Literals already used in previous steps need to be negated
- Node previousLiteralNode = recipe.getStep(j)->getLiteral();
-
- // If this literal is the result of a rewrite, we need to translate it
- if (explanationToMissingAssertion.find(previousLiteralNode) !=
- explanationToMissingAssertion.end()) {
- previousLiteralNode = explanationToMissingAssertion[previousLiteralNode];
- }
-
- Node previousLiteralNodeNegated = previousLiteralNode.negate();
- prop::SatLiteral previousLiteralNegated =
- ProofManager::currentPM()->getCnfProof()->getLiteral(previousLiteralNodeNegated);
-
- currentClause.push_back(previousLiteralNegated);
- currentClauseExpr.push_back(previousLiteralNodeNegated.toExpr());
- }
-
- // If we're in the final step, the last literal is Null and should not be added.
- // Otherwise, the current literal does NOT need to be negated
- Node currentLiteralNode = currentStep->getLiteral();
-
- if (currentLiteralNode != Node()) {
- prop::SatLiteral currentLiteral =
- ProofManager::currentPM()->getCnfProof()->getLiteral(currentLiteralNode);
-
- currentClause.push_back(currentLiteral);
- currentClauseExpr.push_back(currentLiteralNode.toExpr());
- }
-
- bv_lemmas.push_back(utils::mkSortedExpr(kind::OR, currentClauseExpr));
- }
- }
-
- proof::BitVectorProof* bv = ProofManager::getBitVectorProof();
- bv->finalizeConflicts(bv_lemmas);
-}
-
-void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap& map) {
- os << " ;; Theory Lemmas \n";
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: starting" << std::endl;
-
- if (Debug.isOn("pf::dumpLemmas")) {
- dumpTheoryLemmas(lemmas);
- }
-
- // finalizeBvConflicts(lemmas, os, paren, map);
- ProofManager::getBitVectorProof()->printBBDeclarationAndCnf(os, paren, map);
-
- if (options::bitblastMode() == options::BitblastMode::EAGER)
- {
- Assert(lemmas.size() == 1);
- // nothing more to do (no combination with eager so far)
- return;
- }
-
- ProofManager* pm = ProofManager::currentPM();
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing lemmas..." << std::endl;
-
- for (IdToSatClause::const_iterator it = lemmas.begin(); it != lemmas.end(); ++it) {
- ClauseId id = it->first;
- const prop::SatClause* clause = it->second;
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing lemma. ID = "
- << id << std::endl;
-
- std::vector<Expr> clause_expr;
- std::set<Node> clause_expr_nodes;
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- Node node = pm->getCnfProof()->getAtom(lit.getSatVariable());
- Expr atom = node.toExpr();
- if (atom.isConst()) {
- Assert(atom == utils::mkTrue());
- continue;
- }
- Expr expr_lit = lit.isNegated() ? atom.notExpr(): atom;
- clause_expr.push_back(expr_lit);
- clause_expr_nodes.insert(lit.isNegated() ? node.notNode() : node);
- }
-
- LemmaProofRecipe recipe = pm->getCnfProof()->getProofRecipe(clause_expr_nodes);
-
- if (recipe.simpleLemma()) {
- // In a simple lemma, there will be no propositional resolution in the end
-
- Debug("pf::tp") << "Simple lemma" << std::endl;
- // Printing the clause as it appears in resolution proof
- os << "(satlem _ _ ";
- std::ostringstream clause_paren;
- pm->getCnfProof()->printClause(*clause, os, clause_paren);
-
- // Find and handle missing assertions, due to rewrites
- std::set<Node> missingAssertions = recipe.getMissingAssertionsForStep(0);
- if (!missingAssertions.empty()) {
- Debug("pf::tp") << "Have missing assertions for this simple lemma!" << std::endl;
- }
-
- std::set<Node>::const_iterator missingAssertion;
- for (missingAssertion = missingAssertions.begin();
- missingAssertion != missingAssertions.end();
- ++missingAssertion) {
-
- Debug("pf::tp") << "Working on missing assertion: " << *missingAssertion << std::endl;
- Assert(recipe.wasRewritten(missingAssertion->negate()));
- Node explanation = recipe.getExplanation(missingAssertion->negate()).negate();
- Debug("pf::tp") << "Found explanation: " << explanation << std::endl;
-
- // We have a missing assertion.
- // rewriteIt->first is the assertion after the rewrite (the explanation),
- // rewriteIt->second is the original assertion that needs to be fed into the theory.
-
- bool found = false;
- unsigned k;
- for (k = 0; k < clause_expr.size(); ++k) {
- if (clause_expr[k] == explanation.toExpr()) {
- found = true;
- break;
- }
- }
-
- AlwaysAssert(found);
- Debug("pf::tp") << "Replacing theory assertion "
- << clause_expr[k]
- << " with "
- << *missingAssertion
- << std::endl;
-
- clause_expr[k] = missingAssertion->toExpr();
-
- std::ostringstream rewritten;
-
- if (missingAssertion->getKind() == kind::NOT && (*missingAssertion)[0].toExpr() == utils::mkFalse()) {
- rewritten << "(or_elim_2 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << pm->getLitName(explanation);
- rewritten << ") (iff_elim_2 _ _ ";
- rewritten << d_assertionToRewrite[missingAssertion->negate()];
- rewritten << "))";
- }
- else {
- rewritten << "(or_elim_1 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << pm->getLitName(explanation);
- rewritten << ") (iff_elim_1 _ _ ";
- rewritten << d_assertionToRewrite[missingAssertion->negate()];
- rewritten << "))";
- }
-
- Debug("pf::tp") << "Setting a rewrite filter for this proof: " << std::endl
- << pm->getLitName(*missingAssertion) << " --> " << rewritten.str()
- << ", explanation = " << explanation
- << std::endl << std::endl;
-
- pm->addRewriteFilter(pm->getLitName(*missingAssertion), rewritten.str());
- }
-
- // Query the appropriate theory for a proof of this clause
- theory::TheoryId theory_id = getTheoryForLemma(clause);
- Debug("pf::tp") << "Get theory lemma from " << theory_id << "..." << std::endl;
- getTheoryProof(theory_id)->printTheoryLemmaProof(clause_expr, os, paren, map);
-
- // Turn rewrite filter OFF
- pm->clearRewriteFilters();
-
- Debug("pf::tp") << "Get theory lemma from " << theory_id << "... DONE!" << std::endl;
- os << clause_paren.str();
- os << "( \\ " << pm->getLemmaClauseName(id) <<"\n";
- paren << "))";
- } else { // This is a composite lemma
-
- unsigned numberOfSteps = recipe.getNumSteps();
- prop::SatClause currentClause = *clause;
- std::vector<Expr> currentClauseExpr = clause_expr;
-
- for (unsigned i = 0; i < numberOfSteps; ++i) {
- const LemmaProofRecipe::ProofStep* currentStep = recipe.getStep(i);
-
- currentClause = *clause;
- currentClauseExpr = clause_expr;
-
- for (unsigned j = 0; j < i; ++j) {
- // Literals already used in previous steps need to be negated
- Node previousLiteralNode = recipe.getStep(j)->getLiteral();
- Node previousLiteralNodeNegated = previousLiteralNode.negate();
- prop::SatLiteral previousLiteralNegated =
- ProofManager::currentPM()->getCnfProof()->getLiteral(previousLiteralNodeNegated);
- currentClause.push_back(previousLiteralNegated);
- currentClauseExpr.push_back(previousLiteralNodeNegated.toExpr());
- }
-
- // If the current literal is NULL, can ignore (final step)
- // Otherwise, the current literal does NOT need to be negated
- Node currentLiteralNode = currentStep->getLiteral();
- if (currentLiteralNode != Node()) {
- prop::SatLiteral currentLiteral =
- ProofManager::currentPM()->getCnfProof()->getLiteral(currentLiteralNode);
-
- currentClause.push_back(currentLiteral);
- currentClauseExpr.push_back(currentLiteralNode.toExpr());
- }
-
- os << "(satlem _ _ ";
- std::ostringstream clause_paren;
-
- pm->getCnfProof()->printClause(currentClause, os, clause_paren);
-
- // query appropriate theory for proof of clause
- theory::TheoryId theory_id = currentStep->getTheory();
- Debug("pf::tp") << "Get theory lemma from " << theory_id << "..." << std::endl;
-
- std::set<Node> missingAssertions = recipe.getMissingAssertionsForStep(i);
- if (!missingAssertions.empty()) {
- Debug("pf::tp") << "Have missing assertions for this step!" << std::endl;
- }
-
- // Turn rewrite filter ON
- std::set<Node>::const_iterator missingAssertion;
- for (missingAssertion = missingAssertions.begin();
- missingAssertion != missingAssertions.end();
- ++missingAssertion) {
-
- Debug("pf::tp") << "Working on missing assertion: " << *missingAssertion << std::endl;
-
- Assert(recipe.wasRewritten(missingAssertion->negate()));
- Node explanation = recipe.getExplanation(missingAssertion->negate()).negate();
-
- Debug("pf::tp") << "Found explanation: " << explanation << std::endl;
-
- // We have a missing assertion.
- // rewriteIt->first is the assertion after the rewrite (the explanation),
- // rewriteIt->second is the original assertion that needs to be fed into the theory.
-
- bool found = false;
- unsigned k;
- for (k = 0; k < currentClauseExpr.size(); ++k) {
- if (currentClauseExpr[k] == explanation.toExpr()) {
- found = true;
- break;
- }
- }
-
- AlwaysAssert(found);
-
- Debug("pf::tp") << "Replacing theory assertion "
- << currentClauseExpr[k]
- << " with "
- << *missingAssertion
- << std::endl;
-
- currentClauseExpr[k] = missingAssertion->toExpr();
-
- std::ostringstream rewritten;
-
- if (missingAssertion->getKind() == kind::NOT && (*missingAssertion)[0].toExpr() == utils::mkFalse()) {
- rewritten << "(or_elim_2 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << pm->getLitName(explanation);
- rewritten << ") (iff_elim_2 _ _ ";
- rewritten << d_assertionToRewrite[missingAssertion->negate()];
- rewritten << "))";
- }
- else {
- rewritten << "(or_elim_1 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << pm->getLitName(explanation);
- rewritten << ") (iff_elim_1 _ _ ";
- rewritten << d_assertionToRewrite[missingAssertion->negate()];
- rewritten << "))";
- }
-
- Debug("pf::tp") << "Setting a rewrite filter for this proof: " << std::endl
- << pm->getLitName(*missingAssertion) << " --> " << rewritten.str()
- << "explanation = " << explanation
- << std::endl << std::endl;
-
- pm->addRewriteFilter(pm->getLitName(*missingAssertion), rewritten.str());
- }
-
- getTheoryProof(theory_id)->printTheoryLemmaProof(currentClauseExpr, os, paren, map);
-
- // Turn rewrite filter OFF
- pm->clearRewriteFilters();
-
- Debug("pf::tp") << "Get theory lemma from " << theory_id << "... DONE!" << std::endl;
- os << clause_paren.str();
- os << "( \\ " << pm->getLemmaClauseName(id) << "s" << i <<"\n";
- paren << "))";
- }
-
- Assert(numberOfSteps >= 2);
-
- os << "(satlem_simplify _ _ _ ";
- for (unsigned i = 0; i < numberOfSteps - 1; ++i) {
- // Resolve step i with step i + 1
- if (recipe.getStep(i)->getLiteral().getKind() == kind::NOT) {
- os << "(Q _ _ ";
- } else {
- os << "(R _ _ ";
- }
-
- os << pm->getLemmaClauseName(id) << "s" << i;
- os << " ";
- }
-
- os << pm->getLemmaClauseName(id) << "s" << numberOfSteps - 1 << " ";
-
- prop::SatLiteral v;
- for (int i = numberOfSteps - 2; i >= 0; --i) {
- v = ProofManager::currentPM()->getCnfProof()->getLiteral(recipe.getStep(i)->getLiteral());
- os << ProofManager::getVarName(v.getSatVariable(), "") << ") ";
- }
-
- os << "( \\ " << pm->getLemmaClauseName(id) << "\n";
- paren << "))";
- }
- }
-}
-
-void LFSCTheoryProofEngine::printBoundTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Debug("pf::tp") << "LFSCTheoryProofEngine::printBoundTerm( " << term << " ) " << std::endl;
-
- // Since let-abbreviated terms are abbreviated with their default type, only
- // use the let map if there is no expectedType or the expectedType matches
- // the default.
- if (expectedType.isNull()
- || TypeNode::fromType(term.getType()) == expectedType)
- {
- ProofLetMap::const_iterator it = map.find(term);
- if (it != map.end())
- {
- unsigned id = it->second.id;
- unsigned count = it->second.count;
-
- if (count > LET_COUNT)
- {
- os << "let" << id;
- Debug("pf::tp::letmap") << "Using let map for " << term << std::endl;
- return;
- }
- }
- }
- Debug("pf::tp::letmap") << "Skipping let map for " << term << std::endl;
-
- printTheoryTerm(term, os, map, expectedType);
-}
-
-void LFSCTheoryProofEngine::printBoundFormula(Expr term,
- std::ostream& os,
- const ProofLetMap& map)
-{
- Assert(term.getType().isBoolean() or term.getType().isPredicate());
- bool wrapWithBoolToPred = term.getType().isBoolean() and printsAsBool(term);
- if (wrapWithBoolToPred)
- {
- os << "(p_app ";
- }
- printBoundTerm(term, os, map);
- if (wrapWithBoolToPred)
- {
- os << ")";
- }
-}
-
-void LFSCTheoryProofEngine::printCoreTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- if (term.isVariable()) {
- os << ProofManager::sanitize(term);
- return;
- }
-
- Kind k = term.getKind();
-
- switch(k) {
- case kind::ITE: {
- TypeNode armType = expectedType.isNull()
- ? TypeNode::fromType(term.getType())
- : expectedType;
- bool useFormulaType = term.getType().isBoolean();
- Assert(term[1].getType().isSubtypeOf(term.getType()));
- Assert(term[2].getType().isSubtypeOf(term.getType()));
- os << (useFormulaType ? "(ifte " : "(ite _ ");
-
- printBoundFormula(term[0], os, map);
- os << " ";
- if (useFormulaType)
- {
- printBoundFormula(term[1], os, map);
- }
- else
- {
- printBoundTerm(term[1], os, map, armType);
- }
- os << " ";
- if (useFormulaType)
- {
- printBoundFormula(term[2], os, map);
- }
- else
- {
- printBoundTerm(term[2], os, map, armType);
- }
- os << ")";
- return;
- }
-
- case kind::EQUAL: {
- bool booleanCase = term[0].getType().isBoolean();
- TypeNode armType = equalityType(term[0], term[1]);
-
- os << "(";
- if (booleanCase) {
- os << "iff ";
- } else {
- os << "= ";
- printSort(term[0].getType(), os);
- os << " ";
- }
-
- if (booleanCase && printsAsBool(term[0])) os << "(p_app ";
- printBoundTerm(term[0], os, map, armType);
- if (booleanCase && printsAsBool(term[0])) os << ")";
-
- os << " ";
-
- if (booleanCase && printsAsBool(term[1])) os << "(p_app ";
- printBoundTerm(term[1], os, map, armType);
- if (booleanCase && printsAsBool(term[1])) os << ") ";
- os << ")";
-
- return;
- }
-
- case kind::DISTINCT:
- {
- // Distinct nodes can have any number of chidlren.
- Assert(term.getNumChildren() >= 2);
- TypeNode armType = equalityType(term[0], term[1]);
-
- if (term.getNumChildren() == 2) {
- os << "(not (= ";
- printSort(term[0].getType(), os);
- os << " ";
- printBoundTerm(term[0], os, map, armType);
- os << " ";
- printBoundTerm(term[1], os, map, armType);
- os << "))";
- } else {
- unsigned numOfPairs = term.getNumChildren() * (term.getNumChildren() - 1) / 2;
- for (unsigned i = 1; i < numOfPairs; ++i) {
- os << "(and ";
- }
-
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- for (unsigned j = i + 1; j < term.getNumChildren(); ++j) {
- armType = equalityType(term[i], term[j]);
- if ((i != 0) || (j != 1)) {
- os << "(not (= ";
- printSort(term[0].getType(), os);
- os << " ";
- printBoundTerm(term[i], os, map, armType);
- os << " ";
- printBoundTerm(term[j], os, map, armType);
- os << ")))";
- } else {
- os << "(not (= ";
- printSort(term[0].getType(), os);
- os << " ";
- printBoundTerm(term[0], os, map, armType);
- os << " ";
- printBoundTerm(term[1], os, map, armType);
- os << "))";
- }
- }
- }
- }
- return;
- }
-
- default: Unhandled() << k;
- }
-}
-
-void TheoryProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) {
- // Default method for replaying proofs: assert (negated) literals back to a fresh copy of the theory
- Assert(d_theory != NULL);
-
- context::UserContext fakeContext;
- ProofOutputChannel oc;
- theory::Valuation v(NULL);
- //make new copy of theory
- theory::Theory* th;
- Trace("pf::tp") << ";; Print theory lemma proof, theory id = " << d_theory->getId() << std::endl;
-
- if (d_theory->getId()==theory::THEORY_UF) {
- th = new theory::uf::TheoryUF(&fakeContext,
- &fakeContext,
- oc,
- v,
- ProofManager::currentPM()->getLogicInfo(),
- nullptr,
- "replay::");
- } else if (d_theory->getId()==theory::THEORY_ARRAYS) {
- th = new theory::arrays::TheoryArrays(
- &fakeContext,
- &fakeContext,
- oc,
- v,
- ProofManager::currentPM()->getLogicInfo(),
- nullptr,
- "replay::");
- } else if (d_theory->getId() == theory::THEORY_ARITH) {
- Trace("theory-proof-debug") << "Arith proofs currently not supported. Use 'trust'" << std::endl;
- os << " (clausify_false trust)";
- return;
- } else {
- InternalError() << "can't generate theory-proof for "
- << ProofManager::currentPM()->getLogic();
- }
- // must perform initialization on the theory
- if (th != nullptr)
- {
- // finish init, standalone version
- th->finishInitStandalone();
- }
-
- Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - calling th->ProduceProofs()" << std::endl;
- th->produceProofs();
- Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - th->ProduceProofs() DONE" << std::endl;
-
- MyPreRegisterVisitor preRegVisitor(th);
- for (unsigned i=0; i<lemma.size(); i++) {
- Node strippedLit = (lemma[i].getKind() == kind::NOT) ? lemma[i][0] : lemma[i];
- if (strippedLit.getKind() == kind::EQUAL ||
- d_theory->getId() == theory::Theory::theoryOf(strippedLit)) {
- Node lit = Node::fromExpr( lemma[i] ).negate();
- Trace("pf::tp") << "; preregistering and asserting " << lit << std::endl;
- NodeVisitor<MyPreRegisterVisitor>::run(preRegVisitor, lit);
- th->assertFact(lit, false);
- }
- }
-
- Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - calling th->check()" << std::endl;
- th->check(theory::Theory::EFFORT_FULL);
- Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - th->check() DONE" << std::endl;
-
- if(!oc.hasConflict()) {
- Trace("pf::tp") << "; conflict is null" << std::endl;
- Node lastLemma = oc.getLastLemma();
- Assert(!lastLemma.isNull());
- Trace("pf::tp") << "; ++ but got lemma: " << lastLemma << std::endl;
-
- if (lastLemma.getKind() == kind::OR) {
- Debug("pf::tp") << "OR lemma. Negating each child separately" << std::endl;
- for (unsigned i = 0; i < lastLemma.getNumChildren(); ++i) {
- if (lastLemma[i].getKind() == kind::NOT) {
- Trace("pf::tp") << "; asserting fact: " << lastLemma[i][0] << std::endl;
- th->assertFact(lastLemma[i][0], false);
- }
- else {
- Trace("pf::tp") << "; asserting fact: " << lastLemma[i].notNode() << std::endl;
- th->assertFact(lastLemma[i].notNode(), false);
- }
- }
- } else {
- Unreachable();
-
- Assert(oc.getLastLemma().getKind() == kind::NOT);
- Debug("pf::tp") << "NOT lemma" << std::endl;
- Trace("pf::tp") << "; asserting fact: " << oc.getLastLemma()[0]
- << std::endl;
- th->assertFact(oc.getLastLemma()[0], false);
- }
-
- // Trace("pf::tp") << "; ++ but got lemma: " << oc.d_lemma << std::endl;
- // Trace("pf::tp") << "; asserting " << oc.d_lemma[1].negate() << std::endl;
- // th->assertFact(oc.d_lemma[1].negate(), false);
-
- //
- th->check(theory::Theory::EFFORT_FULL);
- } else {
- Debug("pf::tp") << "Calling oc.d_proof->toStream(os)" << std::endl;
- oc.getConflictProof().toStream(os, map);
- Debug("pf::tp") << "Calling oc.d_proof->toStream(os) -- DONE!" << std::endl;
- }
-
- Debug("pf::tp") << "About to delete the theory solver used for proving the lemma... " << std::endl;
- delete th;
- Debug("pf::tp") << "About to delete the theory solver used for proving the lemma: DONE! " << std::endl;
-}
-
-bool TheoryProofEngine::supportedTheory(theory::TheoryId id) {
- return (id == theory::THEORY_ARRAYS ||
- id == theory::THEORY_ARITH ||
- id == theory::THEORY_BV ||
- id == theory::THEORY_UF ||
- id == theory::THEORY_BOOL);
-}
-
-bool TheoryProofEngine::printsAsBool(const Node &n) {
- if (!n.getType().isBoolean()) {
- return false;
- }
-
- theory::TheoryId theory_id = theory::Theory::theoryOf(n);
- return getTheoryProof(theory_id)->printsAsBool(n);
-}
-
-BooleanProof::BooleanProof(TheoryProofEngine* proofEngine)
- : TheoryProof(NULL, proofEngine)
-{}
-
-void BooleanProof::registerTerm(Expr term) {
- Assert(term.getType().isBoolean());
-
- if (term.isVariable() && d_declarations.find(term) == d_declarations.end()) {
- d_declarations.insert(term);
- return;
- }
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- d_proofEngine->registerTerm(term[i]);
- }
-}
-
-theory::TheoryId BooleanProof::getTheoryId() { return theory::THEORY_BOOL; }
-void LFSCBooleanProof::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap) {
- Node falseNode = NodeManager::currentNM()->mkConst(false);
- Node trueNode = NodeManager::currentNM()->mkConst(true);
-
- Assert(c1 == falseNode.toExpr() || c1 == trueNode.toExpr());
- Assert(c2 == falseNode.toExpr() || c2 == trueNode.toExpr());
- Assert(c1 != c2);
-
- if (c1 == trueNode.toExpr())
- os << "t_t_neq_f";
- else
- os << "(negsymm _ _ _ t_t_neq_f)";
-}
-
-void LFSCBooleanProof::printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Assert(term.getType().isBoolean());
- if (term.isVariable()) {
- os << ProofManager::sanitize(term);
- return;
- }
-
- Kind k = term.getKind();
- switch(k) {
- case kind::OR:
- case kind::AND:
- if (options::lfscLetification() && term.getNumChildren() > 2) {
- // If letification is on, the entire term is probably a let expression.
- // However, we need to transform it from (and a b c) into (and a (and b c)) form first.
- Node currentExpression = term[term.getNumChildren() - 1];
- for (int i = term.getNumChildren() - 2; i >= 0; --i) {
- NodeBuilder<> builder(k);
- builder << term[i];
- builder << currentExpression.toExpr();
- currentExpression = builder;
- }
-
- // The let map should already have the current expression.
- ProofLetMap::const_iterator it = map.find(currentExpression.toExpr());
- if (it != map.end()) {
- unsigned id = it->second.id;
- unsigned count = it->second.count;
-
- if (count > LET_COUNT) {
- os << "let" << id;
- break;
- }
- }
- }
-
- // If letification is off or there were 2 children, same treatment as the other cases.
- CVC4_FALLTHROUGH;
- case kind::XOR:
- case kind::IMPLIES:
- case kind::NOT:
- // print the Boolean operators
- os << "(" << utils::toLFSCKind(k);
- if(term.getNumChildren() > 2) {
- // LFSC doesn't allow declarations with variable numbers of
- // arguments, so we have to flatten these N-ary versions.
- std::ostringstream paren;
- os << " ";
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
-
- if (printsAsBool(term[i])) os << "(p_app ";
- d_proofEngine->printBoundTerm(term[i], os, map);
- if (printsAsBool(term[i])) os << ")";
-
- os << " ";
- if(i < term.getNumChildren() - 2) {
- os << "(" << utils::toLFSCKind(k) << " ";
- paren << ")";
- }
- }
- os << paren.str() << ")";
- } else {
- // this is for binary and unary operators
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- os << " ";
- if (printsAsBool(term[i])) os << "(p_app ";
- d_proofEngine->printBoundTerm(term[i], os, map);
- if (printsAsBool(term[i])) os << ")";
- }
- os << ")";
- }
- return;
-
- case kind::CONST_BOOLEAN:
- os << (term.getConst<bool>() ? "true" : "false");
- return;
-
- default: Unhandled() << k;
- }
-}
-
-void LFSCBooleanProof::printOwnedSort(Type type, std::ostream& os) {
- Assert(type.isBoolean());
- os << "Bool";
-}
-
-void LFSCBooleanProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
- // Nothing to do here at this point.
-}
-
-void LFSCBooleanProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
- for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
- Expr term = *it;
-
- os << "(% " << ProofManager::sanitize(term) << " (term ";
- printSort(term.getType(), os);
- os <<")\n";
- paren <<")";
- }
-}
-
-void LFSCBooleanProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
- // Nothing to do here at this point.
-}
-
-void LFSCBooleanProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) {
- // Nothing to do here at this point.
-}
-
-void LFSCBooleanProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) {
- Unreachable() << "No boolean lemmas yet!";
-}
-
-bool LFSCBooleanProof::printsAsBool(const Node &n)
-{
- Kind k = n.getKind();
- switch (k) {
- case kind::BOOLEAN_TERM_VARIABLE:
- case kind::VARIABLE:
- return true;
-
- default:
- return false;
- }
-}
-
-void TheoryProof::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap) {
- // By default, we just print a trust statement. Specific theories can implement
- // better proofs.
-
- os << "(trust_f (not (= _ ";
- d_proofEngine->printBoundTerm(c1, os, globalLetMap);
- os << " ";
- d_proofEngine->printBoundTerm(c2, os, globalLetMap);
- os << ")))";
-}
-
-void TheoryProof::printRewriteProof(std::ostream& os, const Node &n1, const Node &n2) {
- // This is the default for a rewrite proof: just a trust statement.
- ProofLetMap emptyMap;
- os << "(trust_f (iff ";
- d_proofEngine->printBoundTerm(n1.toExpr(), os, emptyMap);
- os << " ";
- d_proofEngine->printBoundTerm(n2.toExpr(), os, emptyMap);
- os << "))";
-}
-
-void TheoryProof::printOwnedTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- this->printOwnedTermAsType(term, os, map, expectedType);
-}
-
-TypeNode TheoryProof::equalityType(const Expr& left, const Expr& right)
-{
- Assert(left.getType() == right.getType())
- << "TheoryProof::equalityType(" << left << ", " << right << "):" << std::endl
- << "types disagree:" << std::endl
- << "\tleft: " << left.getType() << std::endl
- << "\tright:" << right.getType();
- return TypeNode::fromType(left.getType());
-}
-
-bool TheoryProof::match(TNode n1, TNode n2)
-{
- theory::TheoryId theoryId = this->getTheoryId();
- ProofManager* pm = ProofManager::currentPM();
- bool ufProof = (theoryId == theory::THEORY_UF);
- Debug(ufProof ? "pf::uf" : "mgd") << "match " << n1 << " " << n2 << std::endl;
- if (pm->hasOp(n1))
- {
- n1 = pm->lookupOp(n1);
- }
- if (pm->hasOp(n2))
- {
- n2 = pm->lookupOp(n2);
- }
- Debug(ufProof ? "pf::uf" : "mgd") << "+ match " << n1 << " " << n2
- << std::endl;
- if (!ufProof)
- {
- Debug("pf::array") << "+ match: step 1" << std::endl;
- }
- if (n1 == n2)
- {
- return true;
- }
-
- if (n1.getType().isFunction() && n2.hasOperator())
- {
- if (pm->hasOp(n2.getOperator()))
- {
- return n1 == pm->lookupOp(n2.getOperator());
- }
- else
- {
- return n1 == n2.getOperator();
- }
- }
-
- if (n2.getType().isFunction() && n1.hasOperator())
- {
- if (pm->hasOp(n1.getOperator()))
- {
- return n2 == pm->lookupOp(n1.getOperator());
- }
- else
- {
- return n2 == n1.getOperator();
- }
- }
-
- if (n1.hasOperator() && n2.hasOperator()
- && n1.getOperator() != n2.getOperator())
- {
- if (ufProof
- || !((n1.getKind() == kind::SELECT
- && n2.getKind() == kind::PARTIAL_SELECT_0)
- || (n1.getKind() == kind::SELECT
- && n2.getKind() == kind::PARTIAL_SELECT_1)
- || (n1.getKind() == kind::PARTIAL_SELECT_1
- && n2.getKind() == kind::SELECT)
- || (n1.getKind() == kind::PARTIAL_SELECT_1
- && n2.getKind() == kind::PARTIAL_SELECT_0)
- || (n1.getKind() == kind::PARTIAL_SELECT_0
- && n2.getKind() == kind::SELECT)
- || (n1.getKind() == kind::PARTIAL_SELECT_0
- && n2.getKind() == kind::PARTIAL_SELECT_1)))
- {
- return false;
- }
- }
-
- for (size_t i = 0; i < n1.getNumChildren() && i < n2.getNumChildren(); ++i)
- {
- if (n1[i] != n2[i])
- {
- return false;
- }
- }
-
- return true;
-}
-
-int TheoryProof::assertAndPrint(
- const theory::eq::EqProof& pf,
- const ProofLetMap& map,
- std::shared_ptr<theory::eq::EqProof> subTrans,
- theory::eq::EqProof::PrettyPrinter* pPrettyPrinter)
-{
- theory::TheoryId theoryId = getTheoryId();
- int neg = -1;
- Assert(theoryId == theory::THEORY_UF || theoryId == theory::THEORY_ARRAYS);
- bool ufProof = (theoryId == theory::THEORY_UF);
- std::string theoryName = theory::getStatsPrefix(theoryId);
- pf.debug_print(("pf::" + theoryName).c_str(), 0, pPrettyPrinter);
- Debug("pf::" + theoryName) << std::endl;
-
- Assert(pf.d_id == theory::eq::MERGED_THROUGH_TRANS);
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.size() >= 2);
-
- subTrans->d_id = theory::eq::MERGED_THROUGH_TRANS;
- subTrans->d_node = pf.d_node;
-
- size_t i = 0;
- while (i < pf.d_children.size())
- {
- // special treatment for uf and not for array
- if (ufProof
- || pf.d_children[i]->d_id != theory::eq::MERGED_THROUGH_CONGRUENCE)
- {
- pf.d_children[i]->d_node = simplifyBooleanNode(pf.d_children[i]->d_node);
- }
-
- // Look for the negative clause, with which we will form a contradiction.
- if (!pf.d_children[i]->d_node.isNull()
- && pf.d_children[i]->d_node.getKind() == kind::NOT)
- {
- Assert(neg < 0);
- (neg) = i;
- ++i;
- }
-
- // Handle congruence closures over equalities.
- else if (pf.d_children[i]->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE
- && pf.d_children[i]->d_node.isNull())
- {
- Debug("pf::" + theoryName) << "Handling congruence over equalities"
- << std::endl;
-
- // Gather the sequence of consecutive congruence closures.
- std::vector<std::shared_ptr<const theory::eq::EqProof>>
- congruenceClosures;
- unsigned count;
- Debug("pf::" + theoryName) << "Collecting congruence sequence"
- << std::endl;
- for (count = 0; i + count < pf.d_children.size()
- && pf.d_children[i + count]->d_id
- == theory::eq::MERGED_THROUGH_CONGRUENCE
- && pf.d_children[i + count]->d_node.isNull();
- ++count)
- {
- Debug("pf::" + theoryName) << "Found a congruence: " << std::endl;
- pf.d_children[i + count]->debug_print(
- ("pf::" + theoryName).c_str(), 0, pPrettyPrinter);
- congruenceClosures.push_back(pf.d_children[i + count]);
- }
-
- Debug("pf::" + theoryName)
- << "Total number of congruences found: " << congruenceClosures.size()
- << std::endl;
-
- // Determine if the "target" of the congruence sequence appears right
- // before or right after the sequence.
- bool targetAppearsBefore = true;
- bool targetAppearsAfter = true;
-
- if ((i == 0) || (i == 1 && neg == 0))
- {
- Debug("pf::" + theoryName) << "Target does not appear before"
- << std::endl;
- targetAppearsBefore = false;
- }
-
- if ((i + count >= pf.d_children.size())
- || (!pf.d_children[i + count]->d_node.isNull()
- && pf.d_children[i + count]->d_node.getKind() == kind::NOT))
- {
- Debug("pf::" + theoryName) << "Target does not appear after"
- << std::endl;
- targetAppearsAfter = false;
- }
-
- // Flow changes between uf and array
- if (ufProof)
- {
- // Assert that we have precisely at least one possible clause.
- Assert(targetAppearsBefore || targetAppearsAfter);
-
- // If both are valid, assume the one after the sequence is correct
- if (targetAppearsAfter && targetAppearsBefore)
- {
- targetAppearsBefore = false;
- }
- }
- else
- { // not a uf proof
- // Assert that we have precisely one target clause.
- Assert(targetAppearsBefore != targetAppearsAfter);
- }
-
- // Begin breaking up the congruences and ordering the equalities
- // correctly.
- std::vector<std::shared_ptr<theory::eq::EqProof>> orderedEqualities;
-
- // Insert target clause first.
- if (targetAppearsBefore)
- {
- orderedEqualities.push_back(pf.d_children[i - 1]);
- // The target has already been added to subTrans; remove it.
- subTrans->d_children.pop_back();
- }
- else
- {
- orderedEqualities.push_back(pf.d_children[i + count]);
- }
-
- // Start with the congruence closure closest to the target clause, and
- // work our way back/forward.
- if (targetAppearsBefore)
- {
- for (unsigned j = 0; j < count; ++j)
- {
- if (pf.d_children[i + j]->d_children[0]->d_id
- != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.begin(),
- pf.d_children[i + j]->d_children[0]);
- if (pf.d_children[i + j]->d_children[1]->d_id
- != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(orderedEqualities.end(),
- pf.d_children[i + j]->d_children[1]);
- }
- }
- else
- {
- for (unsigned j = 0; j < count; ++j)
- {
- if (pf.d_children[i + count - 1 - j]->d_children[0]->d_id
- != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(
- orderedEqualities.begin(),
- pf.d_children[i + count - 1 - j]->d_children[0]);
- if (pf.d_children[i + count - 1 - j]->d_children[1]->d_id
- != theory::eq::MERGED_THROUGH_REFLEXIVITY)
- orderedEqualities.insert(
- orderedEqualities.end(),
- pf.d_children[i + count - 1 - j]->d_children[1]);
- }
- }
-
- // Copy the result into the main transitivity proof.
- subTrans->d_children.insert(subTrans->d_children.end(),
- orderedEqualities.begin(),
- orderedEqualities.end());
-
- // Increase i to skip over the children that have been processed.
- i += count;
- if (targetAppearsAfter)
- {
- ++i;
- }
- }
-
- // Else, just copy the child proof as is
- else
- {
- subTrans->d_children.push_back(pf.d_children[i]);
- ++i;
- }
- }
-
- bool disequalityFound = (neg >= 0);
- if (!disequalityFound)
- {
- Debug("pf::" + theoryName)
- << "A disequality was NOT found. UNSAT due to merged constants"
- << std::endl;
- Debug("pf::" + theoryName) << "Proof for: " << pf.d_node << std::endl;
- Assert(pf.d_node.getKind() == kind::EQUAL);
- Assert(pf.d_node.getNumChildren() == 2);
- Assert(pf.d_node[0].isConst() && pf.d_node[1].isConst());
- }
- return neg;
-}
-
-std::pair<Node, Node> TheoryProof::identicalEqualitiesPrinterHelper(
- bool evenLengthSequence,
- bool sequenceOver,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map,
- const std::string subproofStr,
- std::stringstream* outStream,
- Node n,
- Node nodeAfterEqualitySequence)
-{
- theory::TheoryId theoryId = getTheoryId();
- Assert(theoryId == theory::THEORY_UF || theoryId == theory::THEORY_ARRAYS);
- bool ufProof = (theoryId == theory::THEORY_UF);
- std::string theoryName = theory::getStatsPrefix(theoryId);
- if (evenLengthSequence)
- {
- // If the length is even, we need to apply transitivity for the "correct"
- // hand of the equality.
-
- Debug("pf::" + theoryName) << "Equality sequence of even length"
- << std::endl;
- Debug("pf::" + theoryName) << "n1 is: " << n << std::endl;
- Debug("pf::" + theoryName) << "pf-d_node is: " << pf.d_node << std::endl;
- Debug("pf::" + theoryName) << "Next node is: " << nodeAfterEqualitySequence
- << std::endl;
-
- (*outStream) << "(trans _ _ _ _ ";
-
- // If the sequence is at the very end of the transitivity proof, use
- // pf.d_node to guide us.
- if (!sequenceOver)
- {
- if (match(n[0], pf.d_node[0]))
- {
- n = n[0].eqNode(n[0]);
- (*outStream) << subproofStr << " (symm _ _ _ " << subproofStr << ")";
- }
- else if (match(n[1], pf.d_node[1]))
- {
- n = n[1].eqNode(n[1]);
- (*outStream) << " (symm _ _ _ " << subproofStr << ")" << subproofStr;
- }
- else
- {
- Debug("pf::" + theoryName) << "Error: identical equalities over, but "
- "hands don't match what we're proving."
- << std::endl;
- Assert(false);
- }
- }
- else
- {
- // We have a "next node". Use it to guide us.
- if (!ufProof && nodeAfterEqualitySequence.getKind() == kind::NOT)
- {
- nodeAfterEqualitySequence = nodeAfterEqualitySequence[0];
- }
-
- Assert(nodeAfterEqualitySequence.getKind() == kind::EQUAL);
-
- if ((n[0] == nodeAfterEqualitySequence[0])
- || (n[0] == nodeAfterEqualitySequence[1]))
- {
- // Eliminate n[1]
- (*outStream) << subproofStr << " (symm _ _ _ " << subproofStr << ")";
- n = n[0].eqNode(n[0]);
- }
- else if ((n[1] == nodeAfterEqualitySequence[0])
- || (n[1] == nodeAfterEqualitySequence[1]))
- {
- // Eliminate n[0]
- (*outStream) << " (symm _ _ _ " << subproofStr << ")" << subproofStr;
- n = n[1].eqNode(n[1]);
- }
- else
- {
- Debug("pf::" + theoryName) << "Error: even length sequence, but I "
- "don't know which hand to keep!"
- << std::endl;
- Assert(false);
- }
- }
-
- (*outStream) << ")";
- }
- else
- {
- Debug("pf::" + theoryName) << "Equality sequence length is odd!"
- << std::endl;
- (*outStream).str(subproofStr);
- }
-
- Debug("pf::" + theoryName) << "Have proven: " << n << std::endl;
- return std::make_pair<Node&, Node&>(n, nodeAfterEqualitySequence);
-}
-
-} /* namespace CVC4 */
diff --git a/src/proof/theory_proof.h b/src/proof/theory_proof.h
deleted file mode 100644
index dd5fe0326..000000000
--- a/src/proof/theory_proof.h
+++ /dev/null
@@ -1,510 +0,0 @@
-/********************* */
-/*! \file theory_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Liana Hadarean, Guy Katz, Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__THEORY_PROOF_H
-#define CVC4__THEORY_PROOF_H
-
-#include <iosfwd>
-#include <unordered_map>
-#include <unordered_set>
-
-#include "expr/expr.h"
-#include "expr/type_node.h"
-#include "proof/clause_id.h"
-#include "proof/proof_utils.h"
-#include "prop/sat_solver_types.h"
-#include "theory/uf/equality_engine.h"
-#include "util/proof.h"
-namespace CVC4 {
-
-namespace theory {
-class Theory;
-} /* namespace CVC4::theory */
-
-typedef std::unordered_map < ClauseId, prop::SatClause* > IdToSatClause;
-
-class TheoryProof;
-
-typedef std::unordered_set<Expr, ExprHashFunction > ExprSet;
-typedef std::map<theory::TheoryId, TheoryProof* > TheoryProofTable;
-
-typedef std::set<theory::TheoryId> TheoryIdSet;
-typedef std::map<Expr, TheoryIdSet> ExprToTheoryIds;
-
-class TheoryProofEngine {
-protected:
- ExprSet d_registrationCache;
- TheoryProofTable d_theoryProofTable;
- ExprToTheoryIds d_exprToTheoryIds;
-
- /**
- * Returns whether the theory is currently supported in proof
- * production mode.
- */
- bool supportedTheory(theory::TheoryId id);
-public:
-
- TheoryProofEngine();
- virtual ~TheoryProofEngine();
-
- /**
- * Print the theory term (could be an atom) by delegating to the proper theory.
- *
- * @param term
- * @param os
- */
- virtual void printLetTerm(Expr term, std::ostream& os) = 0;
-
- /**
- * Print a term in some (core or non-core) theory
- *
- * @param term expression representing term
- * @param os output stream
- * @param expectedType The type that this is expected to have in a parent
- * node. Null if there are no such requirements. This is useful for requesting
- * type conversions from the theory. e.g. in (5.5 == 4) the right-hand-side
- * should be converted to a real.
- *
- * The first version of this function has a default value for expectedType
- * (null) The second version is virtual.
- *
- * They are split to avoid mixing virtual function and default argument
- * values, which behave weirdly when combined.
- */
- void printBoundTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType = TypeNode())
- {
- this->printBoundTermAsType(term, os, map, expectedType);
- }
- virtual void printBoundTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) = 0;
-
- /**
- * Print the proof representation of the given sort.
- *
- * @param os
- */
- virtual void printSort(Type type, std::ostream& os) = 0;
-
- /**
- * Go over the assertions and register all terms with the theories.
- *
- * @param os
- * @param paren closing parenthesis
- */
- virtual void registerTermsFromAssertions() = 0;
-
- /**
- * Print the theory assertions (arbitrary formulas over
- * theory atoms)
- *
- * @param os
- * @param paren closing parenthesis
- */
- virtual void printAssertions(std::ostream& os, std::ostream& paren) = 0;
- /**
- * Print variable declarations that need to appear within the proof,
- * e.g. skolemized variables.
- *
- * @param os
- * @param paren closing parenthesis
- */
- virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0;
-
- /**
- * Print aliasing declarations.
- *
- * @param os
- * @param paren closing parenthesis
- */
- virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) = 0;
-
- /**
- * Print proofs of all the theory lemmas (must prove
- * actual clause used in resolution proof).
- *
- * @param os
- * @param paren
- */
- virtual void printTheoryLemmas(const IdToSatClause& lemmas, std::ostream& os,
- std::ostream& paren, ProofLetMap& map) = 0;
-
- /**
- * Register theory atom (ensures all terms and atoms are declared).
- *
- * @param atom
- */
- void registerTerm(Expr atom);
-
- /**
- * Ensures that a theory proof class for the given theory is created.
- * This method can be invoked regardless of whether the "proof" option
- * has been set.
- *
- * @param theory
- */
- void registerTheory(theory::Theory* theory);
- /**
- * Additional configuration of the theory proof class for the given theory.
- * This method should only be invoked when the "proof" option has been set.
- *
- * @param theory
- */
- void finishRegisterTheory(theory::Theory* theory);
-
- theory::TheoryId getTheoryForLemma(const prop::SatClause* clause);
- TheoryProof* getTheoryProof(theory::TheoryId id);
-
- void markTermForFutureRegistration(Expr term, theory::TheoryId id);
-
- void printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap);
-
- /**
- * Print a term in some non-core theory
- *
- * @param term expression representing term
- * @param os output stream
- * @param expectedType The type that this is expected to have in a parent
- * node. Null if there are no such requirements. This is useful for requesting
- * type conversions from the theory. e.g. in (5.5 == 4) the right-hand-side
- * should be converted to a real.
- *
- * The first version of this function has a default value for expectedType
- * (null) The second version is virtual.
- *
- * They are split to avoid mixing virtual function and default argument
- * values, which behave weirdly when combined.
- */
- void printTheoryTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType = TypeNode());
- virtual void printTheoryTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) = 0;
- /**
- * Calls `TheoryProof::equalityType` on the appropriate theory.
- */
- TypeNode equalityType(const Expr& left, const Expr& right);
-
- bool printsAsBool(const Node &n);
-};
-
-class LFSCTheoryProofEngine : public TheoryProofEngine {
- void bind(Expr term, ProofLetMap& map, Bindings& let_order);
-public:
- LFSCTheoryProofEngine()
- : TheoryProofEngine() {}
-
- void printTheoryTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
-
- void registerTermsFromAssertions() override;
- void printSortDeclarations(std::ostream& os, std::ostream& paren);
- void printTermDeclarations(std::ostream& os, std::ostream& paren);
- void printCoreTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType = TypeNode());
- void printLetTerm(Expr term, std::ostream& os) override;
- void printBoundTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
- void printAssertions(std::ostream& os, std::ostream& paren) override;
- void printLemmaRewrites(NodePairSet& rewrites,
- std::ostream& os,
- std::ostream& paren);
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
- void printTheoryLemmas(const IdToSatClause& lemmas,
- std::ostream& os,
- std::ostream& paren,
- ProofLetMap& map) override;
- void printSort(Type type, std::ostream& os) override;
-
- void performExtraRegistrations();
-
- void finalizeBvConflicts(const IdToSatClause& lemmas, std::ostream& os);
-
-private:
- static void dumpTheoryLemmas(const IdToSatClause& lemmas);
-
- // Prints this boolean term as a formula.
- // If necessary, it prints a wrapper converting a `Bool`-sorted term to a
- // formula.
- void printBoundFormula(Expr term, std::ostream& os, const ProofLetMap& map);
-
- // TODO: this function should be moved into the BV prover.
-
- std::map<Node, std::string> d_assertionToRewrite;
-};
-
-class TheoryProof {
-protected:
- // Pointer to the theory for this proof
- theory::Theory* d_theory;
- TheoryProofEngine* d_proofEngine;
- virtual theory::TheoryId getTheoryId() = 0;
-
- public:
- TheoryProof(theory::Theory* th, TheoryProofEngine* proofEngine)
- : d_theory(th)
- , d_proofEngine(proofEngine)
- {}
- virtual ~TheoryProof() {};
- /**
- * Print a term belonging some theory, not necessarily this one.
- *
- * @param term expresion representing term
- * @param os output stream
- */
- void printTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
- d_proofEngine->printBoundTerm(term, os, map);
- }
- /**
- * Print a term belonging to THIS theory.
- *
- * @param term expression representing term
- * @param os output stream
- * @param expectedType The type that this is expected to have in a parent
- * node. Null if there are no such requirements. This is useful for requesting
- * type conversions from the theory. e.g. in (5.5 == 4) the right-hand-side
- * should be converted to a real.
- *
- * The first version of this function has a default value for expectedType
- * (null) The second version is virtual.
- *
- * They are split to avoid mixing virtual function and default argument
- * values, which behave weirdly when combined.
- */
- void printOwnedTerm(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType = TypeNode());
-
- virtual void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) = 0;
-
- /**
- * Return the type (at the SMT level, the sort) of an equality or disequality
- * between `left` and `right`.
- *
- * The default implementation asserts that the two have the same type, and
- * returns it.
- *
- * A theory may want to do something else.
- *
- * For example, the theory of arithmetic allows equalities between Reals and
- * Integers. In this case the integer is upcast to a real, and the equality
- * is over reals.
- */
- virtual TypeNode equalityType(const Expr& left, const Expr& right);
-
- /**
- * Print the proof representation of the given type that belongs to some theory.
- *
- * @param type
- * @param os
- */
- void printSort(Type type, std::ostream& os) {
- d_proofEngine->printSort(type, os);
- }
-
- // congrence matching term helper
- bool match(TNode n1, TNode n2);
-
- /**
- * Helper function for ProofUF::toStreamRecLFSC and
- * ProofArray::toStreamRecLFSC
- * Inputs:
- * - pf: equality engine proof
- * - map: A map for the let-expressions in the proof
- * - subTrans: main transitivity proof part
- * - pPrettyPrinter: optional pretty printer for sub-proofs
- * returns:
- * - the index of the contradicting node in pf.
- * */
- int assertAndPrint(
- const theory::eq::EqProof& pf,
- const ProofLetMap& map,
- std::shared_ptr<theory::eq::EqProof> subTrans,
- theory::eq::EqProof::PrettyPrinter* pPrettyPrinter = nullptr);
-
- /**
- * Helper function for ProofUF::toStreamRecLFSC and
- * ProofArray::toStreamRecLFSC
- * Inputs:
- * - evenLengthSequence: true iff the length of the sequence
- * of the identical equalities is even.
- * - sequenceOver: have we reached the last equality of this sequence?
- * - pf: equality engine proof
- * - map: A map for the let-expressions in the proof
- * - subproofStr: current stringstream content
- * - outStream: output stream to which the proof is printed
- * - n: transitivity sub-proof
- * - nodeAfterEqualitySequence: The node after the identical sequence.
- * Returns:
- * A pair of nodes, that are the updated nodes n and nodeAfterEqualitySequence
- *
- */
- std::pair<Node, Node> identicalEqualitiesPrinterHelper(
- bool evenLengthSequence,
- bool sequenceOver,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map,
- const std::string subproofStr,
- std::stringstream* outStream,
- Node n,
- Node nodeAfterEqualitySequence);
-
- /**
- * Print the proof representation of the given type that belongs to THIS theory.
- *
- * @param type
- * @param os
- */
- virtual void printOwnedSort(Type type, std::ostream& os) = 0;
- /**
- * Print a proof for the theory lemmas. Must prove
- * clause representing lemmas to be used in resolution proof.
- *
- * @param os output stream
- */
- virtual void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map);
- /**
- * Print the sorts declarations for this theory.
- *
- * @param os
- * @param paren
- */
- virtual void printSortDeclarations(std::ostream& os, std::ostream& paren) = 0;
- /**
- * Print the term declarations for this theory.
- *
- * @param os
- * @param paren
- */
- virtual void printTermDeclarations(std::ostream& os, std::ostream& paren) = 0;
- /**
- * Print any deferred variable/sorts declarations for this theory
- * (those that need to appear inside the actual proof).
- *
- * @param os
- * @param paren
- */
- virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0;
- /**
- * Print any aliasing declarations.
- *
- * @param os
- * @param paren
- */
- virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) = 0;
- /**
- * Register a term of this theory that appears in the proof.
- *
- * @param term
- */
- virtual void registerTerm(Expr term) = 0;
- /**
- * Print a proof for the disequality of two constants that belong to this theory.
- *
- * @param term
- */
- virtual void printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap);
- /**
- * Print a proof for the equivalence of n1 and n2.
- *
- * @param term
- */
- virtual void printRewriteProof(std::ostream& os, const Node &n1, const Node &n2);
-
- /**
- * Return whether this node, when serialized as an LFSC proof, has sort `Bool`.
- *
- * This is virtual because it ultimately, theories control the serialization
- * of their proofs, so a theory will need to override this appropriately.
- *
- * This should only be called on nodes of type `Bool`.
- */
- virtual bool printsAsBool(const Node &n) {
- // Most nodes print as formulas, so this is the default.
- return false;
- }
-};
-
-class BooleanProof : public TheoryProof {
-protected:
- ExprSet d_declarations; // all the boolean variables
- theory::TheoryId getTheoryId() override;
-
- public:
- BooleanProof(TheoryProofEngine* proofEngine);
-
- void registerTerm(Expr term) override;
-};
-
-class LFSCBooleanProof : public BooleanProof {
-public:
- LFSCBooleanProof(TheoryProofEngine* proofEngine)
- : BooleanProof(proofEngine)
- {}
- void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode ty) override;
- void printOwnedSort(Type type, std::ostream& os) override;
- void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) override;
- void printSortDeclarations(std::ostream& os, std::ostream& paren) override;
- void printTermDeclarations(std::ostream& os, std::ostream& paren) override;
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
-
- bool printsAsBool(const Node& n) override;
- void printConstantDisequalityProof(std::ostream& os,
- Expr c1,
- Expr c2,
- const ProofLetMap& globalLetMap) override;
-};
-
-} /* CVC4 namespace */
-
-#endif /* CVC4__THEORY_PROOF_H */
diff --git a/src/proof/uf_proof.cpp b/src/proof/uf_proof.cpp
deleted file mode 100644
index 74990ff44..000000000
--- a/src/proof/uf_proof.cpp
+++ /dev/null
@@ -1,759 +0,0 @@
-/********************* */
-/*! \file uf_proof.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Liana Hadarean, Guy Katz, Yoni Zohar
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-#include "proof/uf_proof.h"
-
-#include <stack>
-
-#include "proof/proof_manager.h"
-#include "proof/simplify_boolean_node.h"
-#include "theory/uf/theory_uf.h"
-
-namespace CVC4 {
-
-void ProofUF::toStream(std::ostream& out) const
-{
- ProofLetMap map;
- toStream(out, map);
-}
-
-void ProofUF::toStream(std::ostream& out, const ProofLetMap& map) const
-{
- Trace("theory-proof-debug") << "; Print UF proof..." << std::endl;
- //AJR : carry this further?
- toStreamLFSC(out, ProofManager::getUfProof(), *d_proof, map);
-}
-
-void ProofUF::toStreamLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map)
-{
- Debug("pf::uf") << "ProofUF::toStreamLFSC starting" << std::endl;
- Debug("lfsc-uf") << "Printing uf proof in LFSC : " << std::endl;
- pf.debug_print("lfsc-uf");
- Debug("lfsc-uf") << std::endl;
- toStreamRecLFSC( out, tp, pf, 0, map );
-}
-
-Node ProofUF::toStreamRecLFSC(std::ostream& out,
- TheoryProof* tp,
- const theory::eq::EqProof& pf,
- unsigned tb,
- const ProofLetMap& map)
-{
- Debug("pf::uf") << std::endl
- << std::endl
- << "toStreamRecLFSC called. tb = " << tb
- << " . proof:" << std::endl;
- if (tb == 0)
- {
- // Special case: false was an input, so the proof is just "false".
- if (pf.d_id == theory::eq::MERGED_THROUGH_EQUALITY &&
- pf.d_node == NodeManager::currentNM()->mkConst(false)) {
- out << "(clausify_false ";
- out << ProofManager::getLitName(NodeManager::currentNM()->mkConst(false).notNode());
- out << ")" << std::endl;
- return Node();
- }
-
- std::shared_ptr<theory::eq::EqProof> subTrans =
- std::make_shared<theory::eq::EqProof>();
-
- int neg = tp->assertAndPrint(pf, map, subTrans);
-
- Node n1;
- std::stringstream ss, ss2;
- Debug("pf::uf") << "\nsubtrans has " << subTrans->d_children.size() << " children\n";
- bool disequalityFound = (neg >= 0);
-
- if(!disequalityFound || subTrans->d_children.size() >= 2) {
- n1 = toStreamRecLFSC(ss, tp, *subTrans, 1, map);
- } else {
- n1 = toStreamRecLFSC(ss, tp, *(subTrans->d_children[0]), 1, map);
- Debug("pf::uf") << "\nsubTrans unique child "
- << subTrans->d_children[0]->d_id
- << " was proven\ngot: " << n1 << std::endl;
- }
-
- Debug("pf::uf") << "\nhave proven: " << n1 << std::endl;
-
- out << "(clausify_false (contra _ ";
- if (disequalityFound) {
- Node n2 = pf.d_children[neg]->d_node;
- Assert(n2.getKind() == kind::NOT);
-
- Debug("pf::uf") << "n2 is " << n2[0] << std::endl;
-
- if (n2[0].getNumChildren() > 0)
- {
- Debug("pf::uf") << "\nn2[0]: " << n2[0][0] << std::endl;
- }
- if (n1.getNumChildren() > 1) { Debug("pf::uf") << "n1[1]: " << n1[1] << std::endl; }
-
- if(n2[0].getKind() == kind::APPLY_UF) {
- out << "(trans _ _ _ _ ";
-
- if (n1[0] == n2[0]) {
- out << "(symm _ _ _ ";
- out << ss.str();
- out << ") ";
- } else {
- Assert(n1[1] == n2[0]);
- out << ss.str();
- }
- out << "(pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl;
- } else if (n2[0].getKind() == kind::BOOLEAN_TERM_VARIABLE) {
- out << ss.str() << " " << ProofManager::getLitName(n2[0]) << "))";
- } else {
- Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1])
- || (n1[1] == n2[0][0] && n1[0] == n2[0][1]));
- if(n1[1] == n2[0][0]) {
- out << "(symm _ _ _ " << ss.str() << ")";
- } else {
- out << ss.str();
- }
- out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl;
- }
- } else {
- Node n2 = pf.d_node;
- Assert(n2.getKind() == kind::EQUAL);
- Assert((n1[0] == n2[0] && n1[1] == n2[1])
- || (n1[1] == n2[0] && n1[0] == n2[1]));
-
- out << ss.str();
- out << " ";
- ProofManager::getTheoryProofEngine()->printConstantDisequalityProof(
- out, n1[0].toExpr(), n1[1].toExpr(), map);
- out << "))" << std::endl;
- }
-
- return Node();
- }
- // TODO (#2965): improve this code, which is highly complicated.
- switch(pf.d_id) {
- case theory::eq::MERGED_THROUGH_CONGRUENCE: {
- Debug("pf::uf") << "\nok, looking at congruence:\n";
- pf.debug_print("pf::uf");
- std::stack<const theory::eq::EqProof*> stk;
- for (const theory::eq::EqProof* pf2 = &pf;
- pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE;
- pf2 = pf2->d_children[0].get()) {
- Assert(!pf2->d_node.isNull());
- Assert(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF
- || pf2->d_node.getKind() == kind::BUILTIN
- || pf2->d_node.getKind() == kind::APPLY_UF
- || pf2->d_node.getKind() == kind::SELECT
- || pf2->d_node.getKind() == kind::STORE);
- Assert(pf2->d_children.size() == 2);
- out << "(cong _ _ _ _ _ _ ";
- stk.push(pf2);
- }
- Assert(stk.top()->d_children[0]->d_id
- != theory::eq::MERGED_THROUGH_CONGRUENCE);
- NodeBuilder<> b1(kind::PARTIAL_APPLY_UF), b2(kind::PARTIAL_APPLY_UF);
- const theory::eq::EqProof* pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- Node n1 = toStreamRecLFSC(out, tp, *(pf2->d_children[0]), tb + 1, map);
- out << " ";
- std::stringstream ss;
- Node n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
- Debug("pf::uf") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n";
- pf2->debug_print("pf::uf");
- Debug("pf::uf") << "looking at " << pf2->d_node << "\n";
- Debug("pf::uf") << " " << n1 << "\n";
- Debug("pf::uf") << " " << n2 << "\n";
- int side = 0;
- if (tp->match(pf2->d_node, n1[0]))
- {
- //if(tb == 1) {
- Debug("pf::uf") << "SIDE IS 0\n";
- //}
- side = 0;
- } else {
- //if(tb == 1) {
- Debug("pf::uf") << "SIDE IS 1\n";
- //}
- if (!tp->match(pf2->d_node, n1[1]))
- {
- Debug("pf::uf") << "IN BAD CASE, our first subproof is\n";
- pf2->d_children[0]->debug_print("pf::uf");
- }
- Assert(tp->match(pf2->d_node, n1[1]));
- side = 1;
- }
- if (n1[side].getKind() == kind::APPLY_UF
- || n1[side].getKind() == kind::PARTIAL_APPLY_UF
- || n1[side].getKind() == kind::SELECT
- || n1[side].getKind() == kind::STORE)
- {
- if (n1[side].getKind() == kind::APPLY_UF
- || n1[side].getKind() == kind::PARTIAL_APPLY_UF)
- {
- b1 << n1[side].getOperator();
- } else {
- b1 << ProofManager::currentPM()->mkOp(n1[side].getOperator());
- }
- b1.append(n1[side].begin(), n1[side].end());
- } else {
- b1 << n1[side];
- }
- if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || n1[1-side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::STORE) {
- if (n1[1 - side].getKind() == kind::PARTIAL_APPLY_UF
- || n1[1 - side].getKind() == kind::APPLY_UF)
- {
- b2 << n1[1-side].getOperator();
- } else {
- b2 << ProofManager::currentPM()->mkOp(n1[1-side].getOperator());
- }
- b2.append(n1[1-side].begin(), n1[1-side].end());
- } else {
- b2 << n1[1-side];
- }
- Debug("pf::uf") << "pf2->d_node " << pf2->d_node << std::endl;
- Debug("pf::uf") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl;
- Debug("pf::uf") << "n1 " << n1 << std::endl;
- Debug("pf::uf") << "n2 " << n2 << std::endl;
- Debug("pf::uf") << "side " << side << std::endl;
- if(pf2->d_node[b1.getNumChildren() - (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(pf2->d_node[b1.getNumChildren()
- - (pf2->d_node.getMetaKind()
- == kind::metakind::PARAMETERIZED
- ? 0
- : 1)]
- == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
- out << ")";
- while(!stk.empty()) {
- if(tb == 1) {
- Debug("pf::uf") << "\nMORE TO DO\n";
- }
- pf2 = stk.top();
- stk.pop();
- Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
- out << " ";
- ss.str("");
- n2 = toStreamRecLFSC(ss, tp, *(pf2->d_children[1]), tb + 1, map);
- Debug("pf::uf") << "\nok, in cong[" << stk.size() << "]" << "\n";
- Debug("pf::uf") << "looking at " << pf2->d_node << "\n";
- Debug("pf::uf") << " " << n1 << "\n";
- Debug("pf::uf") << " " << n2 << "\n";
- Debug("pf::uf") << " " << b1 << "\n";
- Debug("pf::uf") << " " << b2 << "\n";
- if(pf2->d_node[b1.getNumChildren()] == n2[side]) {
- b1 << n2[side];
- b2 << n2[1-side];
- out << ss.str();
- } else {
- Assert(pf2->d_node[b1.getNumChildren()] == n2[1 - side]);
- b1 << n2[1-side];
- b2 << n2[side];
- out << "(symm _ _ _ " << ss.str() << ")";
- }
- out << ")";
- }
- n1 = b1;
- n2 = b2;
- Debug("pf::uf") << "at end assert, got " << pf2->d_node << " and " << n1 << std::endl;
- if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
- if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
- b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b1.clear(kind::APPLY_UF);
- b1 << n1.getOperator();
- }
- b1.append(n1.begin(), n1.end());
- n1 = b1;
- Debug("pf::uf") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl;
- if(pf2->d_node.getKind() == kind::APPLY_UF) {
- Assert(n1 == pf2->d_node);
- }
- }
- if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) {
- if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
- b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
- } else {
- b2.clear(kind::APPLY_UF);
- b2 << n2.getOperator();
- }
- b2.append(n2.begin(), n2.end());
- n2 = b2;
- }
- Node n = (side == 0 ? n1.eqNode(n2) : n2.eqNode(n1));
- if(tb == 1) {
- Debug("pf::uf") << "\ncong proved: " << n << "\n";
- }
- return n;
- }
-
- case theory::eq::MERGED_THROUGH_REFLEXIVITY:
- {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- out << "(refl _ ";
- tp->printTerm(NodeManager::currentNM()->toExpr(pf.d_node), out, map);
- out << ")";
- return pf.d_node.eqNode(pf.d_node);
- }
- case theory::eq::MERGED_THROUGH_EQUALITY:
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- out << ProofManager::getLitName(pf.d_node.negate());
- return pf.d_node;
-
- case theory::eq::MERGED_THROUGH_TRANS: {
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.size() >= 2);
- std::stringstream ss;
- Debug("pf::uf") << "\ndoing trans proof[[\n";
- pf.debug_print("pf::uf");
- Debug("pf::uf") << "\n";
-
- pf.d_children[0]->d_node = simplifyBooleanNode(pf.d_children[0]->d_node);
-
- Node n1 = toStreamRecLFSC(ss, tp, *(pf.d_children[0]), tb + 1, map);
- Debug("pf::uf") << "\ndoing trans proof, got n1 " << n1 << "\n";
- if(tb == 1) {
- Debug("pf::uf") << "\ntrans proof[0], got n1 " << n1 << "\n";
- }
-
- bool identicalEqualities = false;
- bool evenLengthSequence;
- std::stringstream dontCare;
- Node nodeAfterEqualitySequence =
- toStreamRecLFSC(dontCare, tp, *(pf.d_children[0]), tb + 1, map);
-
- std::map<size_t, Node> childToStream;
- std::pair<Node, Node> nodePair;
- for(size_t i = 1; i < pf.d_children.size(); ++i) {
- std::stringstream ss1(ss.str()), ss2;
- ss.str("");
-
- pf.d_children[i]->d_node = simplifyBooleanNode(pf.d_children[i]->d_node);
-
- // It is possible that we've already converted the i'th child to stream.
- // If so,
- // use previously stored result. Otherwise, convert and store.
- Node n2;
- if (childToStream.find(i) != childToStream.end())
- n2 = childToStream[i];
- else
- {
- n2 = toStreamRecLFSC(ss2, tp, *(pf.d_children[i]), tb + 1, map);
- childToStream[i] = n2;
- }
-
- // The following branch is dedicated to handling sequences of identical
- // equalities,
- // i.e. trans[ a=b, a=b, a=b ].
- //
- // There are two cases:
- // 1. The number of equalities is odd. Then, the sequence can be
- // collapsed to just one equality,
- // i.e. a=b.
- // 2. The number of equalities is even. Now, we have two options: a=a
- // or b=b. To determine this,
- // we look at the node after the equality sequence. If it needs a,
- // we go for a=a; and if it needs
- // b, we go for b=b. If there is no following node, we look at the
- // goal of the transitivity proof,
- // and use it to determine which option we need.
- if (n2.getKind() == kind::EQUAL)
- {
- if (((n1[0] == n2[0]) && (n1[1] == n2[1]))
- || ((n1[0] == n2[1]) && (n1[1] == n2[0])))
- {
- // We are in a sequence of identical equalities
-
- Debug("pf::uf") << "Detected identical equalities: " << std::endl
- << "\t" << n1 << std::endl;
-
- if (!identicalEqualities)
- {
- // The sequence of identical equalities has started just now
- identicalEqualities = true;
-
- Debug("pf::uf")
- << "The sequence is just beginning. Determining length..."
- << std::endl;
-
- // Determine whether the length of this sequence is odd or even.
- evenLengthSequence = true;
- bool sequenceOver = false;
- size_t j = i + 1;
-
- while (j < pf.d_children.size() && !sequenceOver)
- {
- std::stringstream ignore;
- nodeAfterEqualitySequence =
- toStreamRecLFSC(ignore, tp, *(pf.d_children[j]), tb + 1, map);
-
- if (((nodeAfterEqualitySequence[0] == n1[0])
- && (nodeAfterEqualitySequence[1] == n1[1]))
- || ((nodeAfterEqualitySequence[0] == n1[1])
- && (nodeAfterEqualitySequence[1] == n1[0])))
- {
- evenLengthSequence = !evenLengthSequence;
- }
- else
- {
- sequenceOver = true;
- }
-
- ++j;
- }
-
- nodePair =
- tp->identicalEqualitiesPrinterHelper(evenLengthSequence,
- sequenceOver,
- pf,
- map,
- ss1.str(),
- &ss,
- n1,
- nodeAfterEqualitySequence);
- n1 = nodePair.first;
- nodeAfterEqualitySequence = nodePair.second;
- } else {
- ss.str(ss1.str());
- }
-
- // Ignore the redundancy.
- continue;
- }
- }
-
- if (identicalEqualities) {
- // We were in a sequence of identical equalities, but it has now ended. Resume normal operation.
- identicalEqualities = false;
- }
-
- Debug("pf::uf") << "\ndoing trans proof, got n2 " << n2 << "\n";
- if(tb == 1) {
- Debug("pf::uf") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n";
- Debug("pf::uf") << (n2.getKind() == kind::EQUAL) << "\n";
-
- if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2)) {
- Debug("pf::uf") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n";
- Debug("pf::uf") << n1[0].getId() << " " << n1[0] << "\n";
- Debug("pf::uf") << n1[1].getId() << " " << n1[1] << "\n";
- Debug("pf::uf") << n2[0].getId() << " " << n2[0] << "\n";
- Debug("pf::uf") << n2[1].getId() << " " << n2[1] << "\n";
- Debug("pf::uf") << (n1[0] == n2[0]) << "\n";
- Debug("pf::uf") << (n1[1] == n2[1]) << "\n";
- Debug("pf::uf") << (n1[0] == n2[1]) << "\n";
- Debug("pf::uf") << (n1[1] == n2[0]) << "\n";
- }
- }
-
- ss << "(trans _ _ _ _ ";
-
- if(n2.getKind() == kind::EQUAL && n1.getKind() == kind::EQUAL)
- // Both elements of the transitivity rule are equalities/iffs
- {
- if(n1[0] == n2[0]) {
- if(tb == 1) { Debug("pf::uf") << "case 1\n"; }
- n1 = n1[1].eqNode(n2[1]);
- ss << "(symm _ _ _ " << ss1.str() << ") " << ss2.str();
- } else if(n1[1] == n2[1]) {
- if(tb == 1) { Debug("pf::uf") << "case 2\n"; }
- n1 = n1[0].eqNode(n2[0]);
- ss << ss1.str() << " (symm _ _ _ " << ss2.str() << ")";
- } else if(n1[0] == n2[1]) {
- if(tb == 1) { Debug("pf::uf") << "case 3\n"; }
- n1 = n2[0].eqNode(n1[1]);
- ss << ss2.str() << " " << ss1.str();
- if(tb == 1) { Debug("pf::uf") << "++ proved " << n1 << "\n"; }
- } else if(n1[1] == n2[0]) {
- if(tb == 1) { Debug("pf::uf") << "case 4\n"; }
- n1 = n1[0].eqNode(n2[1]);
- ss << ss1.str() << " " << ss2.str();
- } else {
- Warning() << "\n\ntrans proof failure at step " << i << "\n\n";
- Warning() << "0 proves " << n1 << "\n";
- Warning() << "1 proves " << n2 << "\n\n";
- pf.debug_print("pf::uf",0);
- //toStreamRec(Warning.getStream(), pf, 0);
- Warning() << "\n\n";
- Unreachable();
- }
- Debug("pf::uf") << "++ trans proof[" << i << "], now have " << n1 << std::endl;
- } else if(n1.getKind() == kind::EQUAL) {
- // n1 is an equality/iff, but n2 is a predicate
- if(n1[0] == n2) {
- n1 = n1[1].eqNode(NodeManager::currentNM()->mkConst(true));
- ss << "(symm _ _ _ " << ss1.str() << ") (pred_eq_t _ " << ss2.str() << ")";
- } else if(n1[1] == n2) {
- n1 = n1[0].eqNode(NodeManager::currentNM()->mkConst(true));
- ss << ss1.str() << " (pred_eq_t _ " << ss2.str() << ")";
- } else {
- Unreachable();
- }
- } else if(n2.getKind() == kind::EQUAL) {
- // n2 is an equality/iff, but n1 is a predicate
- if(n2[0] == n1) {
- n1 = n2[1].eqNode(NodeManager::currentNM()->mkConst(true));
- ss << "(symm _ _ _ " << ss2.str() << ") (pred_eq_t _ " << ss1.str() << ")";
- } else if(n2[1] == n1) {
- n1 = n2[0].eqNode(NodeManager::currentNM()->mkConst(true));
- ss << ss2.str() << " (pred_eq_t _ " << ss1.str() << ")";
- } else {
- Unreachable();
- }
- } else {
- // Both n1 and n2 are predicates.
- // We want to prove b1 = b2, and we know that ((b1), (b2)) or ((not b1), (not b2))
- if (n1.getKind() == kind::NOT) {
- Assert(n2.getKind() == kind::NOT);
- Assert(pf.d_node[0] == n1[0] || pf.d_node[0] == n2[0]);
- Assert(pf.d_node[1] == n1[0] || pf.d_node[1] == n2[0]);
- Assert(n1[0].getKind() == kind::BOOLEAN_TERM_VARIABLE);
- Assert(n2[0].getKind() == kind::BOOLEAN_TERM_VARIABLE);
-
- if (pf.d_node[0] == n1[0]) {
- ss << "(false_preds_equal _ _ " << ss1.str() << " " << ss2.str() << ") ";
- ss << "(pred_refl_neg _ " << ss2.str() << ")";
- } else {
- ss << "(false_preds_equal _ _ " << ss2.str() << " " << ss1.str() << ") ";
- ss << "(pred_refl_neg _ " << ss1.str() << ")";
- }
- n1 = pf.d_node;
-
- } else if (n1.getKind() == kind::BOOLEAN_TERM_VARIABLE) {
- Assert(n2.getKind() == kind::BOOLEAN_TERM_VARIABLE);
- Assert(pf.d_node[0] == n1 || pf.d_node[0] == n2);
- Assert(pf.d_node[1] == n1 || pf.d_node[2] == n2);
-
- if (pf.d_node[0] == n1) {
- ss << "(true_preds_equal _ _ " << ss1.str() << " " << ss2.str() << ") ";
- ss << "(pred_refl_pos _ " << ss2.str() << ")";
- } else {
- ss << "(true_preds_equal _ _ " << ss2.str() << " " << ss1.str() << ") ";
- ss << "(pred_refl_pos _ " << ss1.str() << ")";
- }
- n1 = pf.d_node;
-
- } else {
-
- Unreachable();
- }
- }
-
- ss << ")";
- }
- out << ss.str();
- Debug("pf::uf") << "\n++ trans proof done, have proven " << n1 << std::endl;
- return n1;
- }
-
- default:
- Assert(!pf.d_node.isNull());
- Assert(pf.d_children.empty());
- Debug("pf::uf") << "theory proof: " << pf.d_node << " by rule " << int(pf.d_id) << std::endl;
- AlwaysAssert(false);
- return pf.d_node;
- }
-}
-
-UFProof::UFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* pe)
- : TheoryProof(uf, pe)
-{}
-
-theory::TheoryId UFProof::getTheoryId() { return theory::THEORY_UF; }
-void UFProof::registerTerm(Expr term) {
- // already registered
- if (d_declarations.find(term) != d_declarations.end())
- return;
-
- Type type = term.getType();
- if (type.isSort()) {
- // declare uninterpreted sorts
- d_sorts.insert(type);
- }
-
- if (term.getKind() == kind::APPLY_UF) {
- Expr function = term.getOperator();
- d_declarations.insert(function);
- }
-
- if (term.isVariable()) {
- d_declarations.insert(term);
-
-
- if (term.getKind() == kind::BOOLEAN_TERM_VARIABLE) {
- // Ensure cnf literals
- Node asNode(term);
- ProofManager::currentPM()->ensureLiteral(
- asNode.eqNode(NodeManager::currentNM()->mkConst(true)));
- ProofManager::currentPM()->ensureLiteral(
- asNode.eqNode(NodeManager::currentNM()->mkConst(false)));
- }
- }
-
- // recursively declare all other terms
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- // could belong to other theories
- d_proofEngine->registerTerm(term[i]);
- }
-}
-
-void LFSCUFProof::printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType)
-{
- Node node = Node::fromExpr(term);
- Debug("pf::uf") << std::endl << "(pf::uf) LFSCUfProof::printOwnedTerm: term = " << node << std::endl;
-
- Assert(theory::Theory::theoryOf(node) == theory::THEORY_UF);
-
- if (node.getKind() == kind::VARIABLE ||
- node.getKind() == kind::SKOLEM ||
- node.getKind() == kind::BOOLEAN_TERM_VARIABLE) {
- os << node;
- return;
- }
-
- Assert(node.getKind() == kind::APPLY_UF);
-
- if(node.getType().isBoolean()) {
- os << "(p_app ";
- }
- Node func = node.getOperator();
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- os << "(apply _ _ ";
- }
- os << func << " ";
- Assert(func.getType().isFunction());
- std::vector<TypeNode> argsTypes = node.getOperator().getType().getArgTypes();
- for (unsigned i = 0; i < node.getNumChildren(); ++i) {
-
- bool convertToBool = (node[i].getType().isBoolean() && !d_proofEngine->printsAsBool(node[i]));
- if (convertToBool) os << "(f_to_b ";
- d_proofEngine->printBoundTerm(term[i], os, map, argsTypes[i]);
- if (convertToBool) os << ")";
- os << ")";
- }
- if(term.getType().isBoolean()) {
- os << ")";
- }
-}
-
-void LFSCUFProof::printOwnedSort(Type type, std::ostream& os) {
- Debug("pf::uf") << std::endl << "(pf::uf) LFSCArrayProof::printOwnedSort: type is: " << type << std::endl;
-
- Assert(type.isSort());
- os << type;
-}
-
-void LFSCUFProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map) {
- os << " ;; UF Theory Lemma \n;;";
- for (unsigned i = 0; i < lemma.size(); ++i) {
- os << lemma[i] <<" ";
- }
- os <<"\n";
- //os << " (clausify_false trust)";
- UFProof::printTheoryLemmaProof(lemma, os, paren, map);
-}
-
-void LFSCUFProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
- for (TypeSet::const_iterator it = d_sorts.begin(); it != d_sorts.end(); ++it) {
- if (!ProofManager::currentPM()->wasPrinted(*it)) {
- os << "(% " << *it << " sort\n";
- paren << ")";
- ProofManager::currentPM()->markPrinted(*it);
- }
- }
-}
-
-void LFSCUFProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
- // declaring the terms
- Debug("pf::uf") << "LFSCUFProof::printTermDeclarations called" << std::endl;
-
- for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
- Expr term = *it;
-
- os << "(% " << ProofManager::sanitize(term) << " ";
- os << "(term ";
-
- Type type = term.getType();
- if (type.isFunction()) {
- std::ostringstream fparen;
- FunctionType ftype = (FunctionType)type;
- std::vector<Type> args = ftype.getArgTypes();
- args.push_back(ftype.getRangeType());
- os << "(arrow";
- for (unsigned i = 0; i < args.size(); i++) {
- Type arg_type = args[i];
- os << " ";
- d_proofEngine->printSort(arg_type, os);
- if (i < args.size() - 2) {
- os << " (arrow";
- fparen << ")";
- }
- }
- os << fparen.str() << "))\n";
- } else {
- Assert(term.isVariable());
- os << type << ")\n";
- }
- paren << ")";
- }
-
- Debug("pf::uf") << "LFSCUFProof::printTermDeclarations done" << std::endl;
-}
-
-void LFSCUFProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
- // Nothing to do here at this point.
-}
-
-void LFSCUFProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren, const ProofLetMap &globalLetMap) {
- // Nothing to do here at this point.
-}
-
-bool LFSCUFProof::printsAsBool(const Node &n) {
- if (n.getKind() == kind::BOOLEAN_TERM_VARIABLE)
- return true;
-
- return false;
-}
-
-void LFSCUFProof::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2, const ProofLetMap &globalLetMap) {
- Node falseNode = NodeManager::currentNM()->mkConst(false);
- Node trueNode = NodeManager::currentNM()->mkConst(true);
-
- Assert(c1 == falseNode.toExpr() || c1 == trueNode.toExpr());
- Assert(c2 == falseNode.toExpr() || c2 == trueNode.toExpr());
- Assert(c1 != c2);
-
- if (c1 == trueNode.toExpr())
- os << "t_t_neq_f";
- else
- os << "(symm _ _ _ t_t_neq_f)";
-}
-
-} /* namespace CVC4 */
diff --git a/src/proof/uf_proof.h b/src/proof/uf_proof.h
deleted file mode 100644
index 647359a87..000000000
--- a/src/proof/uf_proof.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/********************* */
-/*! \file uf_proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Mathias Preiner, Liana Hadarean, Tim King
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief UF proof
- **
- ** UF proof
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__UF__PROOF_H
-#define CVC4__UF__PROOF_H
-
-#include <memory>
-#include <unordered_set>
-
-#include "expr/expr.h"
-#include "proof/theory_proof.h"
-#include "theory/uf/equality_engine.h"
-#include "util/proof.h"
-
-namespace CVC4 {
-
-// proof object outputted by TheoryUF
-class ProofUF : public Proof
-{
- public:
- ProofUF(std::shared_ptr<theory::eq::EqProof> pf) : d_proof(pf) {}
- void toStream(std::ostream& out) const override;
- void toStream(std::ostream& out, const ProofLetMap& map) const override;
-
- private:
- static void toStreamLFSC(std::ostream& out, TheoryProof* tp,
- const theory::eq::EqProof& pf,
- const ProofLetMap& map);
- static Node toStreamRecLFSC(std::ostream& out, TheoryProof* tp,
- const theory::eq::EqProof& pf, unsigned tb,
- const ProofLetMap& map);
-
- // it is simply an equality engine proof
- std::shared_ptr<theory::eq::EqProof> d_proof;
-};
-
-namespace theory {
-namespace uf {
-class TheoryUF;
-}
-}
-
-typedef std::unordered_set<Type, TypeHashFunction > TypeSet;
-
-
-class UFProof : public TheoryProof {
-protected:
- TypeSet d_sorts; // all the uninterpreted sorts in this theory
- ExprSet d_declarations; // all the variable/function declarations
- theory::TheoryId getTheoryId() override;
-
- public:
- UFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* proofEngine);
-
- void registerTerm(Expr term) override;
-};
-
-class LFSCUFProof : public UFProof {
-public:
- LFSCUFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* proofEngine)
- : UFProof(uf, proofEngine)
- {}
- void printOwnedTermAsType(Expr term,
- std::ostream& os,
- const ProofLetMap& map,
- TypeNode expectedType) override;
- void printOwnedSort(Type type, std::ostream& os) override;
- void printTheoryLemmaProof(std::vector<Expr>& lemma,
- std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& map) override;
- void printSortDeclarations(std::ostream& os, std::ostream& paren) override;
- void printTermDeclarations(std::ostream& os, std::ostream& paren) override;
- void printDeferredDeclarations(std::ostream& os,
- std::ostream& paren) override;
- void printAliasingDeclarations(std::ostream& os,
- std::ostream& paren,
- const ProofLetMap& globalLetMap) override;
-
- bool printsAsBool(const Node& n) override;
-
- void printConstantDisequalityProof(std::ostream& os,
- Expr c1,
- Expr c2,
- const ProofLetMap& globalLetMap) override;
-};
-
-
-}/* CVC4 namespace */
-
-#endif /* CVC4__UF__PROOF_H */
diff --git a/src/prop/bvminisat/bvminisat.cpp b/src/prop/bvminisat/bvminisat.cpp
index c1aac33be..0b531c498 100644
--- a/src/prop/bvminisat/bvminisat.cpp
+++ b/src/prop/bvminisat/bvminisat.cpp
@@ -18,7 +18,6 @@
#include "prop/bvminisat/simp/SimpSolver.h"
#include "proof/clause_id.h"
-#include "proof/sat_proof.h"
#include "util/statistics_registry.h"
namespace CVC4 {
@@ -66,7 +65,6 @@ ClauseId BVMinisatSatSolver::addClause(SatClause& clause,
// }
ClauseId clause_id = ClauseIdError;
d_minisat->addClause(minisat_clause, clause_id);
- THEORY_PROOF(Assert(clause_id != ClauseIdError););
return clause_id;
}
@@ -76,14 +74,14 @@ SatValue BVMinisatSatSolver::propagate() {
void BVMinisatSatSolver::addMarkerLiteral(SatLiteral lit) {
d_minisat->addMarkerLiteral(BVMinisat::var(toMinisatLit(lit)));
- markUnremovable(lit);
+ markUnremovable(lit);
}
void BVMinisatSatSolver::explain(SatLiteral lit, std::vector<SatLiteral>& explanation) {
std::vector<BVMinisat::Lit> minisat_explanation;
d_minisat->explain(toMinisatLit(lit), minisat_explanation);
for (unsigned i = 0; i < minisat_explanation.size(); ++i) {
- explanation.push_back(toSatLiteral(minisat_explanation[i]));
+ explanation.push_back(toSatLiteral(minisat_explanation[i]));
}
}
@@ -104,12 +102,6 @@ void BVMinisatSatSolver::popAssumption() {
d_minisat->popAssumption();
}
-void BVMinisatSatSolver::setResolutionProofLog(
- proof::ResolutionBitVectorProof* bvp)
-{
- d_minisat->setProofLog( bvp );
-}
-
SatVariable BVMinisatSatSolver::newVar(bool isTheoryAtom, bool preRegister, bool canErase){
return d_minisat->newVar(true, true, !canErase);
}
@@ -148,9 +140,7 @@ SatValue BVMinisatSatSolver::solve(long unsigned int& resource){
return result;
}
-bool BVMinisatSatSolver::ok() const {
- return d_minisat->okay();
-}
+bool BVMinisatSatSolver::ok() const { return d_minisat->okay(); }
void BVMinisatSatSolver::getUnsatCore(SatClause& unsatCore) {
// TODO add assertion to check the call was after an unsat call
@@ -160,11 +150,11 @@ void BVMinisatSatSolver::getUnsatCore(SatClause& unsatCore) {
}
SatValue BVMinisatSatSolver::value(SatLiteral l){
- return toSatLiteralValue(d_minisat->value(toMinisatLit(l)));
+ return toSatLiteralValue(d_minisat->value(toMinisatLit(l)));
}
SatValue BVMinisatSatSolver::modelValue(SatLiteral l){
- return toSatLiteralValue(d_minisat->modelValue(toMinisatLit(l)));
+ return toSatLiteralValue(d_minisat->modelValue(toMinisatLit(l)));
}
void BVMinisatSatSolver::unregisterVar(SatLiteral lit) {
@@ -309,17 +299,3 @@ void BVMinisatSatSolver::Statistics::init(BVMinisat::SimpSolver* minisat){
} /* namespace CVC4::prop */
} /* namespace CVC4 */
-
-namespace CVC4 {
-template<>
-prop::SatLiteral toSatLiteral< BVMinisat::Solver>(BVMinisat::Solver::TLit lit) {
- return prop::BVMinisatSatSolver::toSatLiteral(lit);
-}
-
-template<>
-void toSatClause< BVMinisat::Solver> (const BVMinisat::Solver::TClause& minisat_cl,
- prop::SatClause& sat_cl) {
- prop::BVMinisatSatSolver::toSatClause(minisat_cl, sat_cl);
-}
-
-}
diff --git a/src/prop/bvminisat/bvminisat.h b/src/prop/bvminisat/bvminisat.h
index 01a0a518e..f93dc8048 100644
--- a/src/prop/bvminisat/bvminisat.h
+++ b/src/prop/bvminisat/bvminisat.h
@@ -21,8 +21,6 @@
#include <memory>
#include "context/cdo.h"
-#include "proof/clause_id.h"
-#include "proof/resolution_bitvector_proof.h"
#include "prop/bv_sat_solver_notify.h"
#include "prop/bvminisat/simp/SimpSolver.h"
#include "prop/sat_solver.h"
@@ -57,8 +55,8 @@ class BVMinisatSatSolver : public BVSatSolverInterface,
}
};
- std::unique_ptr<BVMinisat::SimpSolver> d_minisat;
- std::unique_ptr<MinisatNotify> d_minisatNotify;
+ std::unique_ptr<BVMinisat::SimpSolver> d_minisat;
+ std::unique_ptr<MinisatNotify> d_minisatNotify;
unsigned d_assertionsCount;
context::CDO<unsigned> d_assertionsRealCount;
@@ -79,6 +77,7 @@ public:
ClauseId addXorClause(SatClause& clause, bool rhs, bool removable) override
{
Unreachable() << "Minisat does not support native XOR reasoning";
+ return ClauseIdError;
}
SatValue propagate() override;
@@ -123,8 +122,6 @@ public:
void popAssumption() override;
- void setResolutionProofLog(proof::ResolutionBitVectorProof* bvp) override;
-
private:
/* Disable the default constructor. */
BVMinisatSatSolver() = delete;
diff --git a/src/prop/bvminisat/core/Solver.cc b/src/prop/bvminisat/core/Solver.cc
index 84ab62fd8..f7ba14acd 100644
--- a/src/prop/bvminisat/core/Solver.cc
+++ b/src/prop/bvminisat/core/Solver.cc
@@ -29,11 +29,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "base/output.h"
#include "options/bv_options.h"
#include "options/smt_options.h"
-#include "proof/clause_id.h"
-#include "proof/proof_manager.h"
-#include "proof/resolution_bitvector_proof.h"
-#include "proof/sat_proof.h"
-#include "proof/sat_proof_implementation.h"
#include "prop/bvminisat/mtl/Sort.h"
#include "theory/interrupted.h"
#include "util/utility.h"
@@ -170,8 +165,7 @@ Solver::Solver(CVC4::context::Context* context)
,
conflict_budget(-1),
propagation_budget(-1),
- asynch_interrupt(false),
- d_bvp(NULL)
+ asynch_interrupt(false)
{
// Create the constant variables
varTrue = newVar(true, false);
@@ -220,7 +214,7 @@ bool Solver::addClause_(vec<Lit>& ps, ClauseId& id)
if (decisionLevel() > 0) {
cancelUntil(0);
}
-
+
if (!ok) {
id = ClauseIdUndef;
return false;
@@ -231,7 +225,7 @@ bool Solver::addClause_(vec<Lit>& ps, ClauseId& id)
sort(ps);
Lit p; int i, j;
int falseLiteralsCount = 0;
-
+
for (i = j = 0, p = lit_Undef; i < ps.size(); i++) {
// tautologies are ignored
if (value(ps[i]) == l_True || ps[i] == ~p) {
@@ -245,82 +239,30 @@ bool Solver::addClause_(vec<Lit>& ps, ClauseId& id)
}
if (value(ps[i]) == l_False) {
- if (!THEORY_PROOF_ON())
- continue;
- ++falseLiteralsCount;
+ continue;
}
ps[j++] = p = ps[i];
}
-
+
ps.shrink(i - j);
clause_added = true;
- Assert(falseLiteralsCount == 0 || THEORY_PROOF_ON());
-
if(falseLiteralsCount == 0) {
if (ps.size() == 0) {
- Assert(!THEORY_PROOF_ON());
return ok = false;
}
else if (ps.size() == 1){
- if(d_bvp){ id = d_bvp->getSatProof()->registerUnitClause(ps[0], INPUT);}
uncheckedEnqueue(ps[0]);
CRef confl_ref = propagate();
ok = (confl_ref == CRef_Undef);
- if(d_bvp){ if (!ok) d_bvp->getSatProof()->finalizeProof(confl_ref); }
return ok;
} else {
CRef cr = ca.alloc(ps, false);
clauses.push(cr);
attachClause(cr);
- if(d_bvp){ id = d_bvp->getSatProof()->registerClause(cr, INPUT);}
- }
- return ok;
- }
-
- if (falseLiteralsCount != 0 && THEORY_PROOF_ON()) {
- // we are in a conflicting state
- if (ps.size() == falseLiteralsCount && falseLiteralsCount == 1) {
- if(d_bvp){ id = d_bvp->getSatProof()->storeUnitConflict(ps[0], INPUT); }
- if(d_bvp){ d_bvp->getSatProof()->finalizeProof(CVC4::BVMinisat::CRef_Lazy); }
- return ok = false;
- }
-
- assign_lt lt(*this);
- sort(ps, lt);
-
- CRef cr = ca.alloc(ps, false);
- clauses.push(cr);
- attachClause(cr);
-
- if(d_bvp){id = d_bvp->getSatProof()->registerClause(cr, INPUT);}
-
- if(ps.size() == falseLiteralsCount) {
- if(d_bvp){ d_bvp->getSatProof()->finalizeProof(cr); }
- return ok = false;
- }
-
- // Check if it propagates
- if (ps.size() == falseLiteralsCount + 1) {
- Clause& cl = ca[cr];
-
- Assert(value(cl[0]) == l_Undef);
- uncheckedEnqueue(cl[0], cr);
- Assert(cl.size() > 1);
- CRef confl = propagate();
- ok = (confl == CRef_Undef);
- if(!ok) {
- if(d_bvp){
- if(ca[confl].size() == 1) {
- id = d_bvp->getSatProof()->storeUnitConflict(ca[confl][0], LEARNT);
- d_bvp->getSatProof()->finalizeProof(CVC4::BVMinisat::CRef_Lazy);
- } else {
- d_bvp->getSatProof()->finalizeProof(confl);
- }
- }
- }
}
+ return ok;
}
return ok;
}
@@ -338,9 +280,6 @@ void Solver::attachClause(CRef cr) {
void Solver::detachClause(CRef cr, bool strict) {
const Clause& clause = ca[cr];
- if (d_bvp)
- {
- d_bvp->getSatProof()->markDeleted(cr); }
assert(clause.size() > 1);
@@ -425,23 +364,24 @@ Lit Solver::pickBranchLit()
return next == var_Undef ? lit_Undef : mkLit(next, rnd_pol ? drand(random_seed) < 0.5 : polarity[next]);
}
-
/*_________________________________________________________________________________________________
|
-| analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void]
-|
+| analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) ->
+[void]
+|
| Description:
| Analyze conflict and produce a reason clause.
-|
+|
| Pre-conditions:
| * 'out_learnt' is assumed to be cleared.
| * Current decision level must be greater than root level.
-|
+|
| Post-conditions:
| * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
-| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the
-| rest of literals. There may be others from the same level though.
-|
+| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision
+level of the | rest of literals. There may be others from the same level
+though.
+|
|________________________________________________________________________________________________@*/
void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip)
{
@@ -454,8 +394,6 @@ void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip
int index = trail.size() - 1;
bool done = false;
-
- if(d_bvp){ d_bvp->getSatProof()->startResChain(confl); }
do{
assert(confl != CRef_Undef); // (otherwise should be UIP)
@@ -477,13 +415,6 @@ void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip
out_learnt.push(q);
}
- if (level(var(q)) == 0)
- {
- if (d_bvp)
- {
- d_bvp->getSatProof()->resolveOutUnit(q);
- }
- }
}
// Select next clause to look at:
@@ -493,10 +424,6 @@ void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip
seen[var(p)] = 0;
pathC--;
- if ( pathC > 0 && confl != CRef_Undef ) {
- if(d_bvp){ d_bvp->getSatProof()->addResolutionStep(p, confl, sign(p));}
- }
-
switch (uip) {
case UIP_FIRST:
done = pathC == 0;
@@ -536,13 +463,6 @@ void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip
// Literal is not redundant
out_learnt[j++] = out_learnt[i1];
}
- else
- {
- if (d_bvp)
- {
- d_bvp->getSatProof()->storeLitRedundant(out_learnt[i1]);
- }
- }
}
}
}else if (ccmin_mode == 1){
@@ -640,10 +560,10 @@ bool Solver::litRedundant(Lit p, uint32_t abstract_levels)
return true;
}
-/**
+/**
* Specialized analyzeFinal procedure where we test the consistency
* of the assumptions before backtracking bellow the assumption level.
- *
+ *
* @param p the original uip (may be unit)
* @param confl_clause the conflict clause
* @param out_conflict the conflict in terms of assumptions we are building
@@ -653,14 +573,14 @@ void Solver::analyzeFinal2(Lit p, CRef confl_clause, vec<Lit>& out_conflict) {
assert (decisionLevel() == assumptions.size());
assert (level(var(p)) == assumptions.size());
- out_conflict.clear();
-
+ out_conflict.clear();
+
Clause& cl = ca[confl_clause];
for (int i = 0; i < cl.size(); ++i) {
seen[var(cl[i])] = 1;
}
- int end = options::proof() ? 0 : trail_lim[0];
+ int end = trail_lim[0];
for (int i = trail.size() - 1; i >= end; i--) {
Var x = var(trail[i]);
if (seen[x]) {
@@ -670,44 +590,31 @@ void Solver::analyzeFinal2(Lit p, CRef confl_clause, vec<Lit>& out_conflict) {
if (marker[x] == 2) {
assert (level(x) > 0);
out_conflict.push(~trail[i]);
- } else {
- if(d_bvp){d_bvp->getSatProof()->resolveOutUnit(~(trail[i])); }
}
- } else {
- if(d_bvp){d_bvp->getSatProof()->resolveOutUnit(~p);}
}
} else {
Clause& clause = ca[reason(x)];
- if(d_bvp){d_bvp->getSatProof()->addResolutionStep(trail[i],reason(x), sign(trail[i]));}
for (int j = 1; j < clause.size(); j++)
{
if (level(var(clause[j])) > 0) seen[var(clause[j])] = 1;
- if(d_bvp){
- if (level(var(clause[j])) == 0)
- {
- d_bvp->getSatProof()->resolveOutUnit(clause[j]);
- seen[var(clause[j])] =
- 0; // we don't need to resolve it out again
- }
- }
}
}
seen[x] = 0;
}
- assert (seen[x] == 0);
+ assert(seen[x] == 0);
}
- assert (out_conflict.size());
+ assert(out_conflict.size());
}
/*_________________________________________________________________________________________________
|
| analyzeFinal : (p : Lit) -> [void]
-|
+|
| Description:
-| Specialized analysis procedure to express the final conflict in terms of assumptions.
-| Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
-| stores the result in 'out_conflict'.
+| Specialized analysis procedure to express the final conflict in terms of
+assumptions. | Calculates the (possibly empty) set of assumptions that led to
+the assignment of 'p', and | stores the result in 'out_conflict'.
|________________________________________________________________________________________________@*/
void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
{
@@ -716,22 +623,14 @@ void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
out_conflict.push(p);
}
- if(d_bvp){
- if (level(var(p)) == 0 && d_bvp->isAssumptionConflict()) {
- Assert(marker[var(p)] == 2);
- if (reason(var(p)) == CRef_Undef) {
- d_bvp->startBVConflict(p);
- }
- }
- }
-
- if (decisionLevel() == 0 && !options::proof()) {
+ if (decisionLevel() == 0)
+ {
return;
}
seen[var(p)] = 1;
- int end = options::proof() ? 0 : trail_lim[0];
-
+ int end = trail_lim[0];
+
for (int i = trail.size()-1; i >= end; i--){
Var x = var(trail[i]);
if (seen[x]) {
@@ -744,26 +643,12 @@ void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
}
} else {
Clause& clause = ca[reason(x)];
- if(d_bvp){
- if (d_bvp->isAssumptionConflict() &&
- trail[i] == p) {
- d_bvp->startBVConflict(reason(x));
- } else {
- d_bvp->getSatProof()->addResolutionStep(trail[i], reason(x), sign(trail[i]));
- }
- }
for (int j = 1; j < clause.size(); j++)
{
if (level(var(clause[j])) > 0)
{
seen[var(clause[j])] = 1;
}
- if(d_bvp){
- if (level(var(clause[j])) == 0)
- {
- d_bvp->getSatProof()->resolveOutUnit(clause[j]);
- }
- }
}
}
seen[x] = 0;
@@ -805,10 +690,9 @@ lbool Solver::propagateAssumptions() {
lbool Solver::assertAssumption(Lit p, bool propagate) {
// TODO need to somehow mark the assumption as unit in the current context?
// it's not always unit though, but this would be useful for debugging
-
+
// assert(marker[var(p)] == 1);
-
if (decisionLevel() > assumptions.size()) {
cancelUntil(assumptions.size());
}
@@ -829,9 +713,9 @@ lbool Solver::assertAssumption(Lit p, bool propagate) {
// run the propagation
if (propagate) {
only_bcp = true;
- ccmin_mode = 0;
+ ccmin_mode = 0;
lbool result = search(-1);
- return result;
+ return result;
} else {
return l_True;
}
@@ -841,18 +725,16 @@ void Solver::addMarkerLiteral(Var var) {
// make sure it wasn't already marked
Assert(marker[var] == 0);
marker[var] = 1;
- if(d_bvp){d_bvp->getSatProof()->registerAssumption(var);}
}
-
/*_________________________________________________________________________________________________
|
| propagate : [void] -> [Clause*]
-|
+|
| Description:
-| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
-| otherwise CRef_Undef.
-|
+| Propagates all enqueued facts. If a conflict arises, the conflicting clause
+is returned, | otherwise CRef_Undef.
+|
| Post-conditions:
| * the propagation queue is empty, even if there was a conflict.
|________________________________________________________________________________________________@*/
@@ -920,20 +802,24 @@ CRef Solver::propagate()
return confl;
}
-
/*_________________________________________________________________________________________________
|
| reduceDB : () -> [void]
-|
+|
| Description:
-| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
-| clauses are clauses that are reason to some assignment. Binary clauses are never removed.
+| Remove half of the learnt clauses, minus the clauses locked by the current
+assignment. Locked | clauses are clauses that are reason to some assignment.
+Binary clauses are never removed.
|________________________________________________________________________________________________@*/
-struct reduceDB_lt {
- ClauseAllocator& ca;
- reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {}
- bool operator () (CRef x, CRef y) {
- return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); }
+struct reduceDB_lt
+{
+ ClauseAllocator& ca;
+ reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {}
+ bool operator()(CRef x, CRef y)
+ {
+ return ca[x].size() > 2
+ && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity());
+ }
};
void Solver::reduceDB()
{
@@ -963,14 +849,6 @@ void Solver::removeSatisfied(vec<CRef>& cs)
Clause& clause = ca[cs[i]];
if (satisfied(clause))
{
- if (locked(clause))
- {
- // store a resolution of the literal clause propagated
- if (d_bvp)
- {
- d_bvp->getSatProof()->storeUnitResolution(clause[0]);
- }
- }
removeClause(cs[i]);
}
else
@@ -989,14 +867,14 @@ void Solver::rebuildOrderHeap()
order_heap.build(vs);
}
-
/*_________________________________________________________________________________________________
|
| simplify : [void] -> [bool]
-|
+|
| Description:
-| Simplify the clause database according to the current top-level assigment. Currently, the only
-| thing done here is the removal of satisfied clauses, but more things can be put here.
+| Simplify the clause database according to the current top-level assigment.
+Currently, the only | thing done here is the removal of satisfied clauses,
+but more things can be put here.
|________________________________________________________________________________________________@*/
bool Solver::simplify()
{
@@ -1021,19 +899,19 @@ bool Solver::simplify()
return true;
}
-
/*_________________________________________________________________________________________________
|
| search : (nof_conflicts : int) (params : const SearchParams&) -> [lbool]
-|
+|
| Description:
-| Search for a model the specified number of conflicts.
+| Search for a model the specified number of conflicts.
| NOTE! Use negative value for 'nof_conflicts' indicate infinity.
-|
+|
| Output:
-| 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
-| all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
-| if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
+| 'l_True' if a partial assigment that is consistent with respect to the
+clauseset is found. If | all variables are decision variables, this means
+that the clause set is satisfiable. 'l_False' | if the clause set is
+unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
|________________________________________________________________________________________________@*/
lbool Solver::search(int nof_conflicts, UIP uip)
{
@@ -1051,7 +929,6 @@ lbool Solver::search(int nof_conflicts, UIP uip)
if (decisionLevel() == 0) {
// can this happen for bv?
- if(d_bvp){ d_bvp->getSatProof()->finalizeProof(confl);}
return l_False;
}
@@ -1067,59 +944,34 @@ lbool Solver::search(int nof_conflicts, UIP uip)
learnts.push(cr);
attachClause(cr);
claBumpActivity(ca[cr]);
- if(d_bvp){
- ClauseId id = d_bvp->getSatProof()->registerClause(cr, LEARNT);
- PSTATS(
- std::unordered_set<int> cl_levels;
- for (int i = 0; i < learnt_clause.size(); ++i) {
- cl_levels.insert(level(var(learnt_clause[i])));
- }
- if( d_bvp ){ d_bvp->getSatProof()->storeClauseGlue(id, cl_levels.size()); }
- )
- d_bvp->getSatProof()->endResChain(id);
- }
}
-
+
if (learnt_clause.size() == 1) {
// learning a unit clause
- if(d_bvp){ d_bvp->getSatProof()->endResChain(learnt_clause[0]);}
}
-
+
// if the uip was an assumption we are unsat
if (level(var(p)) <= assumptions.size()) {
for (int i = 0; i < learnt_clause.size(); ++i) {
- assert (level(var(learnt_clause[i])) <= decisionLevel());
+ assert(level(var(learnt_clause[i])) <= decisionLevel());
seen[var(learnt_clause[i])] = 1;
}
- // Starting new resolution chain for bit-vector proof
- if( d_bvp ){
- if (cr == CRef_Undef) {
- d_bvp->startBVConflict(learnt_clause[0]);
- }
- else {
- d_bvp->startBVConflict(cr);
- }
- }
analyzeFinal(p, conflict);
- if(d_bvp){ d_bvp->endBVConflict(conflict); }
Debug("bvminisat::search") << OUTPUT_TAG << " conflict on assumptions " << std::endl;
return l_False;
}
if (!CVC4::options::bvEagerExplanations()) {
- // check if uip leads to a conflict
+ // check if uip leads to a conflict
if (backtrack_level < assumptions.size()) {
cancelUntil(assumptions.size());
uncheckedEnqueue(p, cr);
-
+
CRef new_confl = propagate();
if (new_confl != CRef_Undef) {
// we have a conflict we now need to explain it
- // TODO: proof for analyzeFinal2
- if(d_bvp){ d_bvp->startBVConflict(new_confl); }
analyzeFinal2(p, new_confl, conflict);
- if(d_bvp){ d_bvp->endBVConflict(conflict); }
return l_False;
}
}
@@ -1127,8 +979,7 @@ lbool Solver::search(int nof_conflicts, UIP uip)
cancelUntil(backtrack_level);
uncheckedEnqueue(p, cr);
-
-
+
varDecayActivity();
claDecayActivity();
@@ -1138,10 +989,17 @@ lbool Solver::search(int nof_conflicts, UIP uip)
max_learnts *= learntsize_inc;
if (verbosity >= 1)
- printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
- (int)conflicts,
- (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals,
- (int)max_learnts, nLearnts(), (double)learnts_literals/nLearnts(), progressEstimate()*100);
+ printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
+ (int)conflicts,
+ (int)dec_vars
+ - (trail_lim.size() == 0 ? trail.size()
+ : trail_lim[0]),
+ nClauses(),
+ (int)clauses_literals,
+ (int)max_learnts,
+ nLearnts(),
+ (double)learnts_literals / nLearnts(),
+ progressEstimate() * 100);
}
}else{
@@ -1152,9 +1010,9 @@ lbool Solver::search(int nof_conflicts, UIP uip)
withinBudget(ResourceManager::Resource::BvSatConflictsStep);
}
catch (const CVC4::theory::Interrupted& e) {
- // do some clean-up and rethrow
- cancelUntil(assumptions.size());
- throw e;
+ // do some clean-up and rethrow
+ cancelUntil(assumptions.size());
+ throw e;
}
if ((decisionLevel() > assumptions.size() && nof_conflicts >= 0
@@ -1192,10 +1050,8 @@ lbool Solver::search(int nof_conflicts, UIP uip)
newDecisionLevel();
}else if (value(p) == l_False){
marker[var(p)] = 2;
-
- if(d_bvp){ d_bvp->markAssumptionConflict(); }
+
analyzeFinal(~p, conflict);
- if(d_bvp){ d_bvp->endBVConflict(conflict); }
Debug("bvminisat::search") << OUTPUT_TAG << " assumption false, we're unsat" << std::endl;
return l_False;
}else{
@@ -1283,7 +1139,7 @@ lbool Solver::solve_()
conflict.clear();
ccmin_mode = 0;
-
+
if (!ok) return l_False;
solves++;
@@ -1324,31 +1180,20 @@ lbool Solver::solve_()
//=================================================================================================
// Bitvector propagations
-//
+//
void Solver::explain(Lit p, std::vector<Lit>& explanation) {
Debug("bvminisat::explain") << OUTPUT_TAG << "starting explain of " << p << std::endl;
// top level fact, no explanation necessary
if (level(var(p)) == 0) {
- if(d_bvp){
- // the only way a marker variable is
- if (reason(var(p)) == CRef_Undef) {
- d_bvp->startBVConflict(p);
- vec<Lit> confl;
- confl.push(p);
- d_bvp->endBVConflict(confl);
- return;
- }
- }
- if (!THEORY_PROOF_ON())
- return;
+ return;
}
-
+
seen[var(p)] = 1;
// if we are called at decisionLevel = 0 trail_lim is empty
- int bottom = options::proof() ? 0 : trail_lim[0];
+ int bottom = trail_lim[0];
for (int i = trail.size()-1; i >= bottom; i--){
Var x = var(trail[i]);
if (seen[x]) {
@@ -1358,21 +1203,12 @@ void Solver::explain(Lit p, std::vector<Lit>& explanation) {
explanation.push_back(trail[i]);
} else {
Assert(level(x) == 0);
- if(d_bvp){ d_bvp->getSatProof()->resolveOutUnit(~(trail[i])); }
}
-
} else {
Clause& clause = ca[reason(x)];
- if(d_bvp){
- if (p == trail[i]) {
- d_bvp->startBVConflict(reason(var(p)));
- } else {
- d_bvp->getSatProof()->addResolutionStep(trail[i], reason(x), sign(trail[i]));
- }
- }
for (int j = 1; j < clause.size(); j++)
{
- if (level(var(clause[j])) > 0 || options::proof())
+ if (level(var(clause[j])) > 0)
{
seen[var(clause[j])] = 1;
}
@@ -1382,28 +1218,11 @@ void Solver::explain(Lit p, std::vector<Lit>& explanation) {
}
}
seen[var(p)] = 0;
-
- if(d_bvp){
- vec<Lit> conflict_clause;
- conflict_clause.push(p);
- for(unsigned i = 0; i < explanation.size(); ++i) {
- conflict_clause.push(~explanation[i]);
- }
- d_bvp->endBVConflict(conflict_clause);
- }
-}
-
-void Solver::setProofLog(proof::ResolutionBitVectorProof* bvp)
-{
- d_bvp = bvp;
- d_bvp->initSatProof(this);
- d_bvp->getSatProof()->registerTrueLit(mkLit(varTrue, false));
- d_bvp->getSatProof()->registerFalseLit(mkLit(varFalse, true));
}
//=================================================================================================
// Writing CNF to DIMACS:
-//
+//
// FIXME: this needs to be rewritten completely.
static Var mapVar(Var x, vec<Var>& map, Var& max)
@@ -1454,7 +1273,7 @@ void Solver::toDimacs(FILE* f, const vec<Lit>& assumps)
for (int i = 0; i < clauses.size(); i++)
if (!satisfied(ca[clauses[i]]))
cnt++;
-
+
for (int i = 0; i < clauses.size(); i++)
if (!satisfied(ca[clauses[i]])){
Clause& clause = ca[clauses[i]];
@@ -1494,8 +1313,7 @@ void Solver::relocAll(ClauseAllocator& to)
Lit p = mkLit(v, s);
// printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
vec<Watcher>& ws = watches[p];
- for (int j = 0; j < ws.size(); j++)
- ca.reloc(ws[j].cref, to, d_bvp ? d_bvp->getSatProof() : NULL);
+ for (int j = 0; j < ws.size(); j++) ca.reloc(ws[j].cref, to);
}
// All reasons:
@@ -1504,20 +1322,16 @@ void Solver::relocAll(ClauseAllocator& to)
Var v = var(trail[i]);
if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
- ca.reloc(vardata[v].reason, to, d_bvp ? d_bvp->getSatProof() : NULL);
+ ca.reloc(vardata[v].reason, to);
}
// All learnt:
//
- for (int i = 0; i < learnts.size(); i++)
- ca.reloc(learnts[i], to, d_bvp ? d_bvp->getSatProof() : NULL);
+ for (int i = 0; i < learnts.size(); i++) ca.reloc(learnts[i], to);
// All original:
//
- for (int i = 0; i < clauses.size(); i++)
- ca.reloc(clauses[i], to, d_bvp ? d_bvp->getSatProof() : NULL);
-
- if(d_bvp){ d_bvp->getSatProof()->finishUpdateCRef(); }
+ for (int i = 0; i < clauses.size(); i++) ca.reloc(clauses[i], to);
}
@@ -1525,33 +1339,28 @@ void Solver::garbageCollect()
{
// Initialize the next region to a size corresponding to the estimated utilization degree. This
// is not precise but should avoid some unnecessary reallocations for the new region:
- ClauseAllocator to(ca.size() - ca.wasted());
- Debug("bvminisat") << " BVMinisat::Garbage collection \n";
+ ClauseAllocator to(ca.size() - ca.wasted());
+ Debug("bvminisat") << " BVMinisat::Garbage collection \n";
relocAll(to);
if (verbosity >= 2)
- printf("| Garbage collection: %12d bytes => %12d bytes |\n",
- ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
+ printf(
+ "| Garbage collection: %12d bytes => %12d bytes |\n",
+ ca.size() * ClauseAllocator::Unit_Size,
+ to.size() * ClauseAllocator::Unit_Size);
to.moveTo(ca);
}
-void ClauseAllocator::reloc(CRef& cr,
- ClauseAllocator& to,
- CVC4::TSatProof<Solver>* proof)
+void ClauseAllocator::reloc(CRef& cr, ClauseAllocator& to)
{
- CRef old = cr; // save the old reference
-
Clause& c = operator[](cr);
if (c.reloced()) { cr = c.relocation(); return; }
-
+
cr = to.alloc(c, c.learnt());
c.relocate(cr);
- if (proof)
- {
- proof->updateCRef(old, cr);
- }
-
- // Copy extra data-fields:
- // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
+
+ // Copy extra data-fields:
+ // (This could be cleaned-up. Generalize Clause-constructor to be applicable
+ // here instead?)
to[cr].mark(c.mark());
if (to[cr].learnt()) to[cr].activity() = c.activity();
else if (to[cr].has_extra()) to[cr].calcAbstraction();
diff --git a/src/prop/bvminisat/core/Solver.h b/src/prop/bvminisat/core/Solver.h
index 7fad72d6d..f2721c88d 100644
--- a/src/prop/bvminisat/core/Solver.h
+++ b/src/prop/bvminisat/core/Solver.h
@@ -25,7 +25,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "context/context.h"
#include "proof/clause_id.h"
-#include "proof/sat_proof.h"
#include "prop/bvminisat/core/SolverTypes.h"
#include "prop/bvminisat/mtl/Alg.h"
#include "prop/bvminisat/mtl/Heap.h"
@@ -39,11 +38,6 @@ namespace BVMinisat {
class Solver;
}
-// TODO (aozdemir) replace this forward declaration with an include
-namespace proof {
-class ResolutionBitVectorProof;
-}
-
namespace BVMinisat {
/** Interface for minisat callbacks */
@@ -71,11 +65,10 @@ public:
//=================================================================================================
// Solver -- the main class:
class Solver {
- friend class CVC4::TSatProof< CVC4::BVMinisat::Solver>;
public:
typedef Var TVar;
typedef Lit TLit;
- typedef Clause TClause;
+ typedef Clause TClause;
typedef CRef TCRef;
typedef vec<Lit> TLitVec;
@@ -109,12 +102,17 @@ public:
Var trueVar() const { return varTrue; }
Var falseVar() const { return varFalse; }
-
- bool addClause (const vec<Lit>& ps, ClauseId& id); // Add a clause to the solver.
+ bool addClause(const vec<Lit>& ps,
+ ClauseId& id); // Add a clause to the solver.
bool addEmptyClause(); // Add the empty clause, making the solver contradictory.
- bool addClause (Lit p, ClauseId& id); // Add a unit clause to the solver.
- bool addClause (Lit p, Lit q, ClauseId& id); // Add a binary clause to the solver.
- bool addClause (Lit p, Lit q, Lit r, ClauseId& id); // Add a ternary clause to the solver.
+ bool addClause(Lit p, ClauseId& id); // Add a unit clause to the solver.
+ bool addClause(Lit p,
+ Lit q,
+ ClauseId& id); // Add a binary clause to the solver.
+ bool addClause(Lit p,
+ Lit q,
+ Lit r,
+ ClauseId& id); // Add a ternary clause to the solver.
bool addClause_( vec<Lit>& ps, ClauseId& id); // Add a clause to the solver without making superflous internal copy. Will
// change the passed vector 'ps'.
@@ -141,9 +139,9 @@ public:
void toDimacs (const char* file, Lit p);
void toDimacs (const char* file, Lit p, Lit q);
void toDimacs (const char* file, Lit p, Lit q, Lit r);
-
+
// Variable mode:
- //
+ //
void setPolarity (Var v, bool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'.
void setDecisionVar (Var v, bool b); // Declare if a variable should be eligible for selection in the decision heuristic.
@@ -211,13 +209,12 @@ public:
void addMarkerLiteral(Var var);
- bool need_to_propagate; // true if we added new clauses, set to true in propagation
+ bool need_to_propagate; // true if we added new clauses, set to true in
+ // propagation
bool only_bcp; // solving mode in which only boolean constraint propagation is done
void setOnlyBCP (bool val) { only_bcp = val;}
void explain(Lit l, std::vector<Lit>& explanation);
- void setProofLog(CVC4::proof::ResolutionBitVectorProof* bvp);
-
protected:
// has a clause been added
@@ -293,9 +290,6 @@ public:
int64_t conflict_budget; // -1 means no budget.
int64_t propagation_budget; // -1 means no budget.
bool asynch_interrupt;
-
- //proof log
- CVC4::proof::ResolutionBitVectorProof* d_bvp;
// Main internal methods:
//
@@ -458,13 +452,15 @@ inline int Solver::nLearnts () const { return learnts.size(); }
inline int Solver::nVars () const { return vardata.size(); }
inline int Solver::nFreeVars () const { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); }
inline void Solver::setPolarity (Var v, bool b) { polarity[v] = b; }
-inline void Solver::setDecisionVar(Var v, bool b)
-{
- if ( b && !decision[v]) dec_vars++;
- else if (!b && decision[v]) dec_vars--;
+inline void Solver::setDecisionVar(Var v, bool b)
+{
+ if (b && !decision[v])
+ dec_vars++;
+ else if (!b && decision[v])
+ dec_vars--;
- decision[v] = b;
- insertVarOrder(v);
+ decision[v] = b;
+ insertVarOrder(v);
}
inline void Solver::setConfBudget(int64_t x){ conflict_budget = conflicts + x; }
inline void Solver::setPropBudget(int64_t x){ propagation_budget = propagations + x; }
diff --git a/src/prop/bvminisat/core/SolverTypes.h b/src/prop/bvminisat/core/SolverTypes.h
index 302db104f..cf9ce7e15 100644
--- a/src/prop/bvminisat/core/SolverTypes.h
+++ b/src/prop/bvminisat/core/SolverTypes.h
@@ -86,15 +86,14 @@ struct LitHashFunction {
const Lit lit_Undef = { -2 }; // }- Useful special constants.
const Lit lit_Error = { -1 }; // }
-
//=================================================================================================
// Lifted booleans:
//
-// NOTE: this implementation is optimized for the case when comparisons between values are mostly
-// between one variable and one constant. Some care had to be taken to make sure that gcc
-// does enough constant propagation to produce sensible code, and this appears to be somewhat
-// fragile unfortunately.
-
+// NOTE: this implementation is optimized for the case when comparisons between
+// values are mostly
+// between one variable and one constant. Some care had to be taken to
+// make sure that gcc does enough constant propagation to produce sensible
+// code, and this appears to be somewhat fragile unfortunately.
#ifndef l_True
#define l_True (lbool((uint8_t)0)) // gcc does not do constant propagation if these are real constants.
@@ -121,10 +120,12 @@ public:
bool operator != (lbool b) const { return !(*this == b); }
lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); }
- lbool operator && (lbool b) const {
- uint8_t sel = (this->value << 1) | (b.value << 3);
- uint8_t v = (0xF7F755F4 >> sel) & 3;
- return lbool(v); }
+ lbool operator&&(lbool b) const
+ {
+ uint8_t sel = (this->value << 1) | (b.value << 3);
+ uint8_t v = (0xF7F755F4 >> sel) & 3;
+ return lbool(v);
+ }
lbool operator || (lbool b) const {
uint8_t sel = (this->value << 1) | (b.value << 3);
@@ -163,14 +164,14 @@ class Clause {
header.reloced = 0;
header.size = ps.size();
- for (int i = 0; i < ps.size(); i++)
- data[i].lit = ps[i];
+ for (int i = 0; i < ps.size(); i++) data[i].lit = ps[i];
if (header.has_extra){
if (header.learnt)
- data[header.size].act = 0;
- else
- calcAbstraction(); }
+ data[header.size].act = 0;
+ else
+ calcAbstraction();
+ }
}
public:
@@ -256,9 +257,7 @@ class ClauseAllocator : public RegionAllocator<uint32_t>
RegionAllocator<uint32_t>::free(clauseWord32Size(c.size(), c.has_extra()));
}
- void reloc(CRef& cr,
- ClauseAllocator& to,
- CVC4::TSatProof<Solver>* proof = NULL);
+ void reloc(CRef& cr, ClauseAllocator& to);
};
@@ -275,7 +274,7 @@ class OccLists
public:
OccLists(const Deleted& d) : deleted(d) {}
-
+
void init (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); }
// Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
@@ -334,13 +333,12 @@ class CMap
typedef Map<CRef, T, CRefHash> HashTable;
HashTable map;
-
+
public:
// Size-operations:
void clear () { map.clear(); }
int size () const { return map.elems(); }
-
// Insert/Remove/Test mapping:
void insert (CRef cr, const T& t){ map.insert(cr, t); }
void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility
@@ -363,15 +361,14 @@ class CMap
printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); }
};
-
/*_________________________________________________________________________________________________
|
| subsumes : (other : const Clause&) -> Lit
-|
+|
| Description:
-| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other'
-| by subsumption resolution.
-|
+| Checks if clause subsumes 'other', and at the same time, if it can be
+used to simplify 'other' | by subsumption resolution.
+|
| Result:
| lit_Error - No subsumption or simplification
| lit_Undef - Clause subsumes 'other'
diff --git a/src/prop/bvminisat/simp/SimpSolver.cc b/src/prop/bvminisat/simp/SimpSolver.cc
index b003342c6..9429e4ced 100644
--- a/src/prop/bvminisat/simp/SimpSolver.cc
+++ b/src/prop/bvminisat/simp/SimpSolver.cc
@@ -23,7 +23,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "options/bv_options.h"
#include "options/smt_options.h"
#include "proof/clause_id.h"
-#include "proof/proof.h"
#include "prop/bvminisat/mtl/Sort.h"
#include "prop/bvminisat/utils/System.h"
@@ -64,7 +63,7 @@ SimpSolver::SimpSolver(CVC4::context::Context* context)
asymm_lits(0),
eliminated_vars(0),
elimorder(1),
- use_simplification(!PROOF_ON()),
+ use_simplification(true),
occurs(ClauseDeleted(ca)),
elim_heap(ElimLt(n_occ)),
bwdsub_assigns(0),
@@ -94,7 +93,7 @@ SimpSolver::SimpSolver(CVC4::context::Context* context)
SimpSolver::~SimpSolver()
{
- // CVC4::StatisticsRegistry::unregisterStat(&total_eliminate_time);
+ // CVC4::StatisticsRegistry::unregisterStat(&total_eliminate_time);
}
@@ -111,7 +110,7 @@ Var SimpSolver::newVar(bool sign, bool dvar, bool freeze) {
touched .push(0);
elim_heap .insert(v);
if (freeze) {
- setFrozen(v, true);
+ setFrozen(v, true);
}
}
return v;
@@ -122,7 +121,7 @@ Var SimpSolver::newVar(bool sign, bool dvar, bool freeze) {
lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
{
only_bcp = false;
-
+
vec<Var> extra_frozen;
lbool result = l_True;
@@ -210,14 +209,15 @@ void SimpSolver::removeClause(CRef cr)
const Clause& clause = ca[cr];
if (use_simplification)
+ {
for (int i = 0; i < clause.size(); i++)
{
n_occ[toInt(clause[i])]--;
updateElimHeap(var(clause[i]));
occurs.smudge(var(clause[i]));
}
-
- Solver::removeClause(cr);
+ }
+ Solver::removeClause(cr);
}
@@ -538,7 +538,7 @@ bool SimpSolver::eliminateVar(Var v)
for (int i = 0; i < cls.size(); i++)
(find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]);
- // Check wether the increase in number of clauses stays within the allowed ('grow'). Moreover, no
+ // Check whether the increase in number of clauses stays within the allowed ('grow'). Moreover, no
// clause must exceed the limit on the maximal clause size (if it is set):
//
int cnt = 0;
@@ -546,9 +546,10 @@ bool SimpSolver::eliminateVar(Var v)
for (int i = 0; i < pos.size(); i++)
for (int j = 0; j < neg.size(); j++)
- if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) &&
- (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim)))
- return true;
+ if (merge(ca[pos[i]], ca[neg[j]], v, clause_size)
+ && (++cnt > cls.size() + grow
+ || (clause_lim != -1 && clause_size > clause_lim)))
+ return true;
// Delete and store old clauses:
eliminated[v] = true;
@@ -565,8 +566,7 @@ bool SimpSolver::eliminateVar(Var v)
mkElimClause(elimclauses, ~mkLit(v));
}
- for (int i = 0; i < cls.size(); i++)
- removeClause(cls[i]);
+ for (int i = 0; i < cls.size(); i++) removeClause(cls[i]);
// Produce clauses in cross product:
vec<Lit>& resolvent = add_tmp;
@@ -580,7 +580,7 @@ bool SimpSolver::eliminateVar(Var v)
// Free occurs list for this variable:
occurs[v].clear(true);
-
+
// Free watchers lists for this variable, if possible:
if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true);
if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true);
@@ -600,7 +600,7 @@ bool SimpSolver::substitute(Var v, Lit x)
eliminated[v] = true;
setDecisionVar(v, false);
const vec<CRef>& cls = occurs.lookup(v);
-
+
vec<Lit>& subst_clause = add_tmp;
for (int i = 0; i < cls.size(); i++){
Clause& clause = ca[cls[i]];
@@ -643,7 +643,7 @@ bool SimpSolver::eliminate(bool turn_off_elim)
{
// CVC4::TimerStat::CodeTimer codeTimer(total_eliminate_time);
-
+
if (!simplify())
return false;
else if (!use_simplification)
@@ -655,9 +655,12 @@ bool SimpSolver::eliminate(bool turn_off_elim)
gatherTouchedClauses();
// printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns);
- if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) &&
- !backwardSubsumptionCheck(true)){
- ok = false; goto cleanup; }
+ if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size())
+ && !backwardSubsumptionCheck(true))
+ {
+ ok = false;
+ goto cleanup;
+ }
// Empty elim_heap and return immediately on user-interrupt:
if (asynch_interrupt){
@@ -670,7 +673,7 @@ bool SimpSolver::eliminate(bool turn_off_elim)
// printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size());
for (int cnt = 0; !elim_heap.empty(); cnt++){
Var elim = elim_heap.removeMin();
-
+
if (asynch_interrupt) break;
if (isEliminated(elim) || value(elim) != l_Undef) continue;
@@ -720,8 +723,10 @@ bool SimpSolver::eliminate(bool turn_off_elim)
}
if (verbosity >= 1 && elimclauses.size() > 0)
- printf("| Eliminated clauses: %10.2f Mb |\n",
- double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024));
+ printf(
+ "| Eliminated clauses: %10.2f Mb "
+ " |\n",
+ double(elimclauses.size() * sizeof(uint32_t)) / (1024 * 1024));
return ok;
@@ -772,15 +777,17 @@ void SimpSolver::garbageCollect()
{
// Initialize the next region to a size corresponding to the estimated utilization degree. This
// is not precise but should avoid some unnecessary reallocations for the new region:
- ClauseAllocator to(ca.size() - ca.wasted());
+ ClauseAllocator to(ca.size() - ca.wasted());
cleanUpClauses();
to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields.
relocAll(to);
Solver::relocAll(to);
if (verbosity >= 2)
- printf("| Garbage collection: %12d bytes => %12d bytes |\n",
- ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
+ printf(
+ "| Garbage collection: %12d bytes => %12d bytes |\n",
+ ca.size() * ClauseAllocator::Unit_Size,
+ to.size() * ClauseAllocator::Unit_Size);
to.moveTo(ca);
}
diff --git a/src/prop/bvminisat/simp/SimpSolver.h b/src/prop/bvminisat/simp/SimpSolver.h
index 9d3a51c02..9907b8d72 100644
--- a/src/prop/bvminisat/simp/SimpSolver.h
+++ b/src/prop/bvminisat/simp/SimpSolver.h
@@ -54,7 +54,7 @@ class SimpSolver : public Solver {
Lit r,
ClauseId& id); // Add a ternary clause to the solver.
bool addClause_(vec<Lit>& ps, ClauseId& id);
- bool substitute(Var v, Lit x); // Replace all occurences of v with x (may
+ bool substitute(Var v, Lit x); // Replace all occurrences of v with x (may
// cause a contradiction).
// Variable mode:
diff --git a/src/prop/cadical.cpp b/src/prop/cadical.cpp
index ca447cea8..7cc5b16cd 100644
--- a/src/prop/cadical.cpp
+++ b/src/prop/cadical.cpp
@@ -19,7 +19,6 @@
#ifdef CVC4_USE_CADICAL
#include "base/check.h"
-#include "proof/sat_proof.h"
namespace CVC4 {
namespace prop {
diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp
index a6a4b6859..c46cd5136 100644
--- a/src/prop/cnf_stream.cpp
+++ b/src/prop/cnf_stream.cpp
@@ -83,22 +83,13 @@ void CnfStream::assertClause(TNode node, SatClause& c) {
}
}
- 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)
- if (PROOF_ON() && d_cnfProof)
+ if (d_cnfProof && clause_id != ClauseIdError)
{
- if (clause_id != ClauseIdError)
- {
- d_cnfProof->registerConvertedClause(clause_id);
- }
- d_cnfProof->popCurrentDefinition();
- };
+ d_cnfProof->registerConvertedClause(clause_id);
+ }
}
void CnfStream::assertClause(TNode node, SatLiteral a) {
@@ -171,11 +162,17 @@ void TseitinCnfStream::ensureLiteral(TNode n, bool noPreregistration) {
// non-empty and that we are not associating a bogus assertion with the
// clause. This should be ok because we use the mapping back to assertions
// for clauses from input assertions only.
- PROOF(if (d_cnfProof) { d_cnfProof->pushCurrentAssertion(Node::null()); });
+ if (d_cnfProof)
+ {
+ d_cnfProof->pushCurrentAssertion(Node::null());
+ }
lit = toCNF(n, false);
- PROOF(if (d_cnfProof) { d_cnfProof->popCurrentAssertion(); });
+ if (d_cnfProof)
+ {
+ d_cnfProof->popCurrentAssertion();
+ }
// Store backward-mappings
// These may already exist
@@ -547,7 +544,6 @@ void TseitinCnfStream::convertAndAssertAnd(TNode node, bool negated) {
// If the node is a conjunction, we handle each conjunct separately
for(TNode::const_iterator conjunct = node.begin(), node_end = node.end();
conjunct != node_end; ++conjunct ) {
- PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence(*conjunct, node););
convertAndAssert(*conjunct, false);
}
} else {
@@ -581,7 +577,6 @@ void TseitinCnfStream::convertAndAssertOr(TNode node, bool negated) {
// If the node is a conjunction, we handle each conjunct separately
for(TNode::const_iterator conjunct = node.begin(), node_end = node.end();
conjunct != node_end; ++conjunct ) {
- PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence((*conjunct).negate(), node.negate()););
convertAndAssert(*conjunct, true);
}
}
@@ -658,8 +653,6 @@ void TseitinCnfStream::convertAndAssertImplies(TNode node, bool negated) {
clause[1] = q;
assertClause(node, clause);
} else {// Construct the
- PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence(node[0], node.negate()););
- PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence(node[1].negate(), node.negate()););
// !(p => q) is the same as (p && ~q)
convertAndAssert(node[0], false);
convertAndAssert(node[1], true);
@@ -693,32 +686,23 @@ void TseitinCnfStream::convertAndAssertIte(TNode node, bool negated) {
void TseitinCnfStream::convertAndAssert(TNode node,
bool removable,
bool negated,
- ProofRule proof_id,
- TNode from) {
+ bool input)
+{
Debug("cnf") << "convertAndAssert(" << node
<< ", removable = " << (removable ? "true" : "false")
<< ", negated = " << (negated ? "true" : "false") << ")" << endl;
d_removable = removable;
- PROOF
- (if (d_cnfProof) {
- Node assertion = negated ? node.notNode() : (Node)node;
- Node from_assertion = negated? from.notNode() : (Node) from;
-
- if (proof_id != RULE_INVALID) {
- d_cnfProof->pushCurrentAssertion(from.isNull() ? assertion : from_assertion);
- d_cnfProof->registerAssertion(from.isNull() ? assertion : from_assertion, proof_id);
- }
- else {
- d_cnfProof->pushCurrentAssertion(assertion);
- d_cnfProof->registerAssertion(assertion, proof_id);
- }
- });
+ if (d_cnfProof)
+ {
+ d_cnfProof->pushCurrentAssertion(negated ? node.notNode() : (Node)node,
+ input);
+ }
convertAndAssert(node, negated);
- PROOF
- (if (d_cnfProof) {
- d_cnfProof->popCurrentAssertion();
- });
+ if (d_cnfProof)
+ {
+ d_cnfProof->popCurrentAssertion();
+ }
}
void TseitinCnfStream::convertAndAssert(TNode node, bool negated) {
diff --git a/src/prop/cnf_stream.h b/src/prop/cnf_stream.h
index 40243e5b9..aec4257f2 100644
--- a/src/prop/cnf_stream.h
+++ b/src/prop/cnf_stream.h
@@ -186,10 +186,13 @@ class CnfStream {
* @param node node to convert and assert
* @param removable whether the sat solver can choose to remove the clauses
* @param negated whether we are asserting the node negated
+ * @param input whether it is an input assertion (rather than a lemma). This
+ * information is only relevant for unsat core tracking.
*/
- virtual void convertAndAssert(TNode node, bool removable, bool negated,
- ProofRule proof_id,
- TNode from = TNode::null()) = 0;
+ virtual void convertAndAssert(TNode node,
+ bool removable,
+ bool negated,
+ bool input = false) = 0;
/**
* Get the node that is represented by the given SatLiteral.
@@ -269,12 +272,13 @@ class TseitinCnfStream : public CnfStream {
* @param node the formula to assert
* @param removable is this something that can be erased
* @param negated true if negated
+ * @param input whether it is an input assertion (rather than a lemma). This
+ * information is only relevant for unsat core tracking.
*/
void convertAndAssert(TNode node,
bool removable,
bool negated,
- ProofRule rule,
- TNode from = TNode::null()) override;
+ bool input = false) override;
private:
/**
diff --git a/src/prop/cryptominisat.cpp b/src/prop/cryptominisat.cpp
index 9dc04c274..9927172be 100644
--- a/src/prop/cryptominisat.cpp
+++ b/src/prop/cryptominisat.cpp
@@ -19,8 +19,6 @@
#include "prop/cryptominisat.h"
#include "base/check.h"
-#include "proof/clause_id.h"
-#include "proof/sat_proof.h"
#include <cryptominisat5/cryptominisat.h>
@@ -86,8 +84,9 @@ void CryptoMinisatSolver::init()
CryptoMinisatSolver::~CryptoMinisatSolver() {}
ClauseId CryptoMinisatSolver::addXorClause(SatClause& clause,
- bool rhs,
- bool removable) {
+ bool rhs,
+ bool removable)
+{
Debug("sat::cryptominisat") << "Add xor clause " << clause <<" = " << rhs << "\n";
if (!d_okay) {
@@ -96,7 +95,7 @@ ClauseId CryptoMinisatSolver::addXorClause(SatClause& clause,
}
++(d_statistics.d_xorClausesAdded);
-
+
// ensure all sat literals have positive polarity by pushing
// the negation on the result
std::vector<CMSatVar> xor_clause;
@@ -118,36 +117,19 @@ ClauseId CryptoMinisatSolver::addClause(SatClause& clause, bool removable){
}
++(d_statistics.d_clausesAdded);
-
+
std::vector<CMSat::Lit> internal_clause;
toInternalClause(clause, internal_clause);
bool nowOkay = d_solver->add_clause(internal_clause);
ClauseId freshId;
- if (THEORY_PROOF_ON())
- {
- freshId = ClauseId(ProofManager::currentPM()->nextId());
- // 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);
- }
- }
- else
- {
- freshId = ClauseIdError;
- }
+ freshId = ClauseIdError;
d_okay &= nowOkay;
return freshId;
}
-bool CryptoMinisatSolver::ok() const {
- return d_okay;
-}
-
+bool CryptoMinisatSolver::ok() const { return d_okay; }
SatVariable CryptoMinisatSolver::newVar(bool isTheoryAtom, bool preRegister, bool canErase){
d_solver->new_var();
@@ -207,19 +189,11 @@ SatValue CryptoMinisatSolver::value(SatLiteral l){
return toSatLiteralValue(value);
}
-SatValue CryptoMinisatSolver::modelValue(SatLiteral l){
- return value(l);
-}
+SatValue CryptoMinisatSolver::modelValue(SatLiteral l) { return value(l); }
unsigned CryptoMinisatSolver::getAssertionLevel() const {
Unreachable() << "No interface to get assertion level in Cryptominisat";
- return -1;
-}
-
-void CryptoMinisatSolver::setClausalProofLog(proof::ClausalBitVectorProof* bvp)
-{
- d_bvp = bvp;
- d_solver->set_drat(&bvp->getDratOstream(), false);
+ return -1;
}
// Satistics for CryptoMinisatSolver
diff --git a/src/prop/cryptominisat.h b/src/prop/cryptominisat.h
index d60855654..6d3b351b0 100644
--- a/src/prop/cryptominisat.h
+++ b/src/prop/cryptominisat.h
@@ -21,7 +21,6 @@
#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
@@ -68,7 +67,6 @@ class CryptoMinisatSolver : public SatSolver
SatValue modelValue(SatLiteral l) override;
unsigned getAssertionLevel() const override;
- void setClausalProofLog(proof::ClausalBitVectorProof* bvp) override;
private:
class Statistics
@@ -97,7 +95,6 @@ class CryptoMinisatSolver : public SatSolver
void init();
std::unique_ptr<CMSat::SATSolver> d_solver;
- proof::ClausalBitVectorProof* d_bvp;
unsigned d_numVariables;
bool d_okay;
SatVariable d_true;
diff --git a/src/prop/kissat.cpp b/src/prop/kissat.cpp
index 0440fcd4e..544a37a3e 100644
--- a/src/prop/kissat.cpp
+++ b/src/prop/kissat.cpp
@@ -19,7 +19,6 @@
#ifdef CVC4_USE_KISSAT
#include "base/check.h"
-#include "proof/sat_proof.h"
namespace CVC4 {
namespace prop {
diff --git a/src/prop/minisat/core/Solver.cc b/src/prop/minisat/core/Solver.cc
index f56f6a447..311224a03 100644
--- a/src/prop/minisat/core/Solver.cc
+++ b/src/prop/minisat/core/Solver.cc
@@ -30,6 +30,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "options/prop_options.h"
#include "options/smt_options.h"
#include "proof/clause_id.h"
+#include "proof/cnf_proof.h"
#include "proof/proof_manager.h"
#include "proof/sat_proof.h"
#include "proof/sat_proof_implementation.h"
@@ -217,7 +218,10 @@ Solver::Solver(CVC4::prop::TheoryProxy* proxy,
propagation_budget(-1),
asynch_interrupt(false)
{
- PROOF(ProofManager::currentPM()->initSatProof(this);)
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->initSatProof(this);
+ }
// Create the constant variables
varTrue = newVar(true, false, false);
@@ -227,11 +231,11 @@ Solver::Solver(CVC4::prop::TheoryProxy* proxy,
uncheckedEnqueue(mkLit(varTrue, false));
uncheckedEnqueue(mkLit(varFalse, true));
// FIXME: these should be axioms I believe
- PROOF
- (
- ProofManager::getSatProof()->registerTrueLit(mkLit(varTrue, false));
- ProofManager::getSatProof()->registerFalseLit(mkLit(varFalse, true));
- );
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->registerTrueLit(mkLit(varTrue, false));
+ ProofManager::getSatProof()->registerFalseLit(mkLit(varFalse, true));
+ }
}
@@ -390,15 +394,20 @@ CRef Solver::reason(Var x) {
// FIXME: at some point will need more information about where this explanation
// came from (ie. the theory/sharing)
Debug("pf::sat") << "Minisat::Solver registering a THEORY_LEMMA (1)" << std::endl;
- PROOF(ClauseId id = ProofManager::getSatProof()->registerClause(
- real_reason, THEORY_LEMMA);
- ProofManager::getCnfProof()->registerConvertedClause(id, true);
- // explainPropagation() pushes the explanation on the assertion stack
- // in CnfProof, so we need to pop it here. This is important because
- // reason() may be called indirectly while adding a clause, which can
- // lead to a wrong assertion being associated with the clause being
- // added (see issue #2137).
- ProofManager::getCnfProof()->popCurrentAssertion(););
+ if (options::unsatCores())
+ {
+ ClauseId id = ProofManager::getSatProof()->registerClause(real_reason,
+ THEORY_LEMMA);
+ // map id to assertion, which may be required if looking for
+ // lemmas in unsat core
+ ProofManager::getCnfProof()->registerConvertedClause(id);
+ // explainPropagation() pushes the explanation on the assertion stack
+ // in CnfProof, so we need to pop it here. This is important because
+ // reason() may be called indirectly while adding a clause, which can
+ // lead to a wrong assertion being associated with the clause being
+ // added (see issue #2137).
+ ProofManager::getCnfProof()->popCurrentAssertion();
+ }
vardata[x] = VarData(real_reason, level(x), user_level(x), intro_level(x), trail_index(x));
clauses_removable.push(real_reason);
attachClause(real_reason);
@@ -441,9 +450,13 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
}
// If a literal is false at 0 level (both sat and user level) we also ignore it
if (value(ps[i]) == l_False) {
- if (!PROOF_ON() && level(var(ps[i])) == 0 && user_level(var(ps[i])) == 0) {
+ if (!options::unsatCores() && level(var(ps[i])) == 0
+ && user_level(var(ps[i])) == 0)
+ {
continue;
- } else {
+ }
+ else
+ {
// If we decide to keep it, we count it into the false literals
falseLiteralsCount ++;
}
@@ -467,34 +480,46 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
lemmas.push();
ps.copyTo(lemmas.last());
lemmas_removable.push(removable);
- PROOF(
- // Store the expression being converted to CNF until
- // the clause is actually created
- Node assertion = ProofManager::getCnfProof()->getCurrentAssertion();
- Node def = ProofManager::getCnfProof()->getCurrentDefinition();
- lemmas_cnf_assertion.push_back(std::make_pair(assertion, def));
- id = ClauseIdUndef;
- );
- // does it have to always be a lemma?
- // PROOF(id = ProofManager::getSatProof()->registerUnitClause(ps[0], THEORY_LEMMA););
- // PROOF(id = ProofManager::getSatProof()->registerTheoryLemma(ps););
- // Debug("cores") << "lemma push " << proof_id << " " << (proof_id & 0xffffffff) << std::endl;
- // lemmas_proof_id.push(proof_id);
+ if (options::unsatCores())
+ {
+ // Store the expression being converted to CNF until
+ // the clause is actually created
+ lemmas_cnf_assertion.push_back(
+ ProofManager::getCnfProof()->getCurrentAssertion());
+ id = ClauseIdUndef;
+ }
} else {
assert(decisionLevel() == 0);
// If all false, we're in conflict
if (ps.size() == falseLiteralsCount) {
- if(PROOF_ON()) {
+ if (options::unsatCores())
+ {
// Take care of false units here; otherwise, we need to
// construct the clause below to give to the proof manager
// as the final conflict.
if(falseLiteralsCount == 1) {
- PROOF( id = ProofManager::getSatProof()->storeUnitConflict(ps[0], INPUT); )
- PROOF( ProofManager::getSatProof()->finalizeProof(CVC4::Minisat::CRef_Lazy); )
+ if (options::unsatCores())
+ {
+ ClauseKind ck =
+ ProofManager::getCnfProof()->getCurrentAssertionKind()
+ ? INPUT
+ : THEORY_LEMMA;
+ id = ProofManager::getSatProof()->storeUnitConflict(ps[0], ck);
+ // map id to assertion, which may be required if looking for
+ // lemmas in unsat core
+ if (ck == THEORY_LEMMA)
+ {
+ ProofManager::getCnfProof()->registerConvertedClause(id);
+ }
+ ProofManager::getSatProof()->finalizeProof(
+ CVC4::Minisat::CRef_Lazy);
+ }
return ok = false;
}
- } else {
+ }
+ else
+ {
return ok = false;
}
}
@@ -509,14 +534,23 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
cr = ca.alloc(clauseLevel, ps, false);
clauses_persistent.push(cr);
- attachClause(cr);
-
- if(PROOF_ON()) {
- PROOF(
- id = ProofManager::getSatProof()->registerClause(cr, INPUT);
- )
- if(ps.size() == falseLiteralsCount) {
- PROOF( ProofManager::getSatProof()->finalizeProof(cr); )
+ attachClause(cr);
+
+ if (options::unsatCores())
+ {
+ ClauseKind ck = ProofManager::getCnfProof()->getCurrentAssertionKind()
+ ? INPUT
+ : THEORY_LEMMA;
+ id = ProofManager::getSatProof()->registerClause(cr, ck);
+ // map id to assertion, which may be required if looking for
+ // lemmas in unsat core
+ if (ck == THEORY_LEMMA)
+ {
+ ProofManager::getCnfProof()->registerConvertedClause(id);
+ }
+ if (ps.size() == falseLiteralsCount)
+ {
+ ProofManager::getSatProof()->finalizeProof(cr);
return ok = false;
}
}
@@ -527,15 +561,25 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
if(assigns[var(ps[0])] == l_Undef) {
assert(assigns[var(ps[0])] != l_False);
uncheckedEnqueue(ps[0], cr);
- Debug("cores") << "i'm registering a unit clause, input" << std::endl;
- PROOF(
- if(ps.size() == 1) {
- id = ProofManager::getSatProof()->registerUnitClause(ps[0], INPUT);
- }
- );
+ Debug("cores") << "i'm registering a unit clause, maybe input"
+ << std::endl;
+ if (options::unsatCores() && ps.size() == 1)
+ {
+ ClauseKind ck =
+ ProofManager::getCnfProof()->getCurrentAssertionKind()
+ ? INPUT
+ : THEORY_LEMMA;
+ id = ProofManager::getSatProof()->registerUnitClause(ps[0], ck);
+ // map id to assertion, which may be required if looking for
+ // lemmas in unsat core
+ if (ck == THEORY_LEMMA)
+ {
+ ProofManager::getCnfProof()->registerConvertedClause(id);
+ }
+ }
CRef confl = propagate(CHECK_WITHOUT_THEORY);
if(! (ok = (confl == CRef_Undef)) ) {
- if (PROOF_ON())
+ if (options::unsatCores())
{
if (ca[confl].size() == 1)
{
@@ -552,7 +596,10 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
}
return ok;
} else {
- PROOF(id = ClauseIdUndef;);
+ if (options::unsatCores())
+ {
+ id = ClauseIdUndef;
+ }
return ok;
}
}
@@ -575,7 +622,10 @@ void Solver::attachClause(CRef cr) {
void Solver::detachClause(CRef cr, bool strict) {
const Clause& c = ca[cr];
- PROOF( ProofManager::getSatProof()->markDeleted(cr); );
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->markDeleted(cr);
+ }
Debug("minisat") << "Solver::detachClause(" << c << ")" << std::endl;
assert(c.size() > 1);
@@ -826,7 +876,10 @@ int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
int max_resolution_level = 0; // Maximal level of the resolved clauses
- PROOF( ProofManager::getSatProof()->startResChain(confl); )
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->startResChain(confl);
+ }
do{
assert(confl != CRef_Undef); // (otherwise should be UIP)
@@ -867,9 +920,9 @@ int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
}
// FIXME: can we do it lazily if we actually need the proof?
- if (level(var(q)) == 0)
+ if (options::unsatCores() && level(var(q)) == 0)
{
- PROOF(ProofManager::getSatProof()->resolveOutUnit(q);)
+ ProofManager::getSatProof()->resolveOutUnit(q);
}
}
}
@@ -881,8 +934,9 @@ int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
seen[var(p)] = 0;
pathC--;
- if ( pathC > 0 && confl != CRef_Undef ) {
- PROOF( ProofManager::getSatProof()->addResolutionStep(p, confl, sign(p)); )
+ if (options::unsatCores() && pathC > 0 && confl != CRef_Undef)
+ {
+ ProofManager::getSatProof()->addResolutionStep(p, confl, sign(p));
}
}while (pathC > 0);
@@ -905,7 +959,10 @@ int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
// Literal is not redundant
out_learnt[j++] = out_learnt[i];
} else {
- PROOF( ProofManager::getSatProof()->storeLitRedundant(out_learnt[i]); )
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->storeLitRedundant(out_learnt[i]);
+ }
// Literal is redundant, to be safe, mark the level as current assertion level
// TODO: maybe optimize
max_resolution_level = std::max(max_resolution_level, user_level(var(out_learnt[i])));
@@ -1169,7 +1226,10 @@ void Solver::propagateTheory() {
addClause(explanation, true, id);
// explainPropagation() pushes the explanation on the assertion
// stack in CnfProof, so we need to pop it here.
- PROOF(ProofManager::getCnfProof()->popCurrentAssertion();)
+ if (options::unsatCores())
+ {
+ ProofManager::getCnfProof()->popCurrentAssertion();
+ }
}
}
}
@@ -1310,9 +1370,10 @@ void Solver::removeSatisfied(vec<CRef>& cs)
for (i = j = 0; i < cs.size(); i++){
Clause& c = ca[cs[i]];
if (satisfied(c)) {
- if (locked(c)) {
+ if (options::unsatCores() && locked(c))
+ {
// store a resolution of the literal c propagated
- PROOF( ProofManager::getSatProof()->storeUnitResolution(c[0]); )
+ ProofManager::getSatProof()->storeUnitResolution(c[0]);
}
removeClause(cs[i]);
}
@@ -1412,8 +1473,11 @@ lbool Solver::search(int nof_conflicts)
conflicts++; conflictC++;
if (decisionLevel() == 0) {
- PROOF( ProofManager::getSatProof()->finalizeProof(confl); )
- return l_False;
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->finalizeProof(confl);
+ }
+ return l_False;
}
// Analyze the conflict
@@ -1425,8 +1489,10 @@ lbool Solver::search(int nof_conflicts)
if (learnt_clause.size() == 1) {
uncheckedEnqueue(learnt_clause[0]);
- PROOF( ProofManager::getSatProof()->endResChain(learnt_clause[0]); )
-
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->endResChain(learnt_clause[0]);
+ }
} else {
CRef cr =
ca.alloc(assertionLevelOnly() ? assertionLevel : max_level,
@@ -1436,15 +1502,12 @@ lbool Solver::search(int nof_conflicts)
attachClause(cr);
claBumpActivity(ca[cr]);
uncheckedEnqueue(learnt_clause[0], cr);
- PROOF(ClauseId id =
- ProofManager::getSatProof()->registerClause(cr, LEARNT);
- PSTATS(std::unordered_set<int> cl_levels;
- for (int i = 0; i < learnt_clause.size(); ++i) {
- cl_levels.insert(level(var(learnt_clause[i])));
- } ProofManager::getSatProof()
- ->storeClauseGlue(id, cl_levels.size());)
- ProofManager::getSatProof()
- ->endResChain(id););
+ if (options::unsatCores())
+ {
+ ClauseId id =
+ ProofManager::getSatProof()->registerClause(cr, LEARNT);
+ ProofManager::getSatProof()->endResChain(id);
+ }
}
varDecayActivity();
@@ -1469,25 +1532,33 @@ lbool Solver::search(int nof_conflicts)
}
} else {
-
- // If this was a final check, we are satisfiable
- if (check_type == CHECK_FINAL) {
- bool decisionEngineDone = d_proxy->isDecisionEngineDone();
- // Unless a lemma has added more stuff to the queues
- if (!decisionEngineDone &&
- (!order_heap.empty() || qhead < trail.size()) ) {
- check_type = CHECK_WITH_THEORY;
- continue;
- } else if (recheck) {
- // There some additional stuff added, so we go for another full-check
- continue;
- } else {
- // Yes, we're truly satisfiable
- return l_True;
- }
- } else if (check_type == CHECK_FINAL_FAKE) {
+ // If this was a final check, we are satisfiable
+ if (check_type == CHECK_FINAL)
+ {
+ bool decisionEngineDone = d_proxy->isDecisionEngineDone();
+ // Unless a lemma has added more stuff to the queues
+ if (!decisionEngineDone
+ && (!order_heap.empty() || qhead < trail.size()))
+ {
check_type = CHECK_WITH_THEORY;
+ continue;
+ }
+ else if (recheck)
+ {
+ // There some additional stuff added, so we go for another
+ // full-check
+ continue;
}
+ else
+ {
+ // Yes, we're truly satisfiable
+ return l_True;
+ }
+ }
+ else if (check_type == CHECK_FINAL_FAKE)
+ {
+ check_type = CHECK_WITH_THEORY;
+ }
if ((nof_conflicts >= 0 && conflictC >= nof_conflicts)
|| !withinBudget(ResourceManager::Resource::SatConflictStep))
@@ -1744,7 +1815,10 @@ void Solver::relocAll(ClauseAllocator& to)
// printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
vec<Watcher>& ws = watches[p];
for (int j = 0; j < ws.size(); j++)
- ca.reloc(ws[j].cref, to, NULLPROOF(ProofManager::getSatProof()));
+ ca.reloc(ws[j].cref,
+ to,
+ CVC4::options::unsatCores() ? ProofManager::getSatProof()
+ : nullptr);
}
// All reasons:
@@ -1753,22 +1827,31 @@ void Solver::relocAll(ClauseAllocator& to)
Var v = var(trail[i]);
if (hasReasonClause(v) && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
- ca.reloc(
- vardata[v].d_reason, to, NULLPROOF(ProofManager::getSatProof()));
+ ca.reloc(vardata[v].d_reason,
+ to,
+ CVC4::options::unsatCores() ? ProofManager::getSatProof()
+ : nullptr);
}
// All learnt:
//
for (int i = 0; i < clauses_removable.size(); i++)
ca.reloc(
- clauses_removable[i], to, NULLPROOF(ProofManager::getSatProof()));
+ clauses_removable[i],
+ to,
+ CVC4::options::unsatCores() ? ProofManager::getSatProof() : nullptr);
// All original:
//
for (int i = 0; i < clauses_persistent.size(); i++)
ca.reloc(
- clauses_persistent[i], to, NULLPROOF(ProofManager::getSatProof()));
+ clauses_persistent[i],
+ to,
+ CVC4::options::unsatCores() ? ProofManager::getSatProof() : nullptr);
- PROOF(ProofManager::getSatProof()->finishUpdateCRef();)
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->finishUpdateCRef();
+ }
}
@@ -1874,7 +1957,7 @@ CRef Solver::updateLemmas() {
// If it's an empty lemma, we have a conflict at zero level
if (lemma.size() == 0) {
- Assert(!PROOF_ON());
+ Assert(!options::unsatCores());
conflict = CRef_Lazy;
backtrackLevel = 0;
Debug("minisat::lemmas") << "Solver::updateLemmas(): found empty clause" << std::endl;
@@ -1904,7 +1987,8 @@ CRef Solver::updateLemmas() {
// Last index in the trail
int backtrack_index = trail.size();
- PROOF(Assert(lemmas.size() == (int)lemmas_cnf_assertion.size()););
+ Assert(!options::unsatCores()
+ || lemmas.size() == (int)lemmas_cnf_assertion.size());
// Attach all the clauses and enqueue all the propagations
for (int j = 0; j < lemmas.size(); ++j)
@@ -1928,15 +2012,16 @@ CRef Solver::updateLemmas() {
}
lemma_ref = ca.alloc(clauseLevel, lemma, removable);
- PROOF(TNode cnf_assertion = lemmas_cnf_assertion[j].first;
- TNode cnf_def = lemmas_cnf_assertion[j].second;
-
- Debug("pf::sat")
- << "Minisat::Solver registering a THEORY_LEMMA (2)" << std::endl;
- ClauseId id = ProofManager::getSatProof()->registerClause(
- lemma_ref, THEORY_LEMMA);
- ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion);
- ProofManager::getCnfProof()->setClauseDefinition(id, cnf_def););
+ if (options::unsatCores())
+ {
+ TNode cnf_assertion = lemmas_cnf_assertion[j];
+
+ Debug("pf::sat") << "Minisat::Solver registering a THEORY_LEMMA (2)"
+ << std::endl;
+ ClauseId id = ProofManager::getSatProof()->registerClause(lemma_ref,
+ THEORY_LEMMA);
+ ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion);
+ }
if (removable) {
clauses_removable.push(lemma_ref);
} else {
@@ -1948,17 +2033,15 @@ CRef Solver::updateLemmas() {
// If the lemma is propagating enqueue its literal (or set the conflict)
if (conflict == CRef_Undef && value(lemma[0]) != l_True) {
if (lemma.size() == 1 || (value(lemma[1]) == l_False && trail_index(var(lemma[1])) < backtrack_index)) {
- if (PROOF_ON() && lemma.size() == 1)
+ if (options::unsatCores() && lemma.size() == 1)
{
- Node cnf_assertion = lemmas_cnf_assertion[j].first;
- Node cnf_def = lemmas_cnf_assertion[j].second;
+ Node cnf_assertion = lemmas_cnf_assertion[j];
Debug("pf::sat") << "Minisat::Solver registering a THEORY_LEMMA (3) "
<< cnf_assertion << value(lemma[0]) << std::endl;
ClauseId id = ProofManager::getSatProof()->registerUnitClause(
lemma[0], THEORY_LEMMA);
ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion);
- ProofManager::getCnfProof()->setClauseDefinition(id, cnf_def);
}
if (value(lemma[0]) == l_False) {
@@ -1969,7 +2052,10 @@ CRef Solver::updateLemmas() {
} else {
Debug("minisat::lemmas") << "Solver::updateLemmas(): unit conflict or empty clause" << std::endl;
conflict = CRef_Lazy;
- PROOF( ProofManager::getSatProof()->storeUnitConflict(lemma[0], LEARNT); );
+ if (options::unsatCores())
+ {
+ ProofManager::getSatProof()->storeUnitConflict(lemma[0], LEARNT);
+ }
}
} else {
Debug("minisat::lemmas") << "lemma size is " << lemma.size() << std::endl;
@@ -1979,7 +2065,8 @@ CRef Solver::updateLemmas() {
}
}
- PROOF(Assert(lemmas.size() == (int)lemmas_cnf_assertion.size()););
+ Assert(!options::unsatCores()
+ || lemmas.size() == (int)lemmas_cnf_assertion.size());
// Clear the lemmas
lemmas.clear();
lemmas_cnf_assertion.clear();
diff --git a/src/prop/minisat/core/Solver.h b/src/prop/minisat/core/Solver.h
index 508947456..a5f3664e8 100644
--- a/src/prop/minisat/core/Solver.h
+++ b/src/prop/minisat/core/Solver.h
@@ -63,7 +63,7 @@ public:
typedef Var TVar;
typedef Lit TLit;
- typedef Clause TClause;
+ typedef Clause TClause;
typedef CRef TCRef;
typedef vec<Lit> TLitVec;
@@ -98,7 +98,7 @@ public:
vec<bool> lemmas_removable;
/** Nodes being converted to CNF */
- std::vector<std::pair<CVC4::Node, CVC4::Node> > lemmas_cnf_assertion;
+ std::vector<CVC4::Node> lemmas_cnf_assertion;
/** Do a another check if FULL_EFFORT was the last one */
bool recheck;
@@ -203,7 +203,7 @@ public:
lbool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions.
bool okay () const; // FALSE means solver is in a conflicting state
- void toDimacs ();
+ void toDimacs();
void toDimacs (FILE* f, const vec<Lit>& assumps); // Write CNF to file in DIMACS-format.
void toDimacs (const char *file, const vec<Lit>& assumps);
void toDimacs (FILE* f, Clause& c, vec<Var>& map, Var& max);
diff --git a/src/prop/minisat/core/SolverTypes.h b/src/prop/minisat/core/SolverTypes.h
index bbd6e17a2..b30d97aee 100644
--- a/src/prop/minisat/core/SolverTypes.h
+++ b/src/prop/minisat/core/SolverTypes.h
@@ -73,9 +73,14 @@ inline bool sign (Lit p) { return p.x & 1; }
inline int var (Lit p) { return p.x >> 1; }
// Mapping Literals to and from compact integers suitable for array indexing:
-inline int toInt (Var v) { return v; }
-inline int toInt (Lit p) { return p.x; }
-inline Lit toLit (int i) { Lit p; p.x = i; return p; }
+inline int toInt(Var v) { return v; }
+inline int toInt(Lit p) { return p.x; }
+inline Lit toLit(int i)
+{
+ Lit p;
+ p.x = i;
+ return p;
+}
//const Lit lit_Undef = mkLit(var_Undef, false); // }- Useful special constants.
//const Lit lit_Error = mkLit(var_Undef, true ); // }
@@ -83,20 +88,19 @@ inline Lit toLit (int i) { Lit p; p.x = i; return p; }
const Lit lit_Undef = { -2 }; // }- Useful special constants.
const Lit lit_Error = { -1 }; // }
-
//=================================================================================================
// Lifted booleans:
//
-// NOTE: this implementation is optimized for the case when comparisons between values are mostly
-// between one variable and one constant. Some care had to be taken to make sure that gcc
-// does enough constant propagation to produce sensible code, and this appears to be somewhat
-// fragile unfortunately.
+// NOTE: this implementation is optimized for the case when comparisons between
+// values are mostly
+// between one variable and one constant. Some care had to be taken to
+// make sure that gcc does enough constant propagation to produce sensible
+// code, and this appears to be somewhat fragile unfortunately.
/*
- This is to avoid multiple definitions of l_True, l_False and l_Undef if using multiple copies of
- Minisat.
- IMPORTANT: if we you change the value of the constants so that it is not the same in all copies
- of Minisat this breaks!
+ This is to avoid multiple definitions of l_True, l_False and l_Undef if using
+ multiple copies of Minisat. IMPORTANT: if we you change the value of the
+ constants so that it is not the same in all copies of Minisat this breaks!
*/
#ifndef l_True
@@ -124,10 +128,12 @@ public:
bool operator != (lbool b) const { return !(*this == b); }
lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); }
- lbool operator && (lbool b) const {
- uint8_t sel = (this->value << 1) | (b.value << 3);
- uint8_t v = (0xF7F755F4 >> sel) & 3;
- return lbool(v); }
+ lbool operator&&(lbool b) const
+ {
+ uint8_t sel = (this->value << 1) | (b.value << 3);
+ uint8_t v = (0xF7F755F4 >> sel) & 3;
+ return lbool(v);
+ }
lbool operator || (lbool b) const {
uint8_t sel = (this->value << 1) | (b.value << 3);
@@ -163,7 +169,7 @@ inline std::ostream& operator <<(std::ostream& out, Minisat::vec<Minisat::Lit>&
}
inline std::ostream& operator <<(std::ostream& out, Minisat::lbool val) {
- std::string val_str;
+ std::string val_str;
if( val == l_False ) {
val_str = "0";
} else if (val == l_True ) {
@@ -208,14 +214,14 @@ class Clause {
header.size = ps.size();
header.level = level;
- for (int i = 0; i < ps.size(); i++)
- data[i].lit = ps[i];
+ for (int i = 0; i < ps.size(); i++) data[i].lit = ps[i];
if (header.has_extra){
if (header.removable)
- data[header.size].act = 0;
- else
- calcAbstraction(); }
+ data[header.size].act = 0;
+ else
+ calcAbstraction();
+ }
}
public:
@@ -321,7 +327,7 @@ class OccLists
public:
OccLists(const Deleted& d) : deleted(d) {}
-
+
void init (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); }
void resizeTo (const Idx& idx);
// Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
@@ -394,13 +400,12 @@ class CMap
typedef Map<CRef, T, CRefHash> HashTable;
HashTable map;
-
+
public:
// Size-operations:
void clear () { map.clear(); }
int size () const { return map.elems(); }
-
// Insert/Remove/Test mapping:
void insert (CRef cr, const T& t){ map.insert(cr, t); }
void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility
@@ -423,15 +428,14 @@ class CMap
printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); }
};
-
/*_________________________________________________________________________________________________
|
| subsumes : (other : const Clause&) -> Lit
-|
+|
| Description:
-| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other'
-| by subsumption resolution.
-|
+| Checks if clause subsumes 'other', and at the same time, if it can be
+used to simplify 'other' | by subsumption resolution.
+|
| Result:
| lit_Error - No subsumption or simplification
| lit_Undef - Clause subsumes 'other'
diff --git a/src/prop/minisat/minisat.cpp b/src/prop/minisat/minisat.cpp
index a4d2dce8a..25353e416 100644
--- a/src/prop/minisat/minisat.cpp
+++ b/src/prop/minisat/minisat.cpp
@@ -154,7 +154,7 @@ ClauseId MinisatSatSolver::addClause(SatClause& clause, bool removable) {
return ClauseIdUndef;
}
d_minisat->addClause(minisat_clause, removable, clause_id);
- PROOF(Assert(clause_id != ClauseIdError););
+ Assert(!CVC4::options::unsatCores() || clause_id != ClauseIdError);
return clause_id;
}
diff --git a/src/prop/minisat/simp/SimpSolver.cc b/src/prop/minisat/simp/SimpSolver.cc
index a101a0c2d..0ec8981ca 100644
--- a/src/prop/minisat/simp/SimpSolver.cc
+++ b/src/prop/minisat/simp/SimpSolver.cc
@@ -21,8 +21,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "prop/minisat/simp/SimpSolver.h"
#include "options/prop_options.h"
+#include "options/smt_options.h"
#include "proof/clause_id.h"
-#include "proof/proof.h"
#include "prop/minisat/mtl/Sort.h"
#include "prop/minisat/utils/System.h"
@@ -47,25 +47,30 @@ static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of
//=================================================================================================
// Constructor/Destructor:
-
-SimpSolver::SimpSolver(CVC4::prop::TheoryProxy* proxy, CVC4::context::Context* context, bool enableIncremental) :
- Solver(proxy, context, enableIncremental)
- , grow (opt_grow)
- , clause_lim (opt_clause_lim)
- , subsumption_lim (opt_subsumption_lim)
- , simp_garbage_frac (opt_simp_garbage_frac)
- , use_asymm (opt_use_asymm)
- , use_rcheck (opt_use_rcheck)
- , use_elim (options::minisatUseElim() && !enableIncremental)
- , merges (0)
- , asymm_lits (0)
- , eliminated_vars (0)
- , elimorder (1)
- , use_simplification (!enableIncremental && !PROOF_ON()) // TODO: turn off simplifications if proofs are on initially
- , occurs (ClauseDeleted(ca))
- , elim_heap (ElimLt(n_occ))
- , bwdsub_assigns (0)
- , n_touched (0)
+SimpSolver::SimpSolver(CVC4::prop::TheoryProxy* proxy,
+ CVC4::context::Context* context,
+ bool enableIncremental)
+ : Solver(proxy, context, enableIncremental),
+ grow(opt_grow),
+ clause_lim(opt_clause_lim),
+ subsumption_lim(opt_subsumption_lim),
+ simp_garbage_frac(opt_simp_garbage_frac),
+ use_asymm(opt_use_asymm),
+ use_rcheck(opt_use_rcheck),
+ use_elim(options::minisatUseElim() && !enableIncremental),
+ merges(0),
+ asymm_lits(0),
+ eliminated_vars(0),
+ elimorder(1),
+ use_simplification(
+ !enableIncremental
+ && !options::unsatCores()) // TODO: turn off simplifications if
+ // proofs are on initially
+ ,
+ occurs(ClauseDeleted(ca)),
+ elim_heap(ElimLt(n_occ)),
+ bwdsub_assigns(0),
+ n_touched(0)
{
if(options::minisatUseElim() &&
options::minisatUseElim.wasSetByUser() &&
@@ -117,8 +122,8 @@ Var SimpSolver::newVar(bool sign, bool dvar, bool isTheoryAtom, bool preRegister
lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
{
if (options::minisatDumpDimacs()) {
- toDimacs();
- return l_Undef;
+ toDimacs();
+ return l_Undef;
}
assert(decisionLevel() == 0);
@@ -525,7 +530,7 @@ bool SimpSolver::eliminateVar(Var v)
for (int i = 0; i < cls.size(); i++)
(find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]);
- // Check wether the increase in number of clauses stays within the allowed ('grow'). Moreover, no
+ // Check whether the increase in number of clauses stays within the allowed ('grow'). Moreover, no
// clause must exceed the limit on the maximal clause size (if it is set):
//
int cnt = 0;
@@ -533,9 +538,10 @@ bool SimpSolver::eliminateVar(Var v)
for (int i = 0; i < pos.size(); i++)
for (int j = 0; j < neg.size(); j++)
- if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) &&
- (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim)))
- return true;
+ if (merge(ca[pos[i]], ca[neg[j]], v, clause_size)
+ && (++cnt > cls.size() + grow
+ || (clause_lim != -1 && clause_size > clause_lim)))
+ return true;
// Delete and store old clauses:
eliminated[v] = true;
@@ -552,10 +558,9 @@ bool SimpSolver::eliminateVar(Var v)
mkElimClause(elimclauses, ~mkLit(v));
}
- for (int i = 0; i < cls.size(); i++)
- removeClause(cls[i]);
+ for (int i = 0; i < cls.size(); i++) removeClause(cls[i]);
- ClauseId id = ClauseIdUndef;
+ ClauseId id = ClauseIdUndef;
// Produce clauses in cross product:
vec<Lit>& resolvent = add_tmp;
for (int i = 0; i < pos.size(); i++)
@@ -569,7 +574,7 @@ bool SimpSolver::eliminateVar(Var v)
// Free occurs list for this variable:
occurs[v].clear(true);
-
+
// Free watchers lists for this variable, if possible:
if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true);
if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true);
@@ -589,7 +594,7 @@ bool SimpSolver::substitute(Var v, Lit x)
eliminated[v] = true;
setDecisionVar(v, false);
const vec<CRef>& cls = occurs.lookup(v);
-
+
vec<Lit>& subst_clause = add_tmp;
for (int i = 0; i < cls.size(); i++){
Clause& c = ca[cls[i]];
@@ -641,9 +646,12 @@ bool SimpSolver::eliminate(bool turn_off_elim)
gatherTouchedClauses();
// printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns);
- if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) &&
- !backwardSubsumptionCheck(true)){
- ok = false; goto cleanup; }
+ if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size())
+ && !backwardSubsumptionCheck(true))
+ {
+ ok = false;
+ goto cleanup;
+ }
// Empty elim_heap and return immediately on user-interrupt:
if (asynch_interrupt){
@@ -656,7 +664,7 @@ bool SimpSolver::eliminate(bool turn_off_elim)
// printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size());
for (int cnt = 0; !elim_heap.empty(); cnt++){
Var elim = elim_heap.removeMin();
-
+
if (asynch_interrupt) break;
if (isEliminated(elim) || value(elim) != l_Undef) continue;
@@ -706,8 +714,10 @@ bool SimpSolver::eliminate(bool turn_off_elim)
}
if (verbosity >= 1 && elimclauses.size() > 0)
- printf("| Eliminated clauses: %10.2f Mb |\n",
- double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024));
+ printf(
+ "| Eliminated clauses: %10.2f Mb "
+ " |\n",
+ double(elimclauses.size() * sizeof(uint32_t)) / (1024 * 1024));
return ok;
}
@@ -744,11 +754,11 @@ void SimpSolver::relocAll(ClauseAllocator& to)
//
for (int i = 0; i < subsumption_queue.size(); i++)
ca.reloc(subsumption_queue[i], to);
- // TODO reloc now takes the proof form the core solver
+ // TODO reloc now takes the proof form the core solver
// Temporary clause:
//
ca.reloc(bwdsub_tmpunit, to);
- // TODO reloc now takes the proof form the core solver
+ // TODO reloc now takes the proof form the core solver
}
@@ -756,15 +766,17 @@ void SimpSolver::garbageCollect()
{
// Initialize the next region to a size corresponding to the estimated utilization degree. This
// is not precise but should avoid some unnecessary reallocations for the new region:
- ClauseAllocator to(ca.size() - ca.wasted());
+ ClauseAllocator to(ca.size() - ca.wasted());
cleanUpClauses();
to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields.
relocAll(to);
Solver::relocAll(to);
if (verbosity >= 2)
- printf("| Garbage collection: %12d bytes => %12d bytes |\n",
- ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
+ printf(
+ "| Garbage collection: %12d bytes => %12d bytes |\n",
+ ca.size() * ClauseAllocator::Unit_Size,
+ to.size() * ClauseAllocator::Unit_Size);
to.moveTo(ca);
- // TODO: proof.finalizeUpdateId();
+ // TODO: proof.finalizeUpdateId();
}
diff --git a/src/prop/minisat/simp/SimpSolver.h b/src/prop/minisat/simp/SimpSolver.h
index 335075f09..c13ee5583 100644
--- a/src/prop/minisat/simp/SimpSolver.h
+++ b/src/prop/minisat/simp/SimpSolver.h
@@ -55,7 +55,7 @@ class SimpSolver : public Solver {
bool addClause (Lit p, Lit q, bool removable, ClauseId& id); // Add a binary clause to the solver.
bool addClause (Lit p, Lit q, Lit r, bool removable, ClauseId& id); // Add a ternary clause to the solver.
bool addClause_(vec<Lit>& ps, bool removable, ClauseId& id);
- bool substitute(Var v, Lit x); // Replace all occurences of v with x (may cause a contradiction).
+ bool substitute(Var v, Lit x); // Replace all occurrences of v with x (may cause a contradiction).
// Variable mode:
//
diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp
index f74e52509..e71e681e5 100644
--- a/src/prop/prop_engine.cpp
+++ b/src/prop/prop_engine.cpp
@@ -99,17 +99,17 @@ PropEngine::PropEngine(TheoryEngine* te,
d_decisionEngine->setSatSolver(d_satSolver);
d_decisionEngine->setCnfStream(d_cnfStream);
- PROOF (
- ProofManager::currentPM()->initCnfProof(d_cnfStream, userContext);
- );
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->initCnfProof(d_cnfStream, userContext);
+ }
}
void PropEngine::finishInit()
{
NodeManager* nm = NodeManager::currentNM();
- d_cnfStream->convertAndAssert(nm->mkConst(true), false, false, RULE_GIVEN);
- d_cnfStream->convertAndAssert(
- nm->mkConst(false).notNode(), false, false, RULE_GIVEN);
+ d_cnfStream->convertAndAssert(nm->mkConst(true), false, false);
+ d_cnfStream->convertAndAssert(nm->mkConst(false).notNode(), false, false);
}
PropEngine::~PropEngine() {
@@ -126,18 +126,15 @@ void PropEngine::assertFormula(TNode node) {
Assert(!d_inCheckSat) << "Sat solver in solve()!";
Debug("prop") << "assertFormula(" << node << ")" << endl;
// Assert as non-removable
- d_cnfStream->convertAndAssert(node, false, false, RULE_GIVEN);
+ d_cnfStream->convertAndAssert(node, false, false, true);
}
-void PropEngine::assertLemma(TNode node, bool negated,
- bool removable,
- ProofRule rule,
- TNode from) {
- //Assert(d_inCheckSat, "Sat solver should be in solve()!");
+void PropEngine::assertLemma(TNode node, bool negated, bool removable)
+{
Debug("prop::lemmas") << "assertLemma(" << node << ")" << endl;
// Assert as (possibly) removable
- d_cnfStream->convertAndAssert(node, removable, negated, rule, from);
+ d_cnfStream->convertAndAssert(node, removable, negated);
}
void PropEngine::addAssertionsToDecisionEngine(
diff --git a/src/prop/prop_engine.h b/src/prop/prop_engine.h
index 9a2daee49..1df862568 100644
--- a/src/prop/prop_engine.h
+++ b/src/prop/prop_engine.h
@@ -103,11 +103,7 @@ class PropEngine
* @param removable whether this lemma can be quietly removed based
* on an activity heuristic (or not)
*/
- void assertLemma(TNode node,
- bool negated,
- bool removable,
- ProofRule rule,
- TNode from = TNode::null());
+ void assertLemma(TNode node, bool negated, bool removable);
/**
* Pass a list of assertions from an AssertionPipeline to the decision engine.
diff --git a/src/prop/sat_solver.h b/src/prop/sat_solver.h
index d4b08ab71..1526e91b9 100644
--- a/src/prop/sat_solver.h
+++ b/src/prop/sat_solver.h
@@ -33,11 +33,6 @@
namespace CVC4 {
-namespace proof {
-class ClausalBitVectorProof;
-class ResolutionBitVectorProof;
-} // namespace proof
-
namespace prop {
class TheoryProxy;
@@ -58,7 +53,7 @@ public:
/** Add a clause corresponding to rhs = l1 xor .. xor ln */
virtual ClauseId addXorClause(SatClause& clause, bool rhs, bool removable) = 0;
-
+
/**
* Create a new boolean variable in the solver.
* @param isTheoryAtom is this a theory atom that needs to be asserted to theory
@@ -84,6 +79,7 @@ public:
virtual SatValue solve(const std::vector<SatLiteral>& assumptions)
{
Unimplemented() << "Solving under assumptions not implemented";
+ return SAT_VALUE_UNKNOWN;
};
/** Interrupt the solver */
@@ -101,10 +97,6 @@ public:
/** Check if the solver is in an inconsistent state */
virtual bool ok() const = 0;
- virtual void setResolutionProofLog(proof::ResolutionBitVectorProof* bvp) {}
-
- virtual void setClausalProofLog(proof::ClausalBitVectorProof* drat_proof) {}
-
};/* class SatSolver */
diff --git a/src/prop/theory_proxy.cpp b/src/prop/theory_proxy.cpp
index 41da4546e..d0ba4ca71 100644
--- a/src/prop/theory_proxy.cpp
+++ b/src/prop/theory_proxy.cpp
@@ -76,22 +76,12 @@ void TheoryProxy::explainPropagation(SatLiteral l, SatClause& explanation) {
TNode lNode = d_cnfStream->getNode(l);
Debug("prop-explain") << "explainPropagation(" << lNode << ")" << std::endl;
- LemmaProofRecipe* proofRecipe = NULL;
- PROOF(proofRecipe = new LemmaProofRecipe;);
+ Node theoryExplanation = d_theoryEngine->getExplanation(lNode);
- Node theoryExplanation = d_theoryEngine->getExplanationAndRecipe(lNode, proofRecipe);
-
- PROOF({
- ProofManager::getCnfProof()->pushCurrentAssertion(theoryExplanation);
- ProofManager::getCnfProof()->setProofRecipe(proofRecipe);
-
- Debug("pf::sat") << "TheoryProxy::explainPropagation: setting lemma recipe to: "
- << std::endl;
- proofRecipe->dump("pf::sat");
-
- delete proofRecipe;
- proofRecipe = NULL;
- });
+ if (options::unsatCores())
+ {
+ ProofManager::getCnfProof()->pushCurrentAssertion(theoryExplanation);
+ }
Debug("prop-explain") << "explainPropagation() => " << theoryExplanation << std::endl;
if (theoryExplanation.getKind() == kind::AND) {
diff --git a/src/smt/assertions.cpp b/src/smt/assertions.cpp
index ea3acf2d1..8019c383d 100644
--- a/src/smt/assertions.cpp
+++ b/src/smt/assertions.cpp
@@ -17,7 +17,6 @@
#include "expr/node_algorithm.h"
#include "options/base_options.h"
#include "options/language.h"
-#include "options/proof_options.h"
#include "options/smt_options.h"
#include "proof/proof_manager.h"
#include "smt/smt_engine.h"
@@ -179,18 +178,23 @@ void Assertions::addFormula(
}
// Give it to proof manager
- PROOF(if (inInput) {
- // n is an input assertion
- if (inUnsatCore || options::unsatCores() || options::dumpUnsatCores()
- || options::checkUnsatCores() || options::fewerPreprocessingHoles())
+ if (options::unsatCores())
+ {
+ if (inInput)
+ { // n is an input assertion
+ if (inUnsatCore || options::unsatCores() || options::dumpUnsatCores()
+ || options::checkUnsatCores())
+ {
+ ProofManager::currentPM()->addCoreAssertion(n.toExpr());
+ }
+ }
+ else
{
- ProofManager::currentPM()->addCoreAssertion(n.toExpr());
+ // n is the result of an unknown preprocessing step, add it to dependency
+ // map to null
+ ProofManager::currentPM()->addDependence(n, Node::null());
}
- } else {
- // n is the result of an unknown preprocessing step, add it to dependency
- // map to null
- ProofManager::currentPM()->addDependence(n, Node::null());
- });
+ }
// Add the normalized formula to the queue
d_assertions.push_back(n, isAssumption);
diff --git a/src/smt/assertions.h b/src/smt/assertions.h
index c2a16db71..a74c58bd8 100644
--- a/src/smt/assertions.h
+++ b/src/smt/assertions.h
@@ -122,7 +122,8 @@ class Assertions
* formula might be pushed out to the propositional layer
* immediately, or it might be simplified and kept, or it might not
* even be simplified.
- * The arguments isInput and isAssumption are used for bookkeeping for proofs.
+ * The arguments isInput and isAssumption are used for bookkeeping for unsat
+ * cores.
* The argument maybeHasFv should be set to true if the assertion may have
* free variables. By construction, assertions from the smt2 parser are
* guaranteed not to have free variables. However, other cases such as
diff --git a/src/smt/command.cpp b/src/smt/command.cpp
index 88f04f885..cb95cf348 100644
--- a/src/smt/command.cpp
+++ b/src/smt/command.cpp
@@ -2275,57 +2275,22 @@ void BlockModelValuesCommand::toStream(std::ostream& out,
/* class GetProofCommand */
/* -------------------------------------------------------------------------- */
-GetProofCommand::GetProofCommand() : d_smtEngine(nullptr), d_result(nullptr) {}
+GetProofCommand::GetProofCommand() {}
void GetProofCommand::invoke(SmtEngine* smtEngine)
{
- try
- {
- d_smtEngine = smtEngine;
- d_result = &smtEngine->getProof();
- d_commandStatus = CommandSuccess::instance();
- }
- catch (RecoverableModalException& e)
- {
- d_commandStatus = new CommandRecoverableFailure(e.what());
- }
- catch (UnsafeInterruptException& e)
- {
- d_commandStatus = new CommandInterrupted();
- }
- catch (exception& e)
- {
- d_commandStatus = new CommandFailure(e.what());
- }
-}
-
-const Proof& GetProofCommand::getResult() const { return *d_result; }
-void GetProofCommand::printResult(std::ostream& out, uint32_t verbosity) const
-{
- if (!ok())
- {
- this->Command::printResult(out, verbosity);
- }
- else
- {
- smt::SmtScope scope(d_smtEngine);
- d_result->toStream(out);
- }
+ Unimplemented() << "Unimplemented get-proof\n";
}
Command* GetProofCommand::exportTo(ExprManager* exprManager,
ExprManagerMapCollection& variableMap)
{
GetProofCommand* c = new GetProofCommand();
- c->d_result = d_result;
- c->d_smtEngine = d_smtEngine;
return c;
}
Command* GetProofCommand::clone() const
{
GetProofCommand* c = new GetProofCommand();
- c->d_result = d_result;
- c->d_smtEngine = d_smtEngine;
return c;
}
diff --git a/src/smt/command.h b/src/smt/command.h
index a0e591269..9fbd1bf73 100644
--- a/src/smt/command.h
+++ b/src/smt/command.h
@@ -33,7 +33,6 @@
#include "expr/type.h"
#include "expr/variable_type_map.h"
#include "proof/unsat_core.h"
-#include "util/proof.h"
#include "util/result.h"
#include "util/sexpr.h"
@@ -1131,9 +1130,7 @@ class CVC4_PUBLIC GetProofCommand : public Command
public:
GetProofCommand();
- const Proof& getResult() const;
void invoke(SmtEngine* smtEngine) override;
- void printResult(std::ostream& out, uint32_t verbosity = 2) const override;
Command* exportTo(ExprManager* exprManager,
ExprManagerMapCollection& variableMap) override;
Command* clone() const override;
@@ -1144,11 +1141,6 @@ class CVC4_PUBLIC GetProofCommand : public Command
bool types = false,
size_t dag = 1,
OutputLanguage language = language::output::LANG_AUTO) const override;
-
- protected:
- SmtEngine* d_smtEngine;
- // d_result is owned by d_smtEngine.
- const Proof* d_result;
}; /* class GetProofCommand */
class CVC4_PUBLIC GetInstantiationsCommand : public Command
diff --git a/src/smt/dump.h b/src/smt/dump.h
index 050935422..4c0efeb6e 100644
--- a/src/smt/dump.h
+++ b/src/smt/dump.h
@@ -21,6 +21,7 @@
#include "base/output.h"
#include "smt/command.h"
+#include "smt/node_command.h"
namespace CVC4 {
@@ -40,6 +41,20 @@ class CVC4_PUBLIC CVC4dumpstream
return *this;
}
+ /** A convenience function for dumping internal commands.
+ *
+ * Since Commands are now part of the public API, internal code should use
+ * NodeCommands and this function (instead of the one above) to dump them.
+ */
+ CVC4dumpstream& operator<<(const NodeCommand& nc)
+ {
+ if (d_os != nullptr)
+ {
+ (*d_os) << nc << std::endl;
+ }
+ return *this;
+ }
+
private:
std::ostream* d_os;
}; /* class CVC4dumpstream */
@@ -56,6 +71,7 @@ class CVC4_PUBLIC CVC4dumpstream
CVC4dumpstream() {}
CVC4dumpstream(std::ostream& os) {}
CVC4dumpstream& operator<<(const Command& c) { return *this; }
+ CVC4dumpstream& operator<<(const NodeCommand& nc) { return *this; }
}; /* class CVC4dumpstream */
#endif /* CVC4_DUMPING && !CVC4_MUZZLE */
diff --git a/src/smt/dump_manager.cpp b/src/smt/dump_manager.cpp
index d5fd65c4c..033be405f 100644
--- a/src/smt/dump_manager.cpp
+++ b/src/smt/dump_manager.cpp
@@ -51,7 +51,7 @@ void DumpManager::finishInit()
void DumpManager::resetAssertions() { d_modelGlobalCommands.clear(); }
-void DumpManager::addToModelCommandAndDump(const Command& c,
+void DumpManager::addToModelCommandAndDump(const NodeCommand& c,
uint32_t flags,
bool userVisible,
const char* dumpTag)
@@ -70,14 +70,14 @@ void DumpManager::addToModelCommandAndDump(const Command& c,
{
if (flags & ExprManager::VAR_FLAG_GLOBAL)
{
- d_modelGlobalCommands.push_back(std::unique_ptr<Command>(c.clone()));
+ d_modelGlobalCommands.push_back(std::unique_ptr<NodeCommand>(c.clone()));
}
else
{
- Command* cc = c.clone();
+ NodeCommand* cc = c.clone();
d_modelCommands.push_back(cc);
// also remember for memory management purposes
- d_modelCommandsAlloc.push_back(std::unique_ptr<Command>(cc));
+ d_modelCommandsAlloc.push_back(std::unique_ptr<NodeCommand>(cc));
}
}
if (Dump.isOn(dumpTag))
@@ -88,7 +88,7 @@ void DumpManager::addToModelCommandAndDump(const Command& c,
}
else
{
- d_dumpCommands.push_back(std::unique_ptr<Command>(c.clone()));
+ d_dumpCommands.push_back(std::unique_ptr<NodeCommand>(c.clone()));
}
}
}
@@ -96,7 +96,7 @@ void DumpManager::addToModelCommandAndDump(const Command& c,
void DumpManager::setPrintFuncInModel(Node f, bool p)
{
Trace("setp-model") << "Set printInModel " << f << " to " << p << std::endl;
- for (std::unique_ptr<Command>& c : d_modelGlobalCommands)
+ for (std::unique_ptr<NodeCommand>& c : d_modelGlobalCommands)
{
DeclareFunctionCommand* dfc =
dynamic_cast<DeclareFunctionCommand*>(c.get());
@@ -109,7 +109,7 @@ void DumpManager::setPrintFuncInModel(Node f, bool p)
}
}
}
- for (Command* c : d_modelCommands)
+ for (NodeCommand* c : d_modelCommands)
{
DeclareFunctionCommand* dfc = dynamic_cast<DeclareFunctionCommand*>(c);
if (dfc != NULL)
@@ -128,7 +128,7 @@ size_t DumpManager::getNumModelCommands() const
return d_modelCommands.size() + d_modelGlobalCommands.size();
}
-const Command* DumpManager::getModelCommand(size_t i) const
+const NodeCommand* DumpManager::getModelCommand(size_t i) const
{
Assert(i < getNumModelCommands());
// index the global commands first, then the locals
diff --git a/src/smt/dump_manager.h b/src/smt/dump_manager.h
index 6f2ee37a1..2ce0570e4 100644
--- a/src/smt/dump_manager.h
+++ b/src/smt/dump_manager.h
@@ -22,7 +22,7 @@
#include "context/cdlist.h"
#include "expr/node.h"
-#include "smt/command.h"
+#include "smt/node_command.h"
namespace CVC4 {
namespace smt {
@@ -36,7 +36,7 @@ namespace smt {
*/
class DumpManager
{
- typedef context::CDList<Command*> CommandList;
+ typedef context::CDList<NodeCommand*> CommandList;
public:
DumpManager(context::UserContext* u);
@@ -54,7 +54,7 @@ class DumpManager
* Add to Model command. This is used for recording a command
* that should be reported during a get-model call.
*/
- void addToModelCommandAndDump(const Command& c,
+ void addToModelCommandAndDump(const NodeCommand& c,
uint32_t flags = 0,
bool userVisible = true,
const char* dumpTag = "declarations");
@@ -66,7 +66,7 @@ class DumpManager
/** get number of commands to report in a model */
size_t getNumModelCommands() const;
/** get model command at index i */
- const Command* getModelCommand(size_t i) const;
+ const NodeCommand* getModelCommand(size_t i) const;
private:
/** Fully inited */
@@ -77,7 +77,7 @@ class DumpManager
* regardless of push/pop). Only maintained if produce-models option
* is on.
*/
- std::vector<std::unique_ptr<Command>> d_modelGlobalCommands;
+ std::vector<std::unique_ptr<NodeCommand>> d_modelGlobalCommands;
/**
* A list of commands that should be in the Model locally (i.e.,
@@ -89,7 +89,7 @@ class DumpManager
* A list of model commands allocated to d_modelCommands at any time. This
* is maintained for memory management purposes.
*/
- std::vector<std::unique_ptr<Command>> d_modelCommandsAlloc;
+ std::vector<std::unique_ptr<NodeCommand>> d_modelCommandsAlloc;
/**
* A vector of declaration commands waiting to be dumped out.
@@ -97,7 +97,7 @@ class DumpManager
* This ensures the declarations come after the set-logic and
* any necessary set-option commands are dumped.
*/
- std::vector<std::unique_ptr<Command>> d_dumpCommands;
+ std::vector<std::unique_ptr<NodeCommand>> d_dumpCommands;
};
} // namespace smt
diff --git a/src/smt/listeners.cpp b/src/smt/listeners.cpp
index 539d6ba2f..52ddcf156 100644
--- a/src/smt/listeners.cpp
+++ b/src/smt/listeners.cpp
@@ -18,7 +18,7 @@
#include "expr/expr.h"
#include "expr/node_manager_attributes.h"
#include "options/smt_options.h"
-#include "smt/command.h"
+#include "smt/node_command.h"
#include "smt/dump.h"
#include "smt/dump_manager.h"
#include "smt/smt_engine.h"
@@ -40,7 +40,7 @@ SmtNodeManagerListener::SmtNodeManagerListener(DumpManager& dm) : d_dm(dm) {}
void SmtNodeManagerListener::nmNotifyNewSort(TypeNode tn, uint32_t flags)
{
- DeclareTypeCommand c(tn.getAttribute(expr::VarNameAttr()), 0, tn.toType());
+ DeclareTypeNodeCommand c(tn.getAttribute(expr::VarNameAttr()), 0, tn);
if ((flags & ExprManager::SORT_FLAG_PLACEHOLDER) == 0)
{
d_dm.addToModelCommandAndDump(c, flags);
@@ -50,9 +50,9 @@ void SmtNodeManagerListener::nmNotifyNewSort(TypeNode tn, uint32_t flags)
void SmtNodeManagerListener::nmNotifyNewSortConstructor(TypeNode tn,
uint32_t flags)
{
- DeclareTypeCommand c(tn.getAttribute(expr::VarNameAttr()),
- tn.getAttribute(expr::SortArityAttr()),
- tn.toType());
+ DeclareTypeNodeCommand c(tn.getAttribute(expr::VarNameAttr()),
+ tn.getAttribute(expr::SortArityAttr()),
+ tn);
if ((flags & ExprManager::SORT_FLAG_PLACEHOLDER) == 0)
{
d_dm.addToModelCommandAndDump(c);
@@ -68,17 +68,16 @@ void SmtNodeManagerListener::nmNotifyNewDatatypes(
for (const TypeNode& dt : dtts)
{
Assert(dt.isDatatype());
- types.push_back(dt.toType());
}
- DatatypeDeclarationCommand c(types);
+ DeclareDatatypeNodeCommand c(dtts);
d_dm.addToModelCommandAndDump(c);
}
}
void SmtNodeManagerListener::nmNotifyNewVar(TNode n, uint32_t flags)
{
- DeclareFunctionCommand c(
- n.getAttribute(expr::VarNameAttr()), n.toExpr(), n.getType().toType());
+ DeclareFunctionNodeCommand c(
+ n.getAttribute(expr::VarNameAttr()), n, n.getType());
if ((flags & ExprManager::VAR_FLAG_DEFINED) == 0)
{
d_dm.addToModelCommandAndDump(c, flags);
@@ -90,7 +89,7 @@ void SmtNodeManagerListener::nmNotifyNewSkolem(TNode n,
uint32_t flags)
{
std::string id = n.getAttribute(expr::VarNameAttr());
- DeclareFunctionCommand c(id, n.toExpr(), n.getType().toType());
+ DeclareFunctionNodeCommand c(id, n, n.getType());
if (Dump.isOn("skolems") && comment != "")
{
Dump("skolems") << CommentCommand(id + " is " + comment);
diff --git a/src/smt/model.cpp b/src/smt/model.cpp
index 7924698ff..a23b885ff 100644
--- a/src/smt/model.cpp
+++ b/src/smt/model.cpp
@@ -19,8 +19,8 @@
#include "expr/expr_iomanip.h"
#include "options/base_options.h"
#include "printer/printer.h"
-#include "smt/command.h"
#include "smt/dump_manager.h"
+#include "smt/node_command.h"
#include "smt/smt_engine.h"
#include "smt/smt_engine_scope.h"
@@ -42,7 +42,7 @@ size_t Model::getNumCommands() const
return d_smt.getDumpManager()->getNumModelCommands();
}
-const Command* Model::getCommand(size_t i) const
+const NodeCommand* Model::getCommand(size_t i) const
{
return d_smt.getDumpManager()->getModelCommand(i);
}
diff --git a/src/smt/model.h b/src/smt/model.h
index 8f4409b07..4c28704c3 100644
--- a/src/smt/model.h
+++ b/src/smt/model.h
@@ -25,7 +25,7 @@
namespace CVC4 {
-class Command;
+class NodeCommand;
class SmtEngine;
class Model;
@@ -48,7 +48,7 @@ class Model {
/** get number of commands to report */
size_t getNumCommands() const;
/** get command */
- const Command* getCommand(size_t i) const;
+ const NodeCommand* getCommand(size_t i) const;
/** get the smt engine that this model is hooked up to */
SmtEngine* getSmtEngine() { return &d_smt; }
/** get the smt engine (as a pointer-to-const) that this model is hooked up to */
diff --git a/src/smt/node_command.cpp b/src/smt/node_command.cpp
new file mode 100644
index 000000000..265b35b3e
--- /dev/null
+++ b/src/smt/node_command.cpp
@@ -0,0 +1,180 @@
+/********************* */
+/*! \file node_command.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Abdalrhman Mohamed
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of NodeCommand functions.
+ **
+ ** Implementation of NodeCommand functions.
+ **/
+
+#include "smt/node_command.h"
+
+#include "printer/printer.h"
+
+namespace CVC4 {
+
+/* -------------------------------------------------------------------------- */
+/* class NodeCommand */
+/* -------------------------------------------------------------------------- */
+
+NodeCommand::~NodeCommand() {}
+
+std::string NodeCommand::toString() const
+{
+ std::stringstream ss;
+ toStream(ss);
+ return ss.str();
+}
+
+std::ostream& operator<<(std::ostream& out, const NodeCommand& nc)
+{
+ nc.toStream(out,
+ Node::setdepth::getDepth(out),
+ Node::printtypes::getPrintTypes(out),
+ Node::dag::getDag(out),
+ Node::setlanguage::getLanguage(out));
+ return out;
+}
+
+/* -------------------------------------------------------------------------- */
+/* class DeclareFunctionNodeCommand */
+/* -------------------------------------------------------------------------- */
+
+DeclareFunctionNodeCommand::DeclareFunctionNodeCommand(const std::string& id,
+ Node expr,
+ TypeNode type)
+ : d_id(id),
+ d_fun(expr),
+ d_type(type),
+ d_printInModel(true),
+ d_printInModelSetByUser(false)
+{
+}
+
+void DeclareFunctionNodeCommand::toStream(std::ostream& out,
+ int toDepth,
+ bool types,
+ size_t dag,
+ OutputLanguage language) const
+{
+ Printer::getPrinter(language)->toStreamCmdDeclareFunction(out, d_id, d_type);
+}
+
+NodeCommand* DeclareFunctionNodeCommand::clone() const
+{
+ return new DeclareFunctionNodeCommand(d_id, d_fun, d_type);
+}
+
+const Node& DeclareFunctionNodeCommand::getFunction() const { return d_fun; }
+
+bool DeclareFunctionNodeCommand::getPrintInModel() const
+{
+ return d_printInModel;
+}
+
+bool DeclareFunctionNodeCommand::getPrintInModelSetByUser() const
+{
+ return d_printInModelSetByUser;
+}
+
+void DeclareFunctionNodeCommand::setPrintInModel(bool p)
+{
+ d_printInModel = p;
+ d_printInModelSetByUser = true;
+}
+
+/* -------------------------------------------------------------------------- */
+/* class DeclareTypeNodeCommand */
+/* -------------------------------------------------------------------------- */
+
+DeclareTypeNodeCommand::DeclareTypeNodeCommand(const std::string& id,
+ size_t arity,
+ TypeNode type)
+ : d_id(id), d_arity(arity), d_type(type)
+{
+}
+
+void DeclareTypeNodeCommand::toStream(std::ostream& out,
+ int toDepth,
+ bool types,
+ size_t dag,
+ OutputLanguage language) const
+{
+ Printer::getPrinter(language)->toStreamCmdDeclareType(
+ out, d_id, d_arity, d_type);
+}
+
+NodeCommand* DeclareTypeNodeCommand::clone() const
+{
+ return new DeclareTypeNodeCommand(d_id, d_arity, d_type);
+}
+
+const std::string DeclareTypeNodeCommand::getSymbol() const { return d_id; }
+
+const TypeNode& DeclareTypeNodeCommand::getType() const { return d_type; }
+
+/* -------------------------------------------------------------------------- */
+/* class DeclareDatatypeNodeCommand */
+/* -------------------------------------------------------------------------- */
+
+DeclareDatatypeNodeCommand::DeclareDatatypeNodeCommand(
+ const std::vector<TypeNode>& datatypes)
+ : d_datatypes(datatypes)
+{
+}
+
+void DeclareDatatypeNodeCommand::toStream(std::ostream& out,
+ int toDepth,
+ bool types,
+ size_t dag,
+ OutputLanguage language) const
+{
+ Printer::getPrinter(language)->toStreamCmdDatatypeDeclaration(out,
+ d_datatypes);
+}
+
+NodeCommand* DeclareDatatypeNodeCommand::clone() const
+{
+ return new DeclareDatatypeNodeCommand(d_datatypes);
+}
+
+/* -------------------------------------------------------------------------- */
+/* class DefineFunctionNodeCommand */
+/* -------------------------------------------------------------------------- */
+
+DefineFunctionNodeCommand::DefineFunctionNodeCommand(
+ const std::string& id,
+ Node fun,
+ const std::vector<Node>& formals,
+ Node formula)
+ : d_id(id), d_fun(fun), d_formals(formals), d_formula(formula)
+{
+}
+
+void DefineFunctionNodeCommand::toStream(std::ostream& out,
+ int toDepth,
+ bool types,
+ size_t dag,
+ OutputLanguage language) const
+{
+ Printer::getPrinter(language)->toStreamCmdDefineFunction(
+ out,
+ d_fun.toString(),
+ d_formals,
+ d_fun.getType().getRangeType(),
+ d_formula);
+}
+
+NodeCommand* DefineFunctionNodeCommand::clone() const
+{
+ return new DefineFunctionNodeCommand(d_id, d_fun, d_formals, d_formula);
+}
+
+} // namespace CVC4
diff --git a/src/smt/node_command.h b/src/smt/node_command.h
new file mode 100644
index 000000000..2ca166bb6
--- /dev/null
+++ b/src/smt/node_command.h
@@ -0,0 +1,157 @@
+/********************* */
+/*! \file node_command.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Abdalrhman Mohamed
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Datastructures used for printing commands internally.
+ **
+ ** Datastructures used for printing commands internally.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__SMT__NODE_COMMAND_H
+#define CVC4__SMT__NODE_COMMAND_H
+
+#include <string>
+
+#include "expr/node.h"
+#include "expr/type_node.h"
+#include "options/language.h"
+
+namespace CVC4 {
+
+/**
+ * A node version of Command. DO NOT use this version unless there is a need
+ * to buffer commands for later use (e.g., printing models).
+ */
+class NodeCommand
+{
+ public:
+ /** Destructor */
+ virtual ~NodeCommand();
+
+ /** Print this NodeCommand to output stream */
+ virtual void toStream(
+ std::ostream& out,
+ int toDepth = -1,
+ bool types = false,
+ size_t dag = 1,
+ OutputLanguage language = language::output::LANG_AUTO) const = 0;
+
+ /** Get a string representation of this NodeCommand */
+ std::string toString() const;
+
+ /** Clone this NodeCommand (make a shallow copy). */
+ virtual NodeCommand* clone() const = 0;
+};
+
+std::ostream& operator<<(std::ostream& out, const NodeCommand& nc);
+
+/**
+ * Declare n-ary function symbol.
+ * SMT-LIB: ( declare-fun <id> ( <type.getArgTypes()> ) <type.getRangeType()> )
+ */
+class DeclareFunctionNodeCommand : public NodeCommand
+{
+ public:
+ DeclareFunctionNodeCommand(const std::string& id, Node fun, TypeNode type);
+ void toStream(
+ std::ostream& out,
+ int toDepth = -1,
+ bool types = false,
+ size_t dag = 1,
+ OutputLanguage language = language::output::LANG_AUTO) const override;
+ NodeCommand* clone() const override;
+ const Node& getFunction() const;
+ bool getPrintInModel() const;
+ bool getPrintInModelSetByUser() const;
+ void setPrintInModel(bool p);
+
+ private:
+ std::string d_id;
+ Node d_fun;
+ TypeNode d_type;
+ bool d_printInModel;
+ bool d_printInModelSetByUser;
+};
+
+/**
+ * Create datatype sort.
+ * SMT-LIB: ( declare-datatypes ( <datatype decls>{n+1} ) ( <datatypes>{n+1} ) )
+ */
+class DeclareDatatypeNodeCommand : public NodeCommand
+{
+ public:
+ DeclareDatatypeNodeCommand(const std::vector<TypeNode>& datatypes);
+ void toStream(
+ std::ostream& out,
+ int toDepth = -1,
+ bool types = false,
+ size_t dag = 1,
+ OutputLanguage language = language::output::LANG_AUTO) const override;
+ NodeCommand* clone() const override;
+
+ private:
+ std::vector<TypeNode> d_datatypes;
+};
+
+/**
+ * Declare uninterpreted sort.
+ * SMT-LIB: ( declare-sort <id> <arity> )
+ */
+class DeclareTypeNodeCommand : public NodeCommand
+{
+ public:
+ DeclareTypeNodeCommand(const std::string& id, size_t arity, TypeNode type);
+ void toStream(
+ std::ostream& out,
+ int toDepth = -1,
+ bool types = false,
+ size_t dag = 1,
+ OutputLanguage language = language::output::LANG_AUTO) const override;
+ NodeCommand* clone() const override;
+ const std::string getSymbol() const;
+ const TypeNode& getType() const;
+
+ private:
+ std::string d_id;
+ size_t d_arity;
+ TypeNode d_type;
+};
+
+/**
+ * Define n-ary function.
+ * SMT-LIB: ( define-fun <id> ( <formals> ) <fun.getType()> <formula> )
+ */
+class DefineFunctionNodeCommand : public NodeCommand
+{
+ public:
+ DefineFunctionNodeCommand(const std::string& id,
+ Node fun,
+ const std::vector<Node>& formals,
+ Node formula);
+ void toStream(
+ std::ostream& out,
+ int toDepth = -1,
+ bool types = false,
+ size_t dag = 1,
+ OutputLanguage language = language::output::LANG_AUTO) const override;
+ NodeCommand* clone() const override;
+
+ private:
+ std::string d_id;
+ Node d_fun;
+ std::vector<Node> d_formals;
+ Node d_formula;
+};
+
+} // namespace CVC4
+
+#endif /* CVC4__SMT__NODE_COMMAND_H */
diff --git a/src/smt/process_assertions.cpp b/src/smt/process_assertions.cpp
index a69207512..33d092def 100644
--- a/src/smt/process_assertions.cpp
+++ b/src/smt/process_assertions.cpp
@@ -21,7 +21,6 @@
#include "options/arith_options.h"
#include "options/base_options.h"
#include "options/bv_options.h"
-#include "options/proof_options.h"
#include "options/quantifiers_options.h"
#include "options/sep_options.h"
#include "options/smt_options.h"
@@ -147,12 +146,6 @@ bool ProcessAssertions::apply(Assertions& as)
<< endl;
dumpAssertions("post-definition-expansion", assertions);
- // save the assertions now
- THEORY_PROOF(
- for (size_t i = 0, nasserts = assertions.size(); i < nasserts; ++i) {
- ProofManager::currentPM()->addAssertion(assertions[i].toExpr());
- });
-
Debug("smt") << " assertions : " << assertions.size() << endl;
if (options::globalNegate())
@@ -470,7 +463,7 @@ bool ProcessAssertions::simplifyAssertions(AssertionPipeline& assertions)
if (options::simplificationMode() != options::SimplificationMode::NONE)
{
- if (!options::unsatCores() && !options::fewerPreprocessingHoles())
+ if (!options::unsatCores())
{
// Perform non-clausal simplification
PreprocessingPassResult res =
@@ -532,7 +525,7 @@ bool ProcessAssertions::simplifyAssertions(AssertionPipeline& assertions)
if (options::repeatSimp()
&& options::simplificationMode() != options::SimplificationMode::NONE
- && !options::unsatCores() && !options::fewerPreprocessingHoles())
+ && !options::unsatCores())
{
PreprocessingPassResult res =
d_passes["non-clausal-simp"]->apply(&assertions);
diff --git a/src/smt/set_defaults.cpp b/src/smt/set_defaults.cpp
index 130f75894..6f00998d2 100644
--- a/src/smt/set_defaults.cpp
+++ b/src/smt/set_defaults.cpp
@@ -27,7 +27,6 @@
#include "options/open_ostream.h"
#include "options/option_exception.h"
#include "options/printer_options.h"
-#include "options/proof_options.h"
#include "options/prop_options.h"
#include "options/quantifiers_options.h"
#include "options/sep_options.h"
@@ -72,11 +71,6 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
Notice() << "SmtEngine: setting unsatCores" << std::endl;
options::unsatCores.set(true);
}
- if (options::checkProofs() || options::dumpProofs())
- {
- Notice() << "SmtEngine: setting proof" << std::endl;
- options::proof.set(true);
- }
if (options::bitvectorAigSimplifications.wasSetByUser())
{
Notice() << "SmtEngine: setting bitvectorAig" << std::endl;
@@ -254,12 +248,6 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
<< std::endl;
}
}
- // !!!!!!!!!!!!!!!! temporary, to support CI check for old proof system
- if (options::proof())
- {
- options::proofNew.set(false);
- }
-
if (options::arraysExp())
{
if (!logic.isQuantified())
@@ -316,11 +304,10 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
options::produceAssertions.set(true);
}
- // Disable options incompatible with incremental solving, unsat cores, and
- // proofs or output an error if enabled explicitly. It is also currently
- // incompatible with arithmetic, force the option off.
- if (options::incrementalSolving() || options::unsatCores()
- || options::proof())
+ // Disable options incompatible with incremental solving, unsat cores or
+ // output an error if enabled explicitly. It is also currently incompatible
+ // with arithmetic, force the option off.
+ if (options::incrementalSolving() || options::unsatCores())
{
if (options::unconstrainedSimp())
{
@@ -328,10 +315,10 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
{
throw OptionException(
"unconstrained simplification not supported with unsat "
- "cores/proofs/incremental solving");
+ "cores/incremental solving");
}
Notice() << "SmtEngine: turning off unconstrained simplification to "
- "support unsat cores/proofs/incremental solving"
+ "support unsat cores/incremental solving"
<< std::endl;
options::unconstrainedSimp.set(false);
}
@@ -353,17 +340,17 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
}
}
- if (options::incrementalSolving() || options::proof())
+ if (options::incrementalSolving())
{
if (options::sygusInference())
{
if (options::sygusInference.wasSetByUser())
{
throw OptionException(
- "sygus inference not supported with proofs/incremental solving");
+ "sygus inference not supported with incremental solving");
}
Notice() << "SmtEngine: turning off sygus inference to support "
- "proofs/incremental solving"
+ "incremental solving"
<< std::endl;
options::sygusInference.set(false);
}
@@ -380,19 +367,18 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
options::bitvectorToBool.set(true);
}
- // Disable options incompatible with unsat cores and proofs or output an
- // error if enabled explicitly
- if (options::unsatCores() || options::proof())
+ // Disable options incompatible with unsat cores or output an error if enabled
+ // explicitly
+ if (options::unsatCores())
{
if (options::simplificationMode() != options::SimplificationMode::NONE)
{
if (options::simplificationMode.wasSetByUser())
{
- throw OptionException(
- "simplification not supported with unsat cores/proofs");
+ throw OptionException("simplification not supported with unsat cores");
}
Notice() << "SmtEngine: turning off simplification to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::simplificationMode.set(options::SimplificationMode::NONE);
}
@@ -402,10 +388,10 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
if (options::pbRewrites.wasSetByUser())
{
throw OptionException(
- "pseudoboolean rewrites not supported with unsat cores/proofs");
+ "pseudoboolean rewrites not supported with unsat cores");
}
Notice() << "SmtEngine: turning off pseudoboolean rewrites to support "
- "unsat cores/proofs"
+ "unsat cores"
<< std::endl;
options::pbRewrites.set(false);
}
@@ -414,11 +400,10 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
{
if (options::sortInference.wasSetByUser())
{
- throw OptionException(
- "sort inference not supported with unsat cores/proofs");
+ throw OptionException("sort inference not supported with unsat cores");
}
Notice() << "SmtEngine: turning off sort inference to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::sortInference.set(false);
}
@@ -428,10 +413,10 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
if (options::preSkolemQuant.wasSetByUser())
{
throw OptionException(
- "pre-skolemization not supported with unsat cores/proofs");
+ "pre-skolemization not supported with unsat cores");
}
Notice() << "SmtEngine: turning off pre-skolemization to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::preSkolemQuant.set(false);
}
@@ -441,11 +426,10 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
{
if (options::bitvectorToBool.wasSetByUser())
{
- throw OptionException(
- "bv-to-bool not supported with unsat cores/proofs");
+ throw OptionException("bv-to-bool not supported with unsat cores");
}
Notice() << "SmtEngine: turning off bitvector-to-bool to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::bitvectorToBool.set(false);
}
@@ -455,10 +439,10 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
if (options::boolToBitvector.wasSetByUser())
{
throw OptionException(
- "bool-to-bv != off not supported with unsat cores/proofs");
+ "bool-to-bv != off not supported with unsat cores");
}
Notice() << "SmtEngine: turning off bool-to-bv to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::boolToBitvector.set(options::BoolToBVMode::OFF);
}
@@ -467,11 +451,10 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
{
if (options::bvIntroducePow2.wasSetByUser())
{
- throw OptionException(
- "bv-intro-pow2 not supported with unsat cores/proofs");
+ throw OptionException("bv-intro-pow2 not supported with unsat cores");
}
Notice() << "SmtEngine: turning off bv-intro-pow2 to support "
- "unsat-cores/proofs"
+ "unsat-cores"
<< std::endl;
options::bvIntroducePow2.set(false);
}
@@ -480,11 +463,10 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
{
if (options::repeatSimp.wasSetByUser())
{
- throw OptionException(
- "repeat-simp not supported with unsat cores/proofs");
+ throw OptionException("repeat-simp not supported with unsat cores");
}
Notice() << "SmtEngine: turning off repeat-simp to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::repeatSimp.set(false);
}
@@ -493,19 +475,17 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
{
if (options::globalNegate.wasSetByUser())
{
- throw OptionException(
- "global-negate not supported with unsat cores/proofs");
+ throw OptionException("global-negate not supported with unsat cores");
}
Notice() << "SmtEngine: turning off global-negate to support unsat "
- "cores/proofs"
+ "cores"
<< std::endl;
options::globalNegate.set(false);
}
if (options::bitvectorAig())
{
- throw OptionException(
- "bitblast-aig not supported with unsat cores/proofs");
+ throw OptionException("bitblast-aig not supported with unsat cores");
}
}
else
@@ -626,7 +606,7 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
if (!options::ufSymmetryBreaker.wasSetByUser())
{
bool qf_uf_noinc = logic.isPure(THEORY_UF) && !logic.isQuantified()
- && !options::incrementalSolving() && !options::proof()
+ && !options::incrementalSolving()
&& !options::unsatCores();
Trace("smt") << "setting uf symmetry breaker to " << qf_uf_noinc
<< std::endl;
@@ -848,7 +828,7 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
// Do we need to track instantiations?
// Needed for sygus due to single invocation techniques.
if (options::cegqiNestedQE()
- || (options::proof() && !options::trackInstLemmas.wasSetByUser())
+ || (options::unsatCores() && !options::trackInstLemmas.wasSetByUser())
|| is_sygus)
{
options::trackInstLemmas.set(true);
@@ -1323,59 +1303,6 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
options::arraysOptimizeLinear.set(false);
}
- if (options::proof())
- {
- if (options::incrementalSolving())
- {
- if (options::incrementalSolving.wasSetByUser())
- {
- throw OptionException("--incremental is not supported with proofs");
- }
- Warning()
- << "SmtEngine: turning off incremental solving mode (not yet "
- "supported with --proof, try --tear-down-incremental instead)"
- << std::endl;
- options::incrementalSolving.set(false);
- }
- if (logic > LogicInfo("QF_AUFBVLRA"))
- {
- throw OptionException(
- "Proofs are only supported for sub-logics of QF_AUFBVLIA.");
- }
- if (options::bitvectorAlgebraicSolver())
- {
- if (options::bitvectorAlgebraicSolver.wasSetByUser())
- {
- throw OptionException(
- "--bv-algebraic-solver is not supported with proofs");
- }
- Notice() << "SmtEngine: turning off bv algebraic solver to support proofs"
- << std::endl;
- options::bitvectorAlgebraicSolver.set(false);
- }
- if (options::bitvectorEqualitySolver())
- {
- if (options::bitvectorEqualitySolver.wasSetByUser())
- {
- throw OptionException("--bv-eq-solver is not supported with proofs");
- }
- Notice() << "SmtEngine: turning off bv eq solver to support proofs"
- << std::endl;
- options::bitvectorEqualitySolver.set(false);
- }
- if (options::bitvectorInequalitySolver())
- {
- if (options::bitvectorInequalitySolver.wasSetByUser())
- {
- throw OptionException(
- "--bv-inequality-solver is not supported with proofs");
- }
- Notice() << "SmtEngine: turning off bv ineq solver to support proofs"
- << std::endl;
- options::bitvectorInequalitySolver.set(false);
- }
- }
-
if (!options::bitvectorEqualitySolver())
{
if (options::bvLazyRewriteExtf())
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index 98e865478..81d4f594d 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -62,7 +62,6 @@
#include "options/open_ostream.h"
#include "options/option_exception.h"
#include "options/printer_options.h"
-#include "options/proof_options.h"
#include "options/prop_options.h"
#include "options/quantifiers_options.h"
#include "options/sep_options.h"
@@ -75,9 +74,7 @@
#include "preprocessing/preprocessing_pass_context.h"
#include "preprocessing/preprocessing_pass_registry.h"
#include "printer/printer.h"
-#include "proof/proof.h"
#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
#include "proof/unsat_core.h"
#include "smt/abduction_solver.h"
#include "smt/abstract_values.h"
@@ -113,14 +110,9 @@
#include "theory/theory_model.h"
#include "theory/theory_traits.h"
#include "util/hash.h"
-#include "util/proof.h"
#include "util/random.h"
#include "util/resource_manager.h"
-#if (IS_LFSC_BUILD && IS_PROOFS_BUILD)
-#include "lfscc.h"
-#endif
-
using namespace std;
using namespace CVC4;
using namespace CVC4::smt;
@@ -131,10 +123,6 @@ using namespace CVC4::theory;
namespace CVC4 {
-namespace proof {
-extern const char* const plf_signatures;
-} // namespace proof
-
namespace smt {
}/* namespace CVC4::smt */
@@ -307,15 +295,6 @@ void SmtEngine::finishInit()
d_abductSolver.reset(new AbductionSolver(this));
}
- PROOF( ProofManager::currentPM()->setLogic(d_logic); );
- PROOF({
- TheoryEngine* te = d_smtSolver->getTheoryEngine();
- for (TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id)
- {
- ProofManager::currentPM()->getTheoryProofEngine()->finishRegisterTheory(
- te->theoryOf(id));
- }
- });
d_pp->finishInit();
AlwaysAssert(getPropEngine()->getAssertionLevel() == 0)
@@ -709,9 +688,18 @@ void SmtEngine::defineFunction(Expr func,
ss << language::SetLanguage(
language::SetLanguage::getLanguage(Dump.getStream()))
<< func;
- DefineFunctionCommand c(ss.str(), func, formals, formula, global);
+ std::vector<Node> nFormals;
+ nFormals.reserve(formals.size());
+
+ for (const Expr& formal : formals)
+ {
+ nFormals.push_back(formal.getNode());
+ }
+
+ DefineFunctionNodeCommand nc(
+ ss.str(), func.getNode(), nFormals, formula.getNode());
d_dumpm->addToModelCommandAndDump(
- c, ExprManager::VAR_FLAG_DEFINED, true, "declarations");
+ nc, ExprManager::VAR_FLAG_DEFINED, true, "declarations");
// type check body
debugCheckFunctionBody(formula, formals, func);
@@ -891,7 +879,7 @@ theory::TheoryModel* SmtEngine::getAvailableModel(const char* c) const
std::stringstream ss;
ss << "Cannot " << c
<< " since model is not available. Perhaps the most recent call to "
- "check-sat was interupted?";
+ "check-sat was interrupted?";
throw RecoverableModalException(ss.str().c_str());
}
@@ -1005,12 +993,6 @@ Result SmtEngine::checkSatInternal(const vector<Node>& assumptions,
checkModel();
}
}
- // Check that UNSAT results generate a proof correctly.
- if(options::checkProofs()) {
- if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
- checkProof();
- }
- }
// Check that UNSAT results generate an unsat core correctly.
if(options::checkUnsatCores()) {
if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
@@ -1476,43 +1458,6 @@ Expr SmtEngine::getSepHeapExpr() { return getSepHeapAndNilExpr().first; }
Expr SmtEngine::getSepNilExpr() { return getSepHeapAndNilExpr().second; }
-void SmtEngine::checkProof()
-{
-#if (IS_LFSC_BUILD && IS_PROOFS_BUILD)
-
- Chat() << "generating proof..." << endl;
-
- const Proof& pf = getProof();
-
- Chat() << "checking proof..." << endl;
-
- std::string logicString = d_logic.getLogicString();
-
- std::stringstream pfStream;
-
- pfStream << proof::plf_signatures << endl;
- int64_t sizeBeforeProof = static_cast<int64_t>(pfStream.tellp());
-
- pf.toStream(pfStream);
- d_stats->d_proofsSize +=
- static_cast<int64_t>(pfStream.tellp()) - sizeBeforeProof;
-
- {
- TimerStat::CodeTimer checkProofTimer(d_stats->d_lfscCheckProofTime);
- lfscc_init();
- lfscc_check_file(pfStream, false, false, false, false, false, false, false);
- }
- // FIXME: we should actually call lfscc_cleanup here, but lfscc_cleanup
- // segfaults on regress0/bv/core/bitvec7.smt
- // lfscc_cleanup();
-
-#else /* (IS_LFSC_BUILD && IS_PROOFS_BUILD) */
- Unreachable()
- << "This version of CVC4 was built without proof support; cannot check "
- "proofs.";
-#endif /* (IS_LFSC_BUILD && IS_PROOFS_BUILD) */
-}
-
UnsatCore SmtEngine::getUnsatCoreInternal()
{
#if IS_PROOFS_BUILD
@@ -1548,7 +1493,6 @@ void SmtEngine::checkUnsatCore() {
coreChecker.setIsInternalSubsolver();
coreChecker.setLogic(getLogicInfo());
coreChecker.getOptions().set(options::checkUnsatCores, false);
- coreChecker.getOptions().set(options::checkProofs, false);
Notice() << "SmtEngine::checkUnsatCore(): pushing core assertions (size == " << core.size() << ")" << endl;
for(UnsatCore::iterator i = core.begin(); i != core.end(); ++i) {
@@ -1823,32 +1767,6 @@ UnsatCore SmtEngine::getUnsatCore() {
return getUnsatCoreInternal();
}
-// TODO(#1108): Simplify the error reporting of this method.
-const Proof& SmtEngine::getProof()
-{
- Trace("smt") << "SMT getProof()" << endl;
- SmtScope smts(this);
- finishInit();
- if(Dump.isOn("benchmark")) {
- Dump("benchmark") << GetProofCommand();
- }
-#if IS_PROOFS_BUILD
- if(!options::proof()) {
- throw ModalException("Cannot get a proof when produce-proofs option is off.");
- }
- if (d_state->getMode() != SmtMode::UNSAT)
- {
- throw RecoverableModalException(
- "Cannot get a proof unless immediately preceded by UNSAT/ENTAILED "
- "response.");
- }
-
- return ProofManager::getProof(this);
-#else /* IS_PROOFS_BUILD */
- throw ModalException("This build of CVC4 doesn't have proof support.");
-#endif /* IS_PROOFS_BUILD */
-}
-
void SmtEngine::printInstantiations( std::ostream& out ) {
SmtScope smts(this);
finishInit();
diff --git a/src/smt/smt_engine.h b/src/smt/smt_engine.h
index 99c4a67d3..5aa2ba987 100644
--- a/src/smt/smt_engine.h
+++ b/src/smt/smt_engine.h
@@ -34,7 +34,6 @@
#include "smt/smt_mode.h"
#include "theory/logic_info.h"
#include "util/hash.h"
-#include "util/proof.h"
#include "util/result.h"
#include "util/sexpr.h"
#include "util/statistics.h"
@@ -544,16 +543,6 @@ class CVC4_PUBLIC SmtEngine
*/
std::vector<std::pair<Expr, Expr> > getAssignment();
- /**
- * Get the last proof (only if immediately preceded by an UNSAT or ENTAILED
- * query). Only permitted if CVC4 was built with proof support and
- * produce-proofs is on.
- *
- * The Proof object is owned by this SmtEngine until the SmtEngine is
- * destroyed.
- */
- const Proof& getProof();
-
/** Print all instantiations made by the quantifiers module. */
void printInstantiations(std::ostream& out);
@@ -566,7 +555,7 @@ class CVC4_PUBLIC SmtEngine
/**
* Get synth solution.
*
- * This method returns true if we are in a state immediately preceeded by
+ * This method returns true if we are in a state immediately preceded by
* a successful call to checkSynth.
*
* This method adds entries to solMap that map functions-to-synthesize with
@@ -921,11 +910,6 @@ class CVC4_PUBLIC SmtEngine
};
/**
- * Check that a generated proof (via getProof()) checks.
- */
- void checkProof();
-
- /**
* Internal method to get an unsatisfiable core (only if immediately preceded
* by an UNSAT or ENTAILED query). Only permitted if CVC4 was built with
* unsat-core support and produce-unsat-cores is on. Does not dump the
diff --git a/src/smt/smt_engine_scope.cpp b/src/smt/smt_engine_scope.cpp
index 1e9c91767..cc86ae33c 100644
--- a/src/smt/smt_engine_scope.cpp
+++ b/src/smt/smt_engine_scope.cpp
@@ -20,7 +20,6 @@
#include "base/check.h"
#include "base/configuration_private.h"
#include "base/output.h"
-#include "proof/proof.h"
#include "smt/smt_engine.h"
namespace CVC4 {
diff --git a/src/smt/smt_engine_stats.cpp b/src/smt/smt_engine_stats.cpp
index 9b25580d2..e36284714 100644
--- a/src/smt/smt_engine_stats.cpp
+++ b/src/smt/smt_engine_stats.cpp
@@ -25,9 +25,7 @@ SmtEngineStatistics::SmtEngineStatistics()
d_cnfConversionTime("smt::SmtEngine::cnfConversionTime"),
d_numAssertionsPre("smt::SmtEngine::numAssertionsPreITERemoval", 0),
d_numAssertionsPost("smt::SmtEngine::numAssertionsPostITERemoval", 0),
- d_proofsSize("smt::SmtEngine::proofsSize", 0),
d_checkModelTime("smt::SmtEngine::checkModelTime"),
- d_lfscCheckProofTime("smt::SmtEngine::lfscCheckProofTime"),
d_checkUnsatCoreTime("smt::SmtEngine::checkUnsatCoreTime"),
d_solveTime("smt::SmtEngine::solveTime"),
d_pushPopTime("smt::SmtEngine::pushPopTime"),
@@ -39,9 +37,7 @@ SmtEngineStatistics::SmtEngineStatistics()
smtStatisticsRegistry()->registerStat(&d_cnfConversionTime);
smtStatisticsRegistry()->registerStat(&d_numAssertionsPre);
smtStatisticsRegistry()->registerStat(&d_numAssertionsPost);
- smtStatisticsRegistry()->registerStat(&d_proofsSize);
smtStatisticsRegistry()->registerStat(&d_checkModelTime);
- smtStatisticsRegistry()->registerStat(&d_lfscCheckProofTime);
smtStatisticsRegistry()->registerStat(&d_checkUnsatCoreTime);
smtStatisticsRegistry()->registerStat(&d_solveTime);
smtStatisticsRegistry()->registerStat(&d_pushPopTime);
@@ -56,9 +52,7 @@ SmtEngineStatistics::~SmtEngineStatistics()
smtStatisticsRegistry()->unregisterStat(&d_cnfConversionTime);
smtStatisticsRegistry()->unregisterStat(&d_numAssertionsPre);
smtStatisticsRegistry()->unregisterStat(&d_numAssertionsPost);
- smtStatisticsRegistry()->unregisterStat(&d_proofsSize);
smtStatisticsRegistry()->unregisterStat(&d_checkModelTime);
- smtStatisticsRegistry()->unregisterStat(&d_lfscCheckProofTime);
smtStatisticsRegistry()->unregisterStat(&d_checkUnsatCoreTime);
smtStatisticsRegistry()->unregisterStat(&d_solveTime);
smtStatisticsRegistry()->unregisterStat(&d_pushPopTime);
diff --git a/src/smt/smt_engine_stats.h b/src/smt/smt_engine_stats.h
index 3463a0371..5193d173c 100644
--- a/src/smt/smt_engine_stats.h
+++ b/src/smt/smt_engine_stats.h
@@ -36,12 +36,8 @@ struct SmtEngineStatistics
IntStat d_numAssertionsPre;
/** Number of assertions after ite removal */
IntStat d_numAssertionsPost;
- /** Size of all proofs generated */
- IntStat d_proofsSize;
/** time spent in checkModel() */
TimerStat d_checkModelTime;
- /** time spent checking the proof with LFSC */
- TimerStat d_lfscCheckProofTime;
/** time spent in checkUnsatCore() */
TimerStat d_checkUnsatCoreTime;
/** time spent in PropEngine::checkSat() */
diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp
index a31d84587..706c18416 100644
--- a/src/smt/smt_solver.cpp
+++ b/src/smt/smt_solver.cpp
@@ -14,7 +14,6 @@
#include "smt/smt_solver.h"
-#include "proof/theory_proof.h"
#include "prop/prop_engine.h"
#include "smt/assertions.h"
#include "smt/preprocessor.h"
@@ -58,11 +57,6 @@ void SmtSolver::finishInit(const LogicInfo& logicInfo)
++id)
{
theory::TheoryConstructor::addTheory(d_theoryEngine.get(), id);
- // register with proof engine if applicable
-#ifdef CVC4_PROOF
- ProofManager::currentPM()->getTheoryProofEngine()->registerTheory(
- d_theoryEngine->theoryOf(id));
-#endif
}
Trace("smt-debug") << "Making prop engine..." << std::endl;
@@ -197,7 +191,7 @@ Result SmtSolver::checkSatisfiability(Assertions& as,
// set the filename on the result
Result r = Result(result, filename);
-
+
// notify our state of the check-sat result
d_state.notifyCheckSatResult(hasAssumptions, r);
diff --git a/src/smt/sygus_solver.h b/src/smt/sygus_solver.h
index 468535da1..621bea9f3 100644
--- a/src/smt/sygus_solver.h
+++ b/src/smt/sygus_solver.h
@@ -116,7 +116,7 @@ class SygusSolver
/**
* Get synth solution.
*
- * This method returns true if we are in a state immediately preceeded by
+ * This method returns true if we are in a state immediately preceded by
* a successful call to checkSynth.
*
* This method adds entries to sol_map that map functions-to-synthesize with
diff --git a/src/smt/term_formula_removal.cpp b/src/smt/term_formula_removal.cpp
index 5da190a3d..74fcda668 100644
--- a/src/smt/term_formula_removal.cpp
+++ b/src/smt/term_formula_removal.cpp
@@ -19,7 +19,7 @@
#include "expr/node_algorithm.h"
#include "expr/skolem_manager.h"
-#include "options/proof_options.h"
+#include "options/smt_options.h"
#include "proof/proof_manager.h"
using namespace std;
@@ -45,16 +45,21 @@ theory::TrustNode RemoveTermFormulas::run(
{
Node itesRemoved = run(assertion, newAsserts, newSkolems, false, false);
// In some calling contexts, not necessary to report dependence information.
- if (reportDeps
- && (options::unsatCores() || options::fewerPreprocessingHoles()))
+ if (reportDeps && options::unsatCores())
{
// new assertions have a dependence on the node
- PROOF(ProofManager::currentPM()->addDependence(itesRemoved, assertion);)
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(itesRemoved, assertion);
+ }
unsigned n = 0;
while (n < newAsserts.size())
{
- PROOF(ProofManager::currentPM()->addDependence(newAsserts[n].getProven(),
- assertion);)
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(newAsserts[n].getProven(),
+ assertion);
+ }
++n;
}
}
@@ -380,7 +385,7 @@ Node RemoveTermFormulas::replace(TNode node, bool inQuant, bool inTerm) const {
}else if( !inTerm && hasNestedTermChildren( node ) ){
// Remember if we're inside a term
inTerm = true;
- }
+ }
vector<Node> newChildren;
bool somethingChanged = false;
@@ -402,13 +407,14 @@ Node RemoveTermFormulas::replace(TNode node, bool inQuant, bool inTerm) const {
}
}
-// returns true if the children of node should be considered nested terms
+// returns true if the children of node should be considered nested terms
bool RemoveTermFormulas::hasNestedTermChildren( TNode node ) {
- return theory::kindToTheoryId(node.getKind())!=theory::THEORY_BOOL &&
- node.getKind()!=kind::EQUAL && node.getKind()!=kind::SEP_STAR &&
- node.getKind()!=kind::SEP_WAND && node.getKind()!=kind::SEP_LABEL &&
- node.getKind()!=kind::BITVECTOR_EAGER_ATOM;
- // dont' worry about FORALL or EXISTS (handled separately)
+ return theory::kindToTheoryId(node.getKind()) != theory::THEORY_BOOL
+ && node.getKind() != kind::EQUAL && node.getKind() != kind::SEP_STAR
+ && node.getKind() != kind::SEP_WAND
+ && node.getKind() != kind::SEP_LABEL
+ && node.getKind() != kind::BITVECTOR_EAGER_ATOM;
+ // dont' worry about FORALL or EXISTS (handled separately)
}
Node RemoveTermFormulas::getAxiomFor(Node n)
diff --git a/src/proof/simplify_boolean_node.h b/src/theory/arith/arith_lemma.cpp
index bb4fe2e47..9bd4df255 100644
--- a/src/proof/simplify_boolean_node.h
+++ b/src/theory/arith/arith_lemma.cpp
@@ -1,27 +1,28 @@
/********************* */
-/*! \file simplify_boolean_node.h
+/*! \file arith_lemma.cpp
** \verbatim
** Top contributors (to current version):
- ** Mathias Preiner, Guy Katz
+ ** Gereon Kremer
** This file is part of the CVC4 project.
** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
** in the top-level source directory) and their institutional affiliations.
** All rights reserved. See the file COPYING in the top-level source
** directory for licensing information.\endverbatim
**
- ** \brief Simplifying a boolean node, needed for constructing LFSC proofs.
- **
+ ** \brief ArithLemma class, derived from Lemma.
**/
-#include "cvc4_private.h"
-
-#ifndef CVC4__SIMPLIFY_BOOLEAN_NODE_H
-#define CVC4__SIMPLIFY_BOOLEAN_NODE_H
+#include "theory/arith/arith_lemma.h"
namespace CVC4 {
+namespace theory {
+namespace arith {
-Node simplifyBooleanNode(const Node &n);
-
-}/* CVC4 namespace */
+std::ostream& operator<<(std::ostream& out, const ArithLemma& al)
+{
+ return out << al.d_node;
+}
-#endif /* CVC4__SIMPLIFY_BOOLEAN_NODE_H */
+} // namespace arith
+} // namespace theory
+} // namespace CVC4
diff --git a/src/theory/arith/arith_lemma.h b/src/theory/arith/arith_lemma.h
new file mode 100644
index 000000000..a06cb83f3
--- /dev/null
+++ b/src/theory/arith/arith_lemma.h
@@ -0,0 +1,61 @@
+/********************* */
+/*! \file arith_lemma.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Gereon Kremer
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief ArithLemma class, derived from Lemma.
+ **/
+
+#ifndef CVC4__THEORY__ARITH__ARITH_LEMMA_H
+#define CVC4__THEORY__ARITH__ARITH_LEMMA_H
+
+#include <tuple>
+#include <vector>
+
+#include "expr/node.h"
+#include "theory/arith/nl/inference.h"
+#include "theory/inference_manager_buffered.h"
+#include "theory/output_channel.h"
+#include "theory/theory_inference.h"
+
+namespace CVC4 {
+namespace theory {
+namespace arith {
+
+/**
+ * The data structure for a single lemma to process by the arithmetic theory,
+ * derived from theory::SimpleTheoryLemma.
+ *
+ * This also includes the inference type that produced this lemma.
+ */
+class ArithLemma : public SimpleTheoryLemma
+{
+ public:
+ ArithLemma(Node n,
+ LemmaProperty p,
+ ProofGenerator* pg,
+ nl::Inference inf = nl::Inference::UNKNOWN)
+ : SimpleTheoryLemma(n, p, pg), d_inference(inf)
+ {
+ }
+ virtual ~ArithLemma() {}
+
+ /** The inference id for the lemma */
+ nl::Inference d_inference;
+};
+/**
+ * Writes an arithmetic lemma to a stream.
+ */
+std::ostream& operator<<(std::ostream& out, const ArithLemma& al);
+
+} // namespace arith
+} // namespace theory
+} // namespace CVC4
+
+#endif /* CVC4__THEORY__ARITH__ARITH_LEMMA_H */
diff --git a/src/theory/arith/callbacks.cpp b/src/theory/arith/callbacks.cpp
index 758a337ba..f5f8a1a10 100644
--- a/src/theory/arith/callbacks.cpp
+++ b/src/theory/arith/callbacks.cpp
@@ -16,6 +16,8 @@
**/
#include "theory/arith/callbacks.h"
+
+#include "theory/arith/proof_macros.h"
#include "theory/arith/theory_arith_private.h"
namespace CVC4 {
@@ -87,17 +89,17 @@ void FarkasConflictBuilder::reset(){
d_consequent = NullConstraint;
d_constraints.clear();
d_consequentSet = false;
- PROOF(d_farkas.clear());
+ ARITH_PROOF(d_farkas.clear());
Assert(!underConstruction());
}
/* Adds a constraint to the constraint under construction. */
void FarkasConflictBuilder::addConstraint(ConstraintCP c, const Rational& fc){
Assert(
- !PROOF_ON()
+ !ARITH_PROOF_ON()
|| (!underConstruction() && d_constraints.empty() && d_farkas.empty())
|| (underConstruction() && d_constraints.size() + 1 == d_farkas.size()));
- Assert(PROOF_ON() || d_farkas.empty());
+ Assert(ARITH_PROOF_ON() || d_farkas.empty());
Assert(c->isTrue());
if(d_consequent == NullConstraint){
@@ -105,17 +107,20 @@ void FarkasConflictBuilder::addConstraint(ConstraintCP c, const Rational& fc){
} else {
d_constraints.push_back(c);
}
- PROOF(d_farkas.push_back(fc););
- Assert(!PROOF_ON() || d_constraints.size() + 1 == d_farkas.size());
- Assert(PROOF_ON() || d_farkas.empty());
+ ARITH_PROOF(d_farkas.push_back(fc));
+ Assert(!ARITH_PROOF_ON() || d_constraints.size() + 1 == d_farkas.size());
+ Assert(ARITH_PROOF_ON() || d_farkas.empty());
}
void FarkasConflictBuilder::addConstraint(ConstraintCP c, const Rational& fc, const Rational& mult){
Assert(!mult.isZero());
- if(PROOF_ON() && !mult.isOne()){
+ if (ARITH_PROOF_ON() && !mult.isOne())
+ {
Rational prod = fc * mult;
addConstraint(c, prod);
- }else{
+ }
+ else
+ {
addConstraint(c, fc);
}
}
@@ -132,7 +137,7 @@ void FarkasConflictBuilder::makeLastConsequent(){
ConstraintCP last = d_constraints.back();
d_constraints.back() = d_consequent;
d_consequent = last;
- PROOF( std::swap( d_farkas.front(), d_farkas.back() ) );
+ ARITH_PROOF(std::swap(d_farkas.front(), d_farkas.back()));
d_consequentSet = true;
}
@@ -145,14 +150,14 @@ ConstraintCP FarkasConflictBuilder::commitConflict(){
Assert(underConstruction());
Assert(!d_constraints.empty());
Assert(
- !PROOF_ON()
+ !ARITH_PROOF_ON()
|| (!underConstruction() && d_constraints.empty() && d_farkas.empty())
|| (underConstruction() && d_constraints.size() + 1 == d_farkas.size()));
- Assert(PROOF_ON() || d_farkas.empty());
+ Assert(ARITH_PROOF_ON() || d_farkas.empty());
Assert(d_consequentSet);
ConstraintP not_c = d_consequent->getNegation();
- RationalVectorCP coeffs = NULLPROOF(&d_farkas);
+ RationalVectorCP coeffs = ARITH_NULLPROOF(&d_farkas);
not_c->impliedByFarkas(d_constraints, coeffs, true );
reset();
diff --git a/src/theory/arith/constraint.cpp b/src/theory/arith/constraint.cpp
index 6a04e70d1..081bc08a7 100644
--- a/src/theory/arith/constraint.cpp
+++ b/src/theory/arith/constraint.cpp
@@ -21,7 +21,6 @@
#include <unordered_set>
#include "base/output.h"
-#include "proof/proof.h"
#include "smt/smt_statistics_registry.h"
#include "theory/arith/arith_utilities.h"
#include "theory/arith/normal_form.h"
@@ -551,46 +550,49 @@ bool Constraint::hasTrichotomyProof() const {
void Constraint::printProofTree(std::ostream& out, size_t depth) const
{
-#if IS_PROOFS_BUILD
- const ConstraintRule& rule = getConstraintRule();
- out << std::string(2 * depth, ' ') << "* " << getVariable() << " [";
- if (hasLiteral())
+ if (ARITH_PROOF_ON())
{
- out << getLiteral();
- }
- else
- {
- out << "NOLIT";
- };
- out << "]" << ' ' << getType() << ' ' << getValue() << " (" << getProofType()
- << ")";
- if (getProofType() == FarkasAP)
- {
- out << " [";
- bool first = true;
- for (const auto& coeff : *rule.d_farkasCoefficients)
+ const ConstraintRule& rule = getConstraintRule();
+ out << std::string(2 * depth, ' ') << "* " << getVariable() << " [";
+ if (hasLiteral())
{
- if (not first)
+ out << getLiteral();
+ }
+ else
+ {
+ out << "NOLIT";
+ };
+ out << "]" << ' ' << getType() << ' ' << getValue() << " ("
+ << getProofType() << ")";
+ if (getProofType() == FarkasAP)
+ {
+ out << " [";
+ bool first = true;
+ for (const auto& coeff : *rule.d_farkasCoefficients)
{
- out << ", ";
+ if (not first)
+ {
+ out << ", ";
+ }
+ first = false;
+ out << coeff;
}
- first = false;
- out << coeff;
+ out << "]";
}
- out << "]";
- }
- out << endl;
+ out << endl;
- for (AntecedentId i = rule.d_antecedentEnd; i != AntecedentIdSentinel; --i) {
- ConstraintCP antecdent = d_database->getAntecedent(i);
- if (antecdent == NullConstraint) {
- break;
+ for (AntecedentId i = rule.d_antecedentEnd; i != AntecedentIdSentinel; --i)
+ {
+ ConstraintCP antecdent = d_database->getAntecedent(i);
+ if (antecdent == NullConstraint)
+ {
+ break;
+ }
+ antecdent->printProofTree(out, depth + 1);
}
- antecdent->printProofTree(out, depth + 1);
+ return;
}
-#else /* IS_PROOFS_BUILD */
out << "Cannot print proof. This is not a proof build." << endl;
-#endif /* IS_PROOFS_BUILD */
}
bool Constraint::sanityChecking(Node n) const {
@@ -648,8 +650,7 @@ ConstraintCP ConstraintDatabase::getAntecedent (AntecedentId p) const {
void ConstraintRule::print(std::ostream& out) const {
-
- RationalVectorCP coeffs = NULLPROOF(d_farkasCoefficients);
+ RationalVectorCP coeffs = ARITH_NULLPROOF(d_farkasCoefficients);
out << "{ConstraintRule, ";
out << d_constraint << std::endl;
out << "d_proofType= " << d_proofType << ", " << std::endl;
@@ -658,7 +659,7 @@ void ConstraintRule::print(std::ostream& out) const {
if (d_constraint != NullConstraint && d_antecedentEnd != AntecedentIdSentinel)
{
const ConstraintDatabase& database = d_constraint->getDatabase();
-
+
size_t coeffIterator = (coeffs != RationalVectorCPSentinel) ? coeffs->size()-1 : 0;
AntecedentId p = d_antecedentEnd;
// must have at least one antecedent
@@ -700,9 +701,11 @@ bool Constraint::wellFormedFarkasProof() const {
ConstraintCP antecedent = d_database->d_antecedents[p];
if(antecedent == NullConstraint) { return false; }
-#if IS_PROOFS_BUILD
- if(!PROOF_ON()){ return cr.d_farkasCoefficients == RationalVectorCPSentinel; }
- Assert(PROOF_ON());
+ if (!ARITH_PROOF_ON())
+ {
+ return cr.d_farkasCoefficients == RationalVectorCPSentinel;
+ }
+ Assert(ARITH_PROOF_ON());
if(cr.d_farkasCoefficients == RationalVectorCPSentinel){ return false; }
if(cr.d_farkasCoefficients->size() < 2){ return false; }
@@ -755,7 +758,7 @@ bool Constraint::wellFormedFarkasProof() const {
default:
return false;
}
-
+
if(coeffIterator == coeffBegin){ return false; }
--coeffIterator;
--p;
@@ -800,10 +803,6 @@ bool Constraint::wellFormedFarkasProof() const {
// 0 = lhs <= rhs < 0
return (lhs.isNull() || (Constant::isMember(lhs) && Constant(lhs).isZero()))
&& rhs.sgn() < 0;
-
-#else /* IS_PROOFS_BUILD */
- return true;
-#endif /* IS_PROOFS_BUILD */
}
ConstraintP Constraint::makeNegation(ArithVar v, ConstraintType t, const DeltaRational& r){
@@ -860,7 +859,6 @@ ConstraintDatabase::ConstraintDatabase(context::Context* satContext, context::Co
, d_one(1)
, d_negOne(-1)
{
-
}
SortedConstraintMap& ConstraintDatabase::getVariableSCM(ArithVar v) const{
@@ -1109,7 +1107,7 @@ ConstraintP ConstraintDatabase::addLiteral(TNode literal){
return isNot ? hit->getNegation(): hit;
}else{
Comparison negCmp = Comparison::parseNormalForm(negationNode);
-
+
ConstraintType negType = Constraint::constraintTypeOfComparison(negCmp);
DeltaRational negDR = negCmp.normalizedDeltaRational();
@@ -1213,7 +1211,8 @@ void Constraint::impliedByUnate(ConstraintCP imp, bool nowInConflict){
AntecedentId antecedentEnd = d_database->d_antecedents.size() - 1;
RationalVectorP coeffs;
- if(PROOF_ON()){
+ if (ARITH_PROOF_ON())
+ {
std::pair<int, int> sgns = unateFarkasSigns(getNegation(), imp);
Rational first(sgns.first);
@@ -1222,10 +1221,11 @@ void Constraint::impliedByUnate(ConstraintCP imp, bool nowInConflict){
coeffs = new RationalVector();
coeffs->push_back(first);
coeffs->push_back(second);
- } else {
+ }
+ else
+ {
coeffs = RationalVectorPSentinel;
}
-
// no need to delete coeffs the memory is owned by ConstraintRule
d_database->pushConstraintRule(ConstraintRule(this, FarkasAP, antecedentEnd, coeffs));
@@ -1233,7 +1233,7 @@ void Constraint::impliedByUnate(ConstraintCP imp, bool nowInConflict){
if(Debug.isOn("constraint::conflictCommit") && inConflict()){
Debug("constraint::conflictCommit") << "inConflict@impliedByUnate " << this << std::endl;
}
-
+
if(Debug.isOn("constraints::wffp") && !wellFormedFarkasProof()){
getConstraintRule().print(Debug("constraints::wffp"));
}
@@ -1343,7 +1343,7 @@ void Constraint::impliedByIntHole(const ConstraintCPVec& b, bool nowInConflict){
* coeffs != RationalVectorSentinal,
* coeffs->size() = a.size() + 1,
* for i in [0,a.size) : coeff[i] corresponds to a[i], and
- * coeff.back() corresponds to the current constraint.
+ * coeff.back() corresponds to the current constraint.
*/
void Constraint::impliedByFarkas(const ConstraintCPVec& a, RationalVectorCP coeffs, bool nowInConflict){
Debug("constraints::pf") << "impliedByFarkas(" << this;
@@ -1359,10 +1359,9 @@ void Constraint::impliedByFarkas(const ConstraintCPVec& a, RationalVectorCP coef
Assert(negationHasProof() == nowInConflict);
Assert(allHaveProof(a));
- Assert(PROOF_ON() == (coeffs != RationalVectorCPSentinel));
- // !PROOF_ON() => coeffs == RationalVectorCPSentinel
- // PROOF_ON() => coeffs->size() == a.size() + 1
- Assert(!PROOF_ON() || coeffs->size() == a.size() + 1);
+ Assert(ARITH_PROOF_ON() == (coeffs != RationalVectorCPSentinel));
+ Assert(!ARITH_PROOF_ON() || coeffs->size() == a.size() + 1);
+
Assert(a.size() >= 1);
d_database->d_antecedents.push_back(NullConstraint);
@@ -1374,10 +1373,13 @@ void Constraint::impliedByFarkas(const ConstraintCPVec& a, RationalVectorCP coef
AntecedentId antecedentEnd = d_database->d_antecedents.size() - 1;
RationalVectorCP coeffsCopy;
- if(PROOF_ON()){
+ if (ARITH_PROOF_ON())
+ {
Assert(coeffs != RationalVectorCPSentinel);
coeffsCopy = new RationalVector(*coeffs);
- } else {
+ }
+ else
+ {
coeffsCopy = RationalVectorCPSentinel;
}
d_database->pushConstraintRule(ConstraintRule(this, FarkasAP, antecedentEnd, coeffsCopy));
diff --git a/src/theory/arith/constraint.h b/src/theory/arith/constraint.h
index b32616a04..3caccdebd 100644
--- a/src/theory/arith/constraint.h
+++ b/src/theory/arith/constraint.h
@@ -75,9 +75,9 @@
#ifndef CVC4__THEORY__ARITH__CONSTRAINT_H
#define CVC4__THEORY__ARITH__CONSTRAINT_H
-#include <unordered_map>
#include <list>
#include <set>
+#include <unordered_map>
#include <vector>
#include "base/configuration_private.h"
@@ -85,12 +85,12 @@
#include "context/cdqueue.h"
#include "context/context.h"
#include "expr/node.h"
-#include "proof/proof.h"
#include "theory/arith/arithvar.h"
#include "theory/arith/callbacks.h"
#include "theory/arith/congruence_manager.h"
#include "theory/arith/constraint_forward.h"
#include "theory/arith/delta_rational.h"
+#include "theory/arith/proof_macros.h"
namespace CVC4 {
namespace theory {
@@ -252,11 +252,11 @@ struct PerVariableDatabase{
}
};
-
/**
* If proofs are on, there is a vector of rationals for farkas coefficients.
- * This is the owner of the memory for the vector, and calls delete upon cleanup.
- *
+ * This is the owner of the memory for the vector, and calls delete upon
+ * cleanup.
+ *
*/
struct ConstraintRule {
ConstraintP d_constraint;
@@ -302,17 +302,13 @@ struct ConstraintRule {
* We do however use all of the constraints by requiring non-zero
* coefficients.
*/
-#if IS_PROOFS_BUILD
RationalVectorCP d_farkasCoefficients;
-#endif /* IS_PROOFS_BUILD */
ConstraintRule()
: d_constraint(NullConstraint)
, d_proofType(NoAP)
, d_antecedentEnd(AntecedentIdSentinel)
{
-#if IS_PROOFS_BUILD
d_farkasCoefficients = RationalVectorCPSentinel;
-#endif /* IS_PROOFS_BUILD */
}
ConstraintRule(ConstraintP con, ArithProofType pt)
@@ -320,18 +316,14 @@ struct ConstraintRule {
, d_proofType(pt)
, d_antecedentEnd(AntecedentIdSentinel)
{
-#if IS_PROOFS_BUILD
d_farkasCoefficients = RationalVectorCPSentinel;
-#endif /* IS_PROOFS_BUILD */
}
ConstraintRule(ConstraintP con, ArithProofType pt, AntecedentId antecedentEnd)
: d_constraint(con)
, d_proofType(pt)
, d_antecedentEnd(antecedentEnd)
{
-#if IS_PROOFS_BUILD
d_farkasCoefficients = RationalVectorCPSentinel;
-#endif /* IS_PROOFS_BUILD */
}
ConstraintRule(ConstraintP con, ArithProofType pt, AntecedentId antecedentEnd, RationalVectorCP coeffs)
@@ -339,10 +331,8 @@ struct ConstraintRule {
, d_proofType(pt)
, d_antecedentEnd(antecedentEnd)
{
- Assert(PROOF_ON() || coeffs == RationalVectorCPSentinel);
-#if IS_PROOFS_BUILD
+ Assert(ARITH_PROOF_ON() || coeffs == RationalVectorCPSentinel);
d_farkasCoefficients = coeffs;
-#endif /* IS_PROOFS_BUILD */
}
void print(std::ostream& out) const;
@@ -750,7 +740,7 @@ class Constraint {
/**
* If the constraint
- * canBePropagated() and
+ * canBePropagated() and
* !assertedToTheTheory(),
* the constraint is added to the database's propagation queue.
*
@@ -789,9 +779,11 @@ class Constraint {
ConstraintP constraint = crp->d_constraint;
Assert(constraint->d_crid != ConstraintRuleIdSentinel);
constraint->d_crid = ConstraintRuleIdSentinel;
-
- PROOF(if (crp->d_farkasCoefficients != RationalVectorCPSentinel) {
- delete crp->d_farkasCoefficients;
+ ARITH_PROOF({
+ if (crp->d_farkasCoefficients != RationalVectorCPSentinel)
+ {
+ delete crp->d_farkasCoefficients;
+ }
});
}
};
@@ -876,10 +868,11 @@ class Constraint {
return getConstraintRule().d_antecedentEnd;
}
- inline RationalVectorCP getFarkasCoefficients() const {
- return NULLPROOF(getConstraintRule().d_farkasCoefficients);
+ inline RationalVectorCP getFarkasCoefficients() const
+ {
+ return ARITH_NULLPROOF(getConstraintRule().d_farkasCoefficients);
}
-
+
void debugPrint() const;
/**
@@ -1051,8 +1044,7 @@ private:
* The index in this list is the proper ordering of the proofs.
*/
ConstraintRuleList d_constraintProofs;
-
-
+
/**
* Contains the exact list of constraints that can be used for propagation.
*/
@@ -1100,9 +1092,9 @@ private:
const Rational d_one;
const Rational d_negOne;
-
+
friend class Constraint;
-
+
public:
ConstraintDatabase( context::Context* satContext,
@@ -1209,7 +1201,7 @@ public:
/** AntecendentID must be in range. */
ConstraintCP getAntecedent(AntecedentId p) const;
-
+
private:
/** returns true if cons is now in conflict. */
bool handleUnateProp(ConstraintP ant, ConstraintP cons);
diff --git a/src/theory/arith/inference_manager.cpp b/src/theory/arith/inference_manager.cpp
new file mode 100644
index 000000000..bb0bb494e
--- /dev/null
+++ b/src/theory/arith/inference_manager.cpp
@@ -0,0 +1,144 @@
+/********************* */
+/*! \file inference_manager.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Gereon Kremer
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of the inference manager for the theory of strings.
+ **/
+
+#include "theory/arith/inference_manager.h"
+
+#include "options/arith_options.h"
+#include "theory/arith/theory_arith.h"
+#include "theory/rewriter.h"
+
+namespace CVC4 {
+namespace theory {
+namespace arith {
+
+InferenceManager::InferenceManager(TheoryArith& ta,
+ ArithState& astate,
+ ProofNodeManager* pnm)
+ : InferenceManagerBuffered(ta, astate, pnm), d_lemmasPp(ta.getUserContext())
+{
+}
+
+void InferenceManager::addPendingArithLemma(std::unique_ptr<ArithLemma> lemma,
+ bool isWaiting)
+{
+ lemma->d_node = Rewriter::rewrite(lemma->d_node);
+ if (hasCachedLemma(lemma->d_node, lemma->d_property))
+ {
+ return;
+ }
+ if (isEntailedFalse(*lemma))
+ {
+ if (isWaiting)
+ {
+ d_waitingLem.clear();
+ }
+ else
+ {
+ d_pendingLem.clear();
+ d_theoryState.notifyInConflict();
+ }
+ }
+ if (isWaiting)
+ {
+ d_waitingLem.emplace_back(std::move(lemma));
+ }
+ else
+ {
+ d_pendingLem.emplace_back(std::move(lemma));
+ }
+}
+void InferenceManager::addPendingArithLemma(const ArithLemma& lemma,
+ bool isWaiting)
+{
+ addPendingArithLemma(std::unique_ptr<ArithLemma>(new ArithLemma(lemma)),
+ isWaiting);
+}
+void InferenceManager::addPendingArithLemma(const Node& lemma,
+ nl::Inference inftype,
+ bool isWaiting)
+{
+ addPendingArithLemma(std::unique_ptr<ArithLemma>(new ArithLemma(
+ lemma, LemmaProperty::NONE, nullptr, inftype)),
+ isWaiting);
+}
+
+void InferenceManager::flushWaitingLemmas()
+{
+ for (auto& lem : d_waitingLem)
+ {
+ d_pendingLem.emplace_back(std::move(lem));
+ }
+ d_waitingLem.clear();
+}
+
+void InferenceManager::addConflict(const Node& conf, nl::Inference inftype)
+{
+ conflict(Rewriter::rewrite(conf));
+}
+
+std::size_t InferenceManager::numWaitingLemmas() const
+{
+ return d_waitingLem.size();
+}
+
+bool InferenceManager::hasCachedLemma(TNode lem, LemmaProperty p)
+{
+ if (isLemmaPropertyPreprocess(p))
+ {
+ return d_lemmasPp.find(lem) != d_lemmasPp.end();
+ }
+ return TheoryInferenceManager::hasCachedLemma(lem, p);
+}
+
+bool InferenceManager::cacheLemma(TNode lem, LemmaProperty p)
+{
+ if (isLemmaPropertyPreprocess(p))
+ {
+ if (d_lemmasPp.find(lem) != d_lemmasPp.end())
+ {
+ return false;
+ }
+ d_lemmasPp.insert(lem);
+ return true;
+ }
+ return TheoryInferenceManager::cacheLemma(lem, p);
+}
+
+bool InferenceManager::isEntailedFalse(const ArithLemma& lem)
+{
+ if (options::nlExtEntailConflicts())
+ {
+ Node ch_lemma = lem.d_node.negate();
+ ch_lemma = Rewriter::rewrite(ch_lemma);
+ Trace("arith-inf-manager") << "InferenceManager::Check entailment of "
+ << ch_lemma << "..." << std::endl;
+
+ std::pair<bool, Node> et = d_theory.getValuation().entailmentCheck(
+ options::TheoryOfMode::THEORY_OF_TYPE_BASED, ch_lemma);
+ Trace("arith-inf-manager") << "entailment test result : " << et.first << " "
+ << et.second << std::endl;
+ if (et.first)
+ {
+ Trace("arith-inf-manager")
+ << "*** Lemma entailed to be in conflict : " << lem.d_node
+ << std::endl;
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace arith
+} // namespace theory
+} // namespace CVC4
diff --git a/src/theory/arith/inference_manager.h b/src/theory/arith/inference_manager.h
new file mode 100644
index 000000000..1c0678e60
--- /dev/null
+++ b/src/theory/arith/inference_manager.h
@@ -0,0 +1,116 @@
+/********************* */
+/*! \file inference_manager.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Gereon Kremer
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Customized inference manager for the theory of nonlinear arithmetic
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__THEORY__ARITH__INFERENCE_MANAGER_H
+#define CVC4__THEORY__ARITH__INFERENCE_MANAGER_H
+
+#include <map>
+#include <vector>
+
+#include "theory/arith/arith_lemma.h"
+#include "theory/arith/arith_state.h"
+#include "theory/arith/nl/inference.h"
+#include "theory/arith/nl/nl_lemma_utils.h"
+#include "theory/inference_manager_buffered.h"
+
+namespace CVC4 {
+namespace theory {
+namespace arith {
+
+class TheoryArith;
+
+/**
+ * A specialized variant of the InferenceManagerBuffered, tailored to the
+ * arithmetic theory.
+ *
+ * It adds some convenience methods to send ArithLemma and adds a mechanism for
+ * waiting lemmas that can be flushed into the pending lemmas of the this
+ * buffered inference manager.
+ * It also extends the caching mechanism of TheoryInferenceManager to cache
+ * preprocessing lemmas and non-preprocessing lemmas separately. For the former,
+ * it uses the cache provided by the TheoryInferenceManager base class.
+ */
+class InferenceManager : public InferenceManagerBuffered
+{
+ using NodeSet = context::CDHashSet<Node, NodeHashFunction>;
+
+ public:
+ InferenceManager(TheoryArith& ta, ArithState& astate, ProofNodeManager* pnm);
+
+ /**
+ * Add a lemma as pending lemma to the this inference manager.
+ * If isWaiting is true, the lemma is first stored as waiting lemma and only
+ * added as pending lemma when calling flushWaitingLemmas.
+ */
+ void addPendingArithLemma(std::unique_ptr<ArithLemma> lemma,
+ bool isWaiting = false);
+ /**
+ * Add a lemma as pending lemma to the this inference manager.
+ * If isWaiting is true, the lemma is first stored as waiting lemma and only
+ * added as pending lemma when calling flushWaitingLemmas.
+ */
+ void addPendingArithLemma(const ArithLemma& lemma, bool isWaiting = false);
+ /**
+ * Add a lemma as pending lemma to the this inference manager.
+ * If isWaiting is true, the lemma is first stored as waiting lemma and only
+ * added as pending lemma when calling flushWaitingLemmas.
+ */
+ void addPendingArithLemma(const Node& lemma,
+ nl::Inference inftype,
+ bool isWaiting = false);
+
+ /**
+ * Flush all waiting lemmas to the this inference manager (as pending
+ * lemmas). To actually send them, call doPendingLemmas() afterwards.
+ */
+ void flushWaitingLemmas();
+
+ /** Add a conflict to the this inference manager. */
+ void addConflict(const Node& conf, nl::Inference inftype);
+
+ /** Returns the number of pending lemmas. */
+ std::size_t numWaitingLemmas() const;
+
+ /** Checks whether the given lemma is already present in the cache. */
+ virtual bool hasCachedLemma(TNode lem, LemmaProperty p) override;
+
+ protected:
+ /**
+ * Adds the given lemma to the cache. Returns true if it has not been in the
+ * cache yet.
+ */
+ virtual bool cacheLemma(TNode lem, LemmaProperty p) override;
+
+ private:
+ /**
+ * Checks whether the lemma is entailed to be false. In this case, it is a
+ * conflict.
+ */
+ bool isEntailedFalse(const ArithLemma& lem);
+
+ /** The waiting lemmas. */
+ std::vector<std::unique_ptr<ArithLemma>> d_waitingLem;
+
+ /** cache of all preprocessed lemmas sent on the output channel
+ * (user-context-dependent) */
+ NodeSet d_lemmasPp;
+};
+
+} // namespace arith
+} // namespace theory
+} // namespace CVC4
+
+#endif
diff --git a/src/theory/arith/linear_equality.cpp b/src/theory/arith/linear_equality.cpp
index 7eb2f3f9e..3c4f678a2 100644
--- a/src/theory/arith/linear_equality.cpp
+++ b/src/theory/arith/linear_equality.cpp
@@ -510,11 +510,11 @@ void LinearEqualityModule::propagateBasicFromRow(ConstraintP c){
RowIndex ridx = d_tableau.basicToRowIndex(basic);
ConstraintCPVec bounds;
- RationalVectorP coeffs = NULLPROOF(new RationalVector());
+ RationalVectorP coeffs = ARITH_NULLPROOF(new RationalVector());
propagateRow(bounds, ridx, upperBound, c, coeffs);
c->impliedByFarkas(bounds, coeffs, false);
c->tryToPropagate();
-
+
if(coeffs != RationalVectorPSentinel) { delete coeffs; }
}
@@ -524,9 +524,9 @@ void LinearEqualityModule::propagateBasicFromRow(ConstraintP c){
* The proof is in terms of the other constraints and the negation of c, ~c.
*
* A row has the form:
- * sum a_i * x_i = 0
+ * sum a_i * x_i = 0
* or
- * sx + sum r y + sum q z = 0
+ * sx + sum r y + sum q z = 0
* where r > 0 and q < 0.
*
* If rowUp, we are proving c
@@ -555,7 +555,7 @@ void LinearEqualityModule::propagateRow(ConstraintCPVec& into, RowIndex ridx, bo
Assert(farkas->empty());
farkas->push_back(Rational(0));
}
-
+
ArithVar v = c->getVariable();
Debug("arith::propagateRow") << "LinearEqualityModule::propagateRow("
<< ridx << ", " << rowUp << ", " << v << ") start" << endl;
@@ -563,7 +563,7 @@ void LinearEqualityModule::propagateRow(ConstraintCPVec& into, RowIndex ridx, bo
const Rational& multiple = rowUp ? d_one : d_negOne;
Debug("arith::propagateRow") << "multiple: " << multiple << endl;
-
+
Tableau::RowIterator iter = d_tableau.ridRowIterator(ridx);
for(; !iter.atEnd(); ++iter){
const Tableau::Entry& entry = *iter;
@@ -595,8 +595,8 @@ void LinearEqualityModule::propagateRow(ConstraintCPVec& into, RowIndex ridx, bo
if(farkas != RationalVectorPSentinel){
Assert(farkas->front().isZero());
Rational multAij = multiple * a_ij;
- Debug("arith::propagateRow") << "("<<multAij<<") ";
- farkas->front() = multAij;
+ Debug("arith::propagateRow") << "(" << multAij << ") ";
+ farkas->front() = multAij;
}
Debug("arith::propagateRow") << c << endl;
@@ -605,10 +605,10 @@ void LinearEqualityModule::propagateRow(ConstraintCPVec& into, RowIndex ridx, bo
ConstraintCP bound = selectUb
? d_variables.getUpperBoundConstraint(nonbasic)
: d_variables.getLowerBoundConstraint(nonbasic);
-
+
if(farkas != RationalVectorPSentinel){
Rational multAij = multiple * a_ij;
- Debug("arith::propagateRow") << "("<<multAij<<") ";
+ Debug("arith::propagateRow") << "(" << multAij << ") ";
farkas->push_back(multAij);
}
Assert(bound != NullConstraint);
@@ -678,7 +678,7 @@ ConstraintP LinearEqualityModule::weakestExplanation(bool aboveUpper, DeltaRatio
* If !aboveUpper, then the conflict is with the constraint c : x_b >= l_b.
*
* A row has the form:
- * -x_b sum a_i * x_i = 0
+ * -x_b sum a_i * x_i = 0
* or
* -x_b + sum r y + sum q z = 0,
* x_b = sum r y + sum q z
@@ -724,7 +724,7 @@ ConstraintCP LinearEqualityModule::minimallyWeakConflict(bool aboveUpper, ArithV
Assert(assignment < d_variables.getLowerBound(basicVar));
surplus = d_variables.getLowerBound(basicVar) - assignment;
}
-
+
bool anyWeakenings = false;
for(Tableau::RowIterator i = d_tableau.basicRowIterator(basicVar); !i.atEnd(); ++i){
const Tableau::Entry& entry = *i;
diff --git a/src/theory/arith/nl/cad_solver.cpp b/src/theory/arith/nl/cad_solver.cpp
index b1f0894fb..ac939c341 100644
--- a/src/theory/arith/nl/cad_solver.cpp
+++ b/src/theory/arith/nl/cad_solver.cpp
@@ -95,7 +95,7 @@ std::vector<NlLemma> CadSolver::checkFull()
{
lems.emplace_back(nm->mkNode(Kind::OR, mis), Inference::CAD_CONFLICT);
}
- Trace("nl-cad") << "UNSAT with MIS: " << lems.back().d_lemma << std::endl;
+ Trace("nl-cad") << "UNSAT with MIS: " << lems.back().d_node << std::endl;
}
return lems;
#else
diff --git a/src/theory/arith/nl/nl_lemma_utils.cpp b/src/theory/arith/nl/nl_lemma_utils.cpp
index 49eec186e..58a552815 100644
--- a/src/theory/arith/nl/nl_lemma_utils.cpp
+++ b/src/theory/arith/nl/nl_lemma_utils.cpp
@@ -15,20 +15,26 @@
#include "theory/arith/nl/nl_lemma_utils.h"
#include "theory/arith/nl/nl_model.h"
+#include "theory/arith/nl/nonlinear_extension.h"
namespace CVC4 {
namespace theory {
namespace arith {
namespace nl {
-LemmaProperty NlLemma::getLemmaProperty() const
+bool NlLemma::process(TheoryInferenceManager* im)
{
- return d_preprocess ? LemmaProperty::PREPROCESS : LemmaProperty::NONE;
+ bool res = ArithLemma::process(im);
+ if (d_nlext != nullptr)
+ {
+ d_nlext->processSideEffect(*this);
+ }
+ return res;
}
std::ostream& operator<<(std::ostream& out, NlLemma& n)
{
- out << n.d_lemma;
+ out << n.d_node;
return out;
}
diff --git a/src/theory/arith/nl/nl_lemma_utils.h b/src/theory/arith/nl/nl_lemma_utils.h
index f40857fda..c6c22c3c6 100644
--- a/src/theory/arith/nl/nl_lemma_utils.h
+++ b/src/theory/arith/nl/nl_lemma_utils.h
@@ -17,7 +17,9 @@
#include <tuple>
#include <vector>
+
#include "expr/node.h"
+#include "theory/arith/arith_lemma.h"
#include "theory/arith/nl/inference.h"
#include "theory/output_channel.h"
@@ -27,6 +29,7 @@ namespace arith {
namespace nl {
class NlModel;
+class NonlinearExtension;
/**
* The data structure for a single lemma to process by the non-linear solver,
@@ -39,19 +42,24 @@ class NlModel;
* - A set of secant points to record (for transcendental secant plane
* inferences).
*/
-struct NlLemma
+class NlLemma : public ArithLemma
{
- NlLemma(Node lem, Inference id = Inference::UNKNOWN)
- : d_id(id), d_lemma(lem), d_preprocess(false)
+ public:
+ NlLemma(Node n,
+ LemmaProperty p,
+ ProofGenerator* pg,
+ nl::Inference inf = nl::Inference::UNKNOWN)
+ : ArithLemma(n, p, pg, inf)
+ {
+ }
+ NlLemma(Node n, nl::Inference inf = nl::Inference::UNKNOWN)
+ : ArithLemma(n, LemmaProperty::NONE, nullptr, inf)
{
}
~NlLemma() {}
- /** The inference id for the lemma */
- Inference d_id;
- /** The lemma */
- Node d_lemma;
- /** Whether to preprocess the lemma */
- bool d_preprocess;
+
+ bool process(TheoryInferenceManager* im) override;
+
/** secant points to add
*
* A member (tf, d, c) in this vector indicates that point c should be added
@@ -62,8 +70,8 @@ struct NlLemma
* Cimatti et al., CADE 2017.
*/
std::vector<std::tuple<Node, unsigned, Node> > d_secantPoint;
- /** get lemma property (preprocess or none) */
- LemmaProperty getLemmaProperty() const;
+
+ NonlinearExtension* d_nlext;
};
/**
* Writes a non-linear lemma to a stream.
diff --git a/src/theory/arith/nl/nl_model.cpp b/src/theory/arith/nl/nl_model.cpp
index cc10d6659..fbc38fbc2 100644
--- a/src/theory/arith/nl/nl_model.cpp
+++ b/src/theory/arith/nl/nl_model.cpp
@@ -16,6 +16,7 @@
#include "expr/node_algorithm.h"
#include "options/arith_options.h"
+#include "options/smt_options.h"
#include "options/theory_options.h"
#include "theory/arith/arith_msum.h"
#include "theory/arith/arith_utilities.h"
@@ -325,7 +326,7 @@ bool NlModel::checkModel(const std::vector<Node>& assertions,
Node v = cb.first;
Node pred = nm->mkNode(AND, nm->mkNode(GEQ, v, l), nm->mkNode(GEQ, u, v));
pred = nm->mkNode(OR, mg.negate(), pred);
- lemmas.push_back(pred);
+ lemmas.emplace_back(pred);
}
}
return true;
diff --git a/src/theory/arith/nl/nl_solver.cpp b/src/theory/arith/nl/nl_solver.cpp
index 521539674..6c20eec76 100644
--- a/src/theory/arith/nl/nl_solver.cpp
+++ b/src/theory/arith/nl/nl_solver.cpp
@@ -843,7 +843,7 @@ std::vector<NlLemma> NlSolver::checkMonomialMagnitude(unsigned c)
std::vector<NlLemma> nr_lemmas;
for (unsigned i = 0; i < lemmas.size(); i++)
{
- if (r_lemmas.find(lemmas[i].d_lemma) == r_lemmas.end())
+ if (r_lemmas.find(lemmas[i].d_node) == r_lemmas.end())
{
nr_lemmas.push_back(lemmas[i]);
}
diff --git a/src/theory/arith/nl/nonlinear_extension.cpp b/src/theory/arith/nl/nonlinear_extension.cpp
index 8535396e7..ada6aa11a 100644
--- a/src/theory/arith/nl/nonlinear_extension.cpp
+++ b/src/theory/arith/nl/nonlinear_extension.cpp
@@ -166,9 +166,9 @@ void NonlinearExtension::sendLemmas(const std::vector<NlLemma>& out)
{
for (const NlLemma& nlem : out)
{
- Node lem = nlem.d_lemma;
- LemmaProperty p = nlem.getLemmaProperty();
- Trace("nl-ext-lemma") << "NonlinearExtension::Lemma : " << nlem.d_id
+ Node lem = nlem.d_node;
+ LemmaProperty p = nlem.d_property;
+ Trace("nl-ext-lemma") << "NonlinearExtension::Lemma : " << nlem.d_inference
<< " : " << lem << std::endl;
d_containing.getOutputChannel().lemma(lem, p);
// process the side effect
@@ -182,7 +182,7 @@ void NonlinearExtension::sendLemmas(const std::vector<NlLemma>& out)
{
d_lemmas.insert(lem);
}
- d_stats.d_inferences << nlem.d_id;
+ d_stats.d_inferences << nlem.d_inference;
}
}
@@ -210,14 +210,15 @@ void NonlinearExtension::computeRelevantAssertions(
unsigned NonlinearExtension::filterLemma(NlLemma lem, std::vector<NlLemma>& out)
{
Trace("nl-ext-lemma-debug")
- << "NonlinearExtension::Lemma pre-rewrite : " << lem.d_lemma << std::endl;
- lem.d_lemma = Rewriter::rewrite(lem.d_lemma);
+ << "NonlinearExtension::Lemma pre-rewrite : " << lem.d_node << std::endl;
+ lem.d_node = Rewriter::rewrite(lem.d_node);
// get the proper cache
- NodeSet& lcache = lem.d_preprocess ? d_lemmasPp : d_lemmas;
- if (lcache.find(lem.d_lemma) != lcache.end())
+ NodeSet& lcache =
+ isLemmaPropertyPreprocess(lem.d_property) ? d_lemmasPp : d_lemmas;
+ if (lcache.find(lem.d_node) != lcache.end())
{
Trace("nl-ext-lemma-debug")
- << "NonlinearExtension::Lemma duplicate : " << lem.d_lemma << std::endl;
+ << "NonlinearExtension::Lemma duplicate : " << lem.d_node << std::endl;
return 0;
}
out.emplace_back(lem);
@@ -232,7 +233,7 @@ unsigned NonlinearExtension::filterLemmas(std::vector<NlLemma>& lemmas,
// check if any are entailed to be false
for (const NlLemma& lem : lemmas)
{
- Node ch_lemma = lem.d_lemma.negate();
+ Node ch_lemma = lem.d_node.negate();
ch_lemma = Rewriter::rewrite(ch_lemma);
Trace("nl-ext-et-debug")
<< "Check entailment of " << ch_lemma << "..." << std::endl;
@@ -243,7 +244,7 @@ unsigned NonlinearExtension::filterLemmas(std::vector<NlLemma>& lemmas,
if (et.first)
{
Trace("nl-ext-et") << "*** Lemma entailed to be in conflict : "
- << lem.d_lemma << std::endl;
+ << lem.d_node << std::endl;
// return just this lemma
if (filterLemma(lem, out) > 0)
{
diff --git a/src/theory/arith/nl/nonlinear_extension.h b/src/theory/arith/nl/nonlinear_extension.h
index ee58a9e2e..d035b1056 100644
--- a/src/theory/arith/nl/nonlinear_extension.h
+++ b/src/theory/arith/nl/nonlinear_extension.h
@@ -172,6 +172,9 @@ class NonlinearExtension
*/
void presolve();
+ /** Process side effect se */
+ void processSideEffect(const NlLemma& se);
+
private:
/** Model-based refinement
*
@@ -274,8 +277,6 @@ class NonlinearExtension
* Send lemmas in out on the output channel of theory of arithmetic.
*/
void sendLemmas(const std::vector<NlLemma>& out);
- /** Process side effect se */
- void processSideEffect(const NlLemma& se);
/** cache of all lemmas sent on the output channel (user-context-dependent) */
NodeSet d_lemmas;
diff --git a/src/theory/arith/nl/transcendental_solver.cpp b/src/theory/arith/nl/transcendental_solver.cpp
index 321818b94..b2ef16459 100644
--- a/src/theory/arith/nl/transcendental_solver.cpp
+++ b/src/theory/arith/nl/transcendental_solver.cpp
@@ -212,8 +212,8 @@ void TranscendentalSolver::initLastCall(const std::vector<Node>& assertions,
// note we must do preprocess on this lemma
Trace("nl-ext-lemma") << "NonlinearExtension::Lemma : purify : " << lem
<< std::endl;
- NlLemma nlem(lem, Inference::T_PURIFY_ARG);
- nlem.d_preprocess = true;
+ NlLemma nlem(
+ lem, LemmaProperty::PREPROCESS, nullptr, Inference::T_PURIFY_ARG);
lems.emplace_back(nlem);
}
diff --git a/src/theory/arith/proof_macros.h b/src/theory/arith/proof_macros.h
new file mode 100644
index 000000000..6cc1b3b15
--- /dev/null
+++ b/src/theory/arith/proof_macros.h
@@ -0,0 +1,34 @@
+/********************* */
+/*! \file proof_macros.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Alex Ozdemir
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Macros which run code when the old or new proof system is enabled,
+ ** or unsat cores are enabled.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__THEORY__ARITH__PROOF_MACROS_H
+#define CVC4__THEORY__ARITH__PROOF_MACROS_H
+
+#include "options/smt_options.h"
+
+#define ARITH_PROOF(x) \
+ if (CVC4::options::proofNew()) \
+ { \
+ x; \
+ }
+#define ARITH_NULLPROOF(x) \
+ (CVC4::options::proofNew()) \
+ ? x \
+ : NULL
+#define ARITH_PROOF_ON() CVC4::options::proofNew()
+
+#endif // CVC4__THEORY__ARITH__PROOF_MACROS_H
diff --git a/src/theory/arith/theory_arith.cpp b/src/theory/arith/theory_arith.cpp
index ea751ca74..762634ce7 100644
--- a/src/theory/arith/theory_arith.cpp
+++ b/src/theory/arith/theory_arith.cpp
@@ -41,7 +41,6 @@ TheoryArith::TheoryArith(context::Context* c,
d_internal(
new TheoryArithPrivate(*this, c, u, out, valuation, logicInfo, pnm)),
d_ppRewriteTimer("theory::arith::ppRewriteTimer"),
- d_proofRecorder(nullptr),
d_astate(*d_internal, c, u, valuation)
{
smtStatisticsRegistry()->registerStat(&d_ppRewriteTimer);
diff --git a/src/theory/arith/theory_arith.h b/src/theory/arith/theory_arith.h
index bfe30db61..6adf8f66a 100644
--- a/src/theory/arith/theory_arith.h
+++ b/src/theory/arith/theory_arith.h
@@ -18,7 +18,6 @@
#pragma once
#include "expr/node.h"
-#include "proof/arith_proof_recorder.h"
#include "theory/arith/arith_state.h"
#include "theory/arith/theory_arith_private_forward.h"
#include "theory/theory.h"
@@ -41,11 +40,6 @@ class TheoryArith : public Theory {
TimerStat d_ppRewriteTimer;
- /**
- * @brief Where to store Farkas proofs of lemmas
- */
- proof::ArithProofRecorder * d_proofRecorder;
-
public:
TheoryArith(context::Context* c,
context::UserContext* u,
@@ -110,11 +104,6 @@ class TheoryArith : public Theory {
std::pair<bool, Node> entailmentCheck(TNode lit) override;
- void setProofRecorder(proof::ArithProofRecorder* proofRecorder)
- {
- d_proofRecorder = proofRecorder;
- }
-
private:
/** The state object wrapping TheoryArithPrivate */
ArithState d_astate;
diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp
index 8ca99d369..8a780116c 100644
--- a/src/theory/arith/theory_arith_private.cpp
+++ b/src/theory/arith/theory_arith_private.cpp
@@ -624,7 +624,7 @@ bool TheoryArithPrivate::AssertLower(ConstraintP constraint){
ConstraintP ubc = d_partialModel.getUpperBoundConstraint(x_i);
ConstraintP negation = constraint->getNegation();
negation->impliedByUnate(ubc, true);
-
+
raiseConflict(constraint);
++(d_statistics.d_statAssertLowerConflicts);
@@ -757,7 +757,7 @@ bool TheoryArithPrivate::AssertUpper(ConstraintP constraint){
if(d_partialModel.greaterThanUpperBound(x_i, c_i) ){ // \upperbound(x_i) <= c_i
return false; //sat
}
-
+
// cmpToLb = \lowerbound(x_i).cmp(c_i)
int cmpToLB = d_partialModel.cmpToLowerBound(x_i, c_i);
if( cmpToLB < 0 ){ // \upperbound(x_i) < \lowerbound(x_i)
@@ -802,7 +802,7 @@ bool TheoryArithPrivate::AssertUpper(ConstraintP constraint){
++(d_statistics.d_statDisequalityConflicts);
raiseConflict(eq);
return true;
- }
+ }
}
}else if(cmpToLB > 0){
// l <= x <= u and l < u
@@ -1291,8 +1291,10 @@ void TheoryArithPrivate::setupVariableList(const VarList& vl){
}else{
if (d_nonlinearExtension == nullptr)
{
- if( vlNode.getKind()==kind::EXPONENTIAL || vlNode.getKind()==kind::SINE ||
- vlNode.getKind()==kind::COSINE || vlNode.getKind()==kind::TANGENT ){
+ if (vlNode.getKind() == kind::EXPONENTIAL
+ || vlNode.getKind() == kind::SINE || vlNode.getKind() == kind::COSINE
+ || vlNode.getKind() == kind::TANGENT)
+ {
d_nlIncomplete = true;
}
}
@@ -1737,7 +1739,6 @@ ConstraintP TheoryArithPrivate::constraintFromFactQueue(){
} else {
Debug("arith::constraint") << "already has proof: " << constraint->externalExplainByAssertions() << endl;
}
-
if(Debug.isOn("arith::negatedassumption") && inConflict){
ConstraintP negation = constraint->getNegation();
@@ -1905,7 +1906,7 @@ void TheoryArithPrivate::outputConflicts(){
Debug("arith::conflict") << "outputting conflicts" << std::endl;
Assert(anyConflict());
static unsigned int conflicts = 0;
-
+
if(!conflictQueueEmpty()){
Assert(!d_conflicts.empty());
for(size_t i = 0, i_end = d_conflicts.size(); i < i_end; ++i){
@@ -1923,35 +1924,6 @@ void TheoryArithPrivate::outputConflicts(){
++conflicts;
Debug("arith::conflict") << "d_conflicts[" << i << "] " << conflict
<< " 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 j = 0, nchildren = conflict.getNumChildren(); j < nchildren;
- ++j)
- {
- conflictInFarkasCoefficientOrder
- << conflict[conflict.getNumChildren() - j - 1];
- }
-
- if (Debug.isOn("arith::pf::tree")) {
- confConstraint->printProofTree(Debug("arith::pf::tree"));
- confConstraint->getNegation()->printProofTree(Debug("arith::pf::tree"));
- }
-
- Assert(conflict.getNumChildren() == pf.d_farkasCoefficients->size());
- if (confConstraint->hasSimpleFarkasProof()
- && confConstraint->getNegation()->isPossiblyTightenedAssumption())
- {
- 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;
@@ -2190,7 +2162,6 @@ std::pair<ConstraintP, ArithVar> TheoryArithPrivate::replayGetConstraint(const D
return make_pair(imp, added);
}
}
-
ConstraintP newc = d_constraintDatabase.getConstraint(v, t, dr);
d_replayConstraints.push_back(newc);
@@ -2337,7 +2308,7 @@ void TheoryArithPrivate::tryBranchCut(ApproximateSimplex* approx, int nid, Branc
// ConstraintCPVec& back = conflicts.back();
// back.push_back(conflicting);
// back.push_back(negConflicting);
-
+
// // remove the floor/ceiling contraint implied by bcneg
// Constraint::assertionFringe(back);
}
@@ -2375,14 +2346,15 @@ void TheoryArithPrivate::replayAssert(ConstraintP c) {
}else{
Debug("approx::replayAssert") << "replayAssert " << c << " has explanation" << endl;
}
- Debug("approx::replayAssert") << "replayAssertion " << c << endl;
+ Debug("approx::replayAssert") << "replayAssertion " << c << endl;
if(inConflict){
raiseConflict(c);
}else{
assertionCases(c);
}
}else{
- Debug("approx::replayAssert") << "replayAssert " << c << " already asserted" << endl;
+ Debug("approx::replayAssert")
+ << "replayAssert " << c << " already asserted" << endl;
}
}
@@ -2551,7 +2523,7 @@ std::vector<ConstraintCPVec> TheoryArithPrivate::replayLogRec(ApproximateSimplex
SimplexDecisionProcedure& simplex = selectSimplex(true);
simplex.findModel(false);
- // can change d_qflraStatus
+ // can change d_qflraStatus
d_linEq.stopTrackingBoundCounts();
d_partialModel.startQueueingBoundCounts();
@@ -3101,13 +3073,13 @@ bool TheoryArithPrivate::solveRealRelaxation(Theory::Effort effortLevel){
<< " " << useApprox
<< " " << safeToCallApprox()
<< endl;
-
+
bool noPivotLimitPass1 = noPivotLimit && !useApprox;
d_qflraStatus = simplex.findModel(noPivotLimitPass1);
Debug("TheoryArithPrivate::solveRealRelaxation")
<< "solveRealRelaxation()" << " pass1 " << d_qflraStatus << endl;
-
+
if(d_qflraStatus == Result::SAT_UNKNOWN && useApprox && safeToCallApprox()){
// pass2: fancy-final
static const int32_t relaxationLimit = 10000;
@@ -3275,7 +3247,6 @@ bool TheoryArithPrivate::solveRealRelaxation(Theory::Effort effortLevel){
// if(!useFancyFinal){
// d_qflraStatus = simplex.findModel(noPivotLimit);
// }else{
-
// if(d_qflraStatus == Result::SAT_UNKNOWN){
// //Message() << "got sat unknown" << endl;
@@ -3711,7 +3682,7 @@ Node TheoryArithPrivate::branchIntegerVariable(ArithVar x) const {
Integer ceil_d = d.ceiling();
Rational f = r - floor_d;
// Multiply by -1 to get abs value.
- Rational c = (r - ceil_d) * (-1);
+ Rational c = (r - ceil_d) * (-1);
Integer nearest = (c > f) ? floor_d : ceil_d;
// Prioritize trying a simple rounding of the real solution first,
@@ -4140,8 +4111,8 @@ bool TheoryArithPrivate::collectModelInfo(TheoryModel* m)
Debug("arith::collectModelInfo") << "collectModelInfo() begin " << endl;
std::set<Node> termSet;
- d_containing.computeRelevantTerms(termSet);
-
+ const std::set<Kind>& irrKinds = m->getIrrelevantKinds();
+ d_containing.computeAssertedTerms(termSet, irrKinds, true);
// Delta lasts at least the duration of the function call
const Rational& delta = d_partialModel.getDelta();
@@ -4372,7 +4343,7 @@ bool TheoryArithPrivate::propagateCandidateBound(ArithVar basic, bool upperBound
//We are only going to recreate the functionality for now.
//In the future this can be improved to generate a temporary constraint
//if none exists.
- //Experiment with doing this everytime or only when the new constraint
+ //Experiment with doing this every time or only when the new constraint
//implies an unknown fact.
ConstraintType t = upperBound ? UpperBound : LowerBound;
@@ -4651,7 +4622,6 @@ bool TheoryArithPrivate::tryToPropagate(RowIndex ridx, bool rowUp, ArithVar v, b
ConstraintP implied = d_constraintDatabase.getBestImpliedBound(v, t, bound);
if(implied != NullConstraint){
-
return rowImplicationCanBeApplied(ridx, rowUp, implied);
}
}
@@ -4699,9 +4669,8 @@ bool TheoryArithPrivate::rowImplicationCanBeApplied(RowIndex ridx, bool rowUp, C
if( !assertedToTheTheory && canBePropagated && !hasProof ){
ConstraintCPVec explain;
-
- PROOF(d_farkasBuffer.clear());
- RationalVectorP coeffs = NULLPROOF(&d_farkasBuffer);
+ ARITH_PROOF(d_farkasBuffer.clear());
+ RationalVectorP coeffs = ARITH_NULLPROOF(&d_farkasBuffer);
// After invoking `propegateRow`:
// * coeffs[0] is for implied
@@ -4716,38 +4685,6 @@ bool TheoryArithPrivate::rowImplicationCanBeApplied(RowIndex ridx, bool rowUp, C
}
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());
- if (std::all_of(explain.begin(), explain.end(), [](ConstraintCP c) {
- return c->isAssumption() || c->hasIntTightenProof();
- }))
- {
- d_containing.d_proofRecorder->saveFarkasCoefficients(
- conflictInFarkasCoefficientOrder, coeffs);
- }
- })
outputLemma(clause);
}else{
Assert(!implied->negationHasProof());
diff --git a/src/theory/arrays/array_proof_reconstruction.cpp b/src/theory/arrays/array_proof_reconstruction.cpp
deleted file mode 100644
index abc4857e8..000000000
--- a/src/theory/arrays/array_proof_reconstruction.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-/********************* */
-/*! \file array_proof_reconstruction.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Guy Katz, Tim King
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** [[ Add lengthier description here ]]
-
- ** \todo document this file
-
-**/
-
-#include "theory/arrays/array_proof_reconstruction.h"
-
-#include <memory>
-
-namespace CVC4 {
-namespace theory {
-namespace arrays {
-
-ArrayProofReconstruction::ArrayProofReconstruction(const eq::EqualityEngine* equalityEngine)
- : d_equalityEngine(equalityEngine) {
-}
-
-void ArrayProofReconstruction::setRowMergeTag(unsigned tag) {
- d_reasonRow = tag;
-}
-
-void ArrayProofReconstruction::setRow1MergeTag(unsigned tag) {
- d_reasonRow1 = tag;
-}
-
-void ArrayProofReconstruction::setExtMergeTag(unsigned tag) {
- d_reasonExt = tag;
-}
-
-void ArrayProofReconstruction::notify(
- unsigned reasonType, Node reason, Node a, Node b,
- std::vector<TNode>& equalities, eq::EqProof* proof) const {
- Debug("pf::array") << "ArrayProofReconstruction::notify( "
- << reason << ", " << a << ", " << b << std::endl;
-
-
- if (reasonType == d_reasonExt) {
- if (proof) {
- // Todo: here we assume that a=b is an assertion. We should probably call
- // explain() recursively, to explain this.
- std::shared_ptr<eq::EqProof> childProof = std::make_shared<eq::EqProof>();
- childProof->d_node = reason;
- proof->d_children.push_back(childProof);
- }
- }
-
- else if (reasonType == d_reasonRow) {
- // ROW rules mean that (i==k) OR ((a[i]:=t)[k] == a[k])
- // The equality here will be either (i == k) because ((a[i]:=t)[k] != a[k]),
- // or ((a[i]:=t)[k] == a[k]) because (i != k).
-
- if (proof) {
- if (a.getKind() == kind::SELECT) {
- // This is the case of ((a[i]:=t)[k] == a[k]) because (i != k).
-
- // The edge is ((a[i]:=t)[k], a[k]), or (a[k], (a[i]:=t)[k]). This flag should be
- // false in the first case and true in the second case.
- bool currentNodeIsUnchangedArray;
-
- Assert(a.getNumChildren() == 2);
- Assert(b.getNumChildren() == 2);
-
- if (a[0].getKind() == kind::VARIABLE || a[0].getKind() == kind::SKOLEM) {
- currentNodeIsUnchangedArray = true;
- } else if (b[0].getKind() == kind::VARIABLE || b[0].getKind() == kind::SKOLEM) {
- currentNodeIsUnchangedArray = false;
- } else {
- Assert(a[0].getKind() == kind::STORE);
- Assert(b[0].getKind() == kind::STORE);
-
- if (a[0][0] == b[0]) {
- currentNodeIsUnchangedArray = false;
- } else if (b[0][0] == a[0]) {
- currentNodeIsUnchangedArray = true;
- } else {
- Unreachable();
- }
- }
-
- Node indexOne = currentNodeIsUnchangedArray ? a[1] : a[0][1];
- Node indexTwo = currentNodeIsUnchangedArray ? b[0][1] : b[1];
-
- // Some assertions to ensure that the theory of arrays behaves as expected
- Assert(a[1] == b[1]);
- if (currentNodeIsUnchangedArray) {
- Assert(a[0] == b[0][0]);
- } else {
- Assert(a[0][0] == b[0]);
- }
-
- Debug("pf::ee") << "Getting explanation for ROW guard: "
- << indexOne << " != " << indexTwo << std::endl;
-
- std::shared_ptr<eq::EqProof> childProof =
- std::make_shared<eq::EqProof>();
- d_equalityEngine->explainEquality(indexOne, indexTwo, false, equalities,
- childProof.get());
-
- // It could be that the guard condition is a constant disequality. In
- // this case, we need to change it to a different format.
- bool haveNegChild = false;
- for (unsigned i = 0; i < childProof->d_children.size(); ++i) {
- if (childProof->d_children[i]->d_node.getKind() == kind::NOT)
- haveNegChild = true;
- }
-
- if ((childProof->d_children.size() != 0) &&
- (childProof->d_id == theory::eq::MERGED_THROUGH_CONSTANTS || !haveNegChild)) {
- // The proof has two children, explaining why each index is a (different) constant.
- Assert(childProof->d_children.size() == 2);
-
- Node constantOne, constantTwo;
- // Each subproof explains why one of the indices is constant.
-
- if (childProof->d_children[0]->d_id == theory::eq::MERGED_THROUGH_REFLEXIVITY) {
- constantOne = childProof->d_children[0]->d_node;
- } else {
- Assert(childProof->d_children[0]->d_node.getKind() == kind::EQUAL);
- if ((childProof->d_children[0]->d_node[0] == indexOne) ||
- (childProof->d_children[0]->d_node[0] == indexTwo)) {
- constantOne = childProof->d_children[0]->d_node[1];
- } else {
- constantOne = childProof->d_children[0]->d_node[0];
- }
- }
-
- if (childProof->d_children[1]->d_id == theory::eq::MERGED_THROUGH_REFLEXIVITY) {
- constantTwo = childProof->d_children[1]->d_node;
- } else {
- Assert(childProof->d_children[1]->d_node.getKind() == kind::EQUAL);
- if ((childProof->d_children[1]->d_node[0] == indexOne) ||
- (childProof->d_children[1]->d_node[0] == indexTwo)) {
- constantTwo = childProof->d_children[1]->d_node[1];
- } else {
- constantTwo = childProof->d_children[1]->d_node[0];
- }
- }
-
- std::shared_ptr<eq::EqProof> constantDisequalityProof =
- std::make_shared<eq::EqProof>();
- constantDisequalityProof->d_id = theory::eq::MERGED_THROUGH_CONSTANTS;
- constantDisequalityProof->d_node =
- NodeManager::currentNM()->mkNode(kind::EQUAL, constantOne, constantTwo).negate();
-
- // Middle is where we need to insert the new disequality
- std::vector<std::shared_ptr<eq::EqProof>>::iterator middle =
- childProof->d_children.begin();
- ++middle;
-
- childProof->d_children.insert(middle, constantDisequalityProof);
-
- childProof->d_id = theory::eq::MERGED_THROUGH_TRANS;
- childProof->d_node =
- NodeManager::currentNM()->mkNode(kind::EQUAL, indexOne, indexTwo).negate();
- }
-
- proof->d_children.push_back(childProof);
- } else {
- // This is the case of (i == k) because ((a[i]:=t)[k] != a[k]),
-
- Node indexOne = a;
- Node indexTwo = b;
-
- Debug("pf::ee") << "The two indices are: " << indexOne << ", " << indexTwo << std::endl
- << "The reason for the edge is: " << reason << std::endl;
-
- Assert(reason.getNumChildren() == 2);
- Debug("pf::ee") << "Getting explanation for ROW guard: " << reason[1] << std::endl;
-
- std::shared_ptr<eq::EqProof> childProof =
- std::make_shared<eq::EqProof>();
- d_equalityEngine->explainEquality(reason[1][0], reason[1][1], false,
- equalities, childProof.get());
- proof->d_children.push_back(childProof);
- }
- }
-
- }
-
- else if (reasonType == d_reasonRow1) {
- // No special handling required at this time
- }
-}
-
-}/* CVC4::theory::arrays namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
diff --git a/src/theory/arrays/array_proof_reconstruction.h b/src/theory/arrays/array_proof_reconstruction.h
deleted file mode 100644
index a73b5dd08..000000000
--- a/src/theory/arrays/array_proof_reconstruction.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/********************* */
-/*! \file array_proof_reconstruction.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Paul Meng, Mathias Preiner, Tim King
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Array-specific proof construction logic to be used during the
- ** equality engine's path reconstruction
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__THEORY__ARRAYS__ARRAY_PROOF_RECONSTRUCTION_H
-#define CVC4__THEORY__ARRAYS__ARRAY_PROOF_RECONSTRUCTION_H
-
-#include "theory/uf/equality_engine.h"
-
-namespace CVC4 {
-namespace theory {
-namespace arrays {
-
-/**
- * A callback class to be invoked whenever the equality engine traverses
- * an "array-owned" edge during path reconstruction.
- */
-
-class ArrayProofReconstruction : public eq::PathReconstructionNotify {
-public:
- ArrayProofReconstruction(const eq::EqualityEngine* equalityEngine);
-
- void notify(unsigned reasonType, Node reason, Node a, Node b,
- std::vector<TNode>& equalities,
- eq::EqProof* proof) const override;
-
- void setRowMergeTag(unsigned tag);
- void setRow1MergeTag(unsigned tag);
- void setExtMergeTag(unsigned tag);
-
-private:
- /** Merge tag for ROW applications */
- unsigned d_reasonRow;
- /** Merge tag for ROW1 applications */
- unsigned d_reasonRow1;
- /** Merge tag for EXT applications */
- unsigned d_reasonExt;
-
- const eq::EqualityEngine* d_equalityEngine;
-}; /* class ArrayProofReconstruction */
-
-}/* CVC4::theory::arrays namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /* CVC4__THEORY__ARRAYS__ARRAY_PROOF_RECONSTRUCTION_H */
diff --git a/src/theory/arrays/static_fact_manager.cpp b/src/theory/arrays/static_fact_manager.cpp
deleted file mode 100644
index d2f4b75c9..000000000
--- a/src/theory/arrays/static_fact_manager.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/********************* */
-/*! \file static_fact_manager.cpp
- ** \verbatim
- ** Top contributors (to current version):
- ** Clark Barrett, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Path-compressing, backtrackable union-find using an undo
- ** stack. Refactored from the UF union-find.
- **
- ** Path-compressing, backtrackable union-find using an undo stack
- ** rather than storing items in a CDMap<>.
- **/
-
-#include <iostream>
-
-#include "base/check.h"
-#include "expr/node.h"
-#include "theory/arrays/static_fact_manager.h"
-
-using namespace std;
-
-namespace CVC4 {
-namespace theory {
-namespace arrays {
-
-bool StaticFactManager::areEq(TNode a, TNode b) {
- return (find(a) == find(b));
-}
-
-bool StaticFactManager::areDiseq(TNode a, TNode b) {
- Node af = find(a);
- Node bf = find(b);
- Node left, right;
- unsigned i;
- for (i = 0; i < d_diseq.size(); ++i) {
- left = find(d_diseq[i][0]);
- right = find(d_diseq[i][1]);
- if ((left == af && right == bf) ||
- (left == bf && right == af)) {
- return true;
- }
- }
- return false;
-}
-
-void StaticFactManager::addDiseq(TNode eq) {
- Assert(eq.getKind() == kind::EQUAL);
- d_diseq.push_back(eq);
-}
-
-void StaticFactManager::addEq(TNode eq) {
- Assert(eq.getKind() == kind::EQUAL);
- Node a = find(eq[0]);
- Node b = find(eq[1]);
-
- if( a == b) {
- return;
- }
-
- /*
- * take care of the congruence closure part
- */
-
- // make "a" the one with shorter diseqList
- // CNodeTNodesMap::iterator deq_ia = d_disequalities.find(a);
- // CNodeTNodesMap::iterator deq_ib = d_disequalities.find(b);
-
- // if(deq_ia != d_disequalities.end()) {
- // if(deq_ib == d_disequalities.end() ||
- // (*deq_ia).second->size() > (*deq_ib).second->size()) {
- // TNode tmp = a;
- // a = b;
- // b = tmp;
- // }
- // }
- // a = find(a);
- // b = find(b);
-
-
- // b becomes the canon of a
- setCanon(a, b);
-
- // deq_ia = d_disequalities.find(a);
- // map<TNode, TNode> alreadyDiseqs;
- // if(deq_ia != d_disequalities.end()) {
- // /*
- // * Collecting the disequalities of b, no need to check for conflicts
- // * since the representative of b does not change and we check all the things
- // * in a's class when we look at the diseq list of find(a)
- // */
-
- // CNodeTNodesMap::iterator deq_ib = d_disequalities.find(b);
- // if(deq_ib != d_disequalities.end()) {
- // CTNodeListAlloc* deq = (*deq_ib).second;
- // for(CTNodeListAlloc::const_iterator j = deq->begin(); j!=deq->end();
- // j++) {
- // TNode deqn = *j;
- // TNode s = deqn[0];
- // TNode t = deqn[1];
- // TNode sp = find(s);
- // TNode tp = find(t);
- // Assert(sp == b || tp == b);
- // if(sp == b) {
- // alreadyDiseqs[tp] = deqn;
- // } else {
- // alreadyDiseqs[sp] = deqn;
- // }
- // }
- // }
-
- // /*
- // * Looking for conflicts in the a disequality list. Note
- // * that at this point a and b are already merged. Also has
- // * the side effect that it adds them to the list of b (which
- // * became the canonical representative)
- // */
-
- // CTNodeListAlloc* deqa = (*deq_ia).second;
- // for(CTNodeListAlloc::const_iterator i = deqa->begin(); i!= deqa->end();
- // i++) {
- // TNode deqn = (*i);
- // Assert(deqn.getKind() == kind::EQUAL || deqn.getKind() ==
- // kind::IFF); TNode s = deqn[0]; TNode t = deqn[1]; TNode sp = find(s);
- // TNode tp = find(t);
-
- // if(find(s) == find(t)) {
- // d_conflict = deqn;
- // return;
- // }
- // Assert( sp == b || tp == b);
-
- // // make sure not to add duplicates
-
- // if(sp == b) {
- // if(alreadyDiseqs.find(tp) == alreadyDiseqs.end()) {
- // appendToDiseqList(b, deqn);
- // alreadyDiseqs[tp] = deqn;
- // }
- // } else {
- // if(alreadyDiseqs.find(sp) == alreadyDiseqs.end()) {
- // appendToDiseqList(b, deqn);
- // alreadyDiseqs[sp] = deqn;
- // }
- // }
-
- // }
- // }
-
- // // TODO: check for equality propagations
- // // a and b are find(a) and find(b) here
- // checkPropagations(a,b);
-
- // if(a.getType().isArray()) {
- // checkRowLemmas(a,b);
- // checkRowLemmas(b,a);
- // // note the change in order, merge info adds the list of
- // // the 2nd argument to the first
- // d_infoMap.mergeInfo(b, a);
- // }
-}
-
-
-}/* CVC4::theory::arrays namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
diff --git a/src/theory/arrays/static_fact_manager.h b/src/theory/arrays/static_fact_manager.h
deleted file mode 100644
index 2df4b0fda..000000000
--- a/src/theory/arrays/static_fact_manager.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/********************* */
-/*! \file static_fact_manager.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Clark Barrett, Mathias Preiner, Morgan Deters
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Path-compressing, backtrackable union-find using an undo
- ** stack. Refactored from the UF union-find.
- **
- ** Path-compressing, backtrackable union-find using an undo stack
- ** rather than storing items in a CDMap<>.
- **/
-
-#include "cvc4_private.h"
-
-#ifndef CVC4__THEORY__ARRAYS__STATIC_FACT_MANAGER_H
-#define CVC4__THEORY__ARRAYS__STATIC_FACT_MANAGER_H
-
-#include <utility>
-#include <vector>
-#include <unordered_map>
-
-#include "expr/node.h"
-
-namespace CVC4 {
-namespace theory {
-namespace arrays {
-
- class StaticFactManager {
- /** Our underlying map type. */
- typedef std::unordered_map<Node, Node, NodeHashFunction> MapType;
-
- /**
- * Our map of Nodes to their canonical representatives.
- * If a Node is not present in the map, it is its own
- * representative.
- */
- MapType d_map;
- std::vector<Node> d_diseq;
-
-public:
- StaticFactManager() {}
-
- /**
- * Return a Node's union-find representative, doing path compression.
- */
- inline TNode find(TNode n);
-
- /**
- * Return a Node's union-find representative, NOT doing path compression.
- * This is useful for Assert() statements, debug checking, and similar
- * things that you do NOT want to mutate the structure.
- */
- inline TNode debugFind(TNode n) const;
-
- /**
- * Set the canonical representative of n to newParent. They should BOTH
- * be their own canonical representatives on entry to this funciton.
- */
- inline void setCanon(TNode n, TNode newParent);
-
- bool areEq(TNode a, TNode b);
- bool areDiseq(TNode a, TNode b);
- void addDiseq(TNode eq);
- void addEq(TNode eq);
-
-};/* class StaticFactManager<> */
-
-inline TNode StaticFactManager::debugFind(TNode n) const {
- MapType::const_iterator i = d_map.find(n);
- if(i == d_map.end()) {
- return n;
- } else {
- return debugFind((*i).second);
- }
-}
-
-inline TNode StaticFactManager::find(TNode n) {
- Trace("arraysuf") << "arraysUF find of " << n << std::endl;
- MapType::iterator i = d_map.find(n);
- if(i == d_map.end()) {
- Trace("arraysuf") << "arraysUF it is rep" << std::endl;
- return n;
- } else {
- Trace("arraysuf") << "arraysUF not rep: par is " << (*i).second << std::endl;
- std::pair<TNode, TNode> pr = *i;
- // our iterator is invalidated by the recursive call to find(),
- // since it mutates the map
- TNode p = find(pr.second);
- if(p == pr.second) {
- return p;
- }
- pr.second = p;
- d_map.insert(pr);
- return p;
- }
-}
-
-inline void StaticFactManager::setCanon(TNode n, TNode newParent) {
- Assert(d_map.find(n) == d_map.end());
- Assert(d_map.find(newParent) == d_map.end());
- if(n != newParent) {
- d_map[n] = newParent;
- }
-}
-
-}/* CVC4::theory::arrays namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
-
-#endif /*CVC4__THEORY__ARRAYS__STATIC_FACT_MANAGER_H */
diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp
index b4a234748..408f4c682 100644
--- a/src/theory/arrays/theory_arrays.cpp
+++ b/src/theory/arrays/theory_arrays.cpp
@@ -23,9 +23,6 @@
#include "expr/node_algorithm.h"
#include "options/arrays_options.h"
#include "options/smt_options.h"
-#include "proof/array_proof.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
#include "smt/command.h"
#include "smt/logic_exception.h"
#include "smt/smt_statistics_registry.h"
@@ -46,7 +43,6 @@ namespace arrays {
// Use static configuration of options for now
const bool d_ccStore = false;
-const bool d_useArrTable = false;
//const bool d_eagerLemmas = false;
const bool d_preprocess = true;
const bool d_solveWrite = true;
@@ -88,7 +84,6 @@ TheoryArrays::TheoryArrays(context::Context* c,
d_isPreRegistered(c),
d_mayEqualEqualityEngine(c, name + "theory::arrays::mayEqual", true),
d_notify(*this),
- d_conflict(c, false),
d_backtracker(c),
d_infoMap(c, &d_backtracker, name),
d_mergeQueue(c),
@@ -111,7 +106,6 @@ TheoryArrays::TheoryArrays(context::Context* c,
d_readTableContext(new context::Context()),
d_arrayMerges(c),
d_inCheckModel(false),
- d_proofReconstruction(nullptr),
d_dstrat(new TheoryArraysDecisionStrategy(this)),
d_dstratInit(false)
{
@@ -179,26 +173,6 @@ void TheoryArrays::finishInit()
{
d_equalityEngine->addFunctionKind(kind::STORE);
}
- if (d_useArrTable)
- {
- d_equalityEngine->addFunctionKind(kind::ARR_TABLE_FUN);
- }
-
- d_proofReconstruction.reset(new ArrayProofReconstruction(d_equalityEngine));
- d_reasonRow = d_equalityEngine->getFreshMergeReasonType();
- d_reasonRow1 = d_equalityEngine->getFreshMergeReasonType();
- d_reasonExt = d_equalityEngine->getFreshMergeReasonType();
-
- d_proofReconstruction->setRowMergeTag(d_reasonRow);
- d_proofReconstruction->setRow1MergeTag(d_reasonRow1);
- d_proofReconstruction->setExtMergeTag(d_reasonExt);
-
- d_equalityEngine->addPathReconstructionTrigger(d_reasonRow,
- d_proofReconstruction.get());
- d_equalityEngine->addPathReconstructionTrigger(d_reasonRow1,
- d_proofReconstruction.get());
- d_equalityEngine->addPathReconstructionTrigger(d_reasonExt,
- d_proofReconstruction.get());
}
/////////////////////////////////////////////////////////////////////////////
@@ -421,7 +395,8 @@ bool TheoryArrays::propagateLit(TNode literal)
<< std::endl;
// If already in conflict, no more propagation
- if (d_conflict) {
+ if (d_state.isInConflict())
+ {
Debug("arrays") << spaces(getSatContext()->getLevel())
<< "TheoryArrays::propagateLit(" << literal
<< "): already in conflict" << std::endl;
@@ -434,43 +409,12 @@ bool TheoryArrays::propagateLit(TNode literal)
}
bool ok = d_out->propagate(literal);
if (!ok) {
- d_conflict = true;
+ d_state.notifyInConflict();
}
return ok;
}/* TheoryArrays::propagate(TNode) */
-void TheoryArrays::explain(TNode literal, std::vector<TNode>& assumptions,
- eq::EqProof* proof) {
- // Do the work
- bool polarity = literal.getKind() != kind::NOT;
- TNode atom = polarity ? literal : literal[0];
- //eq::EqProof * eqp = new eq::EqProof;
- // eq::EqProof * eqp = NULL;
- if (atom.getKind() == kind::EQUAL) {
- d_equalityEngine->explainEquality(
- atom[0], atom[1], polarity, assumptions, proof);
- } else {
- d_equalityEngine->explainPredicate(atom, polarity, assumptions, proof);
- }
- if (Debug.isOn("pf::array"))
- {
- if (proof)
- {
- Debug("pf::array") << " Proof is : " << std::endl;
- proof->debug_print("pf::array");
- }
-
- Debug("pf::array") << "Array: explain( " << literal << " ):" << std::endl
- << "\t";
- for (unsigned i = 0; i < assumptions.size(); ++i)
- {
- Debug("pf::array") << assumptions[i] << " ";
- }
- Debug("pf::array") << std::endl;
- }
-}
-
TNode TheoryArrays::weakEquivGetRep(TNode node) {
TNode pointer;
while (true) {
@@ -695,7 +639,8 @@ void TheoryArrays::checkWeakEquiv(bool arraysMerged) {
*/
void TheoryArrays::preRegisterTermInternal(TNode node)
{
- if (d_conflict) {
+ if (d_state.isInConflict())
+ {
return;
}
Debug("arrays") << spaces(getSatContext()->getLevel()) << "TheoryArrays::preRegisterTerm(" << node << ")" << std::endl;
@@ -795,7 +740,8 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
}
// Apply RIntro1 Rule
- d_equalityEngine->assertEquality(ni.eqNode(v), true, d_true, d_reasonRow1);
+ d_equalityEngine->assertEquality(
+ ni.eqNode(v), true, d_true, theory::eq::MERGED_THROUGH_ROW1);
d_infoMap.addStore(node, node);
d_infoMap.addInStore(a, node);
@@ -838,7 +784,6 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
// The may equal needs the node
d_mayEqualEqualityEngine.addTerm(node);
d_equalityEngine->addTerm(node);
- Assert(d_equalityEngine->getSize(node) == 1);
}
else {
d_equalityEngine->addTerm(node);
@@ -852,7 +797,6 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
// !d_equalityEngine->consistent());
}
-
void TheoryArrays::preRegisterTerm(TNode node)
{
preRegisterTermInternal(node);
@@ -864,19 +808,32 @@ void TheoryArrays::preRegisterTerm(TNode node)
}
}
-TrustNode TheoryArrays::explain(TNode literal)
+void TheoryArrays::explain(TNode literal, Node& explanation)
{
- Node explanation = explain(literal, NULL);
- return TrustNode::mkTrustPropExp(literal, explanation, nullptr);
-}
-
-Node TheoryArrays::explain(TNode literal, eq::EqProof* proof) {
++d_numExplain;
Debug("arrays") << spaces(getSatContext()->getLevel())
<< "TheoryArrays::explain(" << literal << ")" << std::endl;
std::vector<TNode> assumptions;
- explain(literal, assumptions, proof);
- return mkAnd(assumptions);
+ // Do the work
+ bool polarity = literal.getKind() != kind::NOT;
+ TNode atom = polarity ? literal : literal[0];
+ if (atom.getKind() == kind::EQUAL)
+ {
+ d_equalityEngine->explainEquality(
+ atom[0], atom[1], polarity, assumptions, nullptr);
+ }
+ else
+ {
+ d_equalityEngine->explainPredicate(atom, polarity, assumptions, nullptr);
+ }
+ explanation = mkAnd(assumptions);
+}
+
+TrustNode TheoryArrays::explain(TNode literal)
+{
+ Node explanation;
+ explain(literal, explanation);
+ return TrustNode::mkTrustPropExp(literal, explanation, nullptr);
}
/////////////////////////////////////////////////////////////////////////////
@@ -900,23 +857,6 @@ void TheoryArrays::notifySharedTerm(TNode t)
}
}
-
-EqualityStatus TheoryArrays::getEqualityStatus(TNode a, TNode b) {
- Assert(d_equalityEngine->hasTerm(a) && d_equalityEngine->hasTerm(b));
- if (d_equalityEngine->areEqual(a, b))
- {
- // The terms are implied to be equal
- return EQUALITY_TRUE;
- }
- else if (d_equalityEngine->areDisequal(a, b, false))
- {
- // The terms are implied to be dis-equal
- return EQUALITY_FALSE;
- }
- return EQUALITY_UNKNOWN;//FALSE_IN_MODEL;
-}
-
-
void TheoryArrays::checkPair(TNode r1, TNode r2)
{
Debug("arrays::sharing") << "TheoryArrays::computeCareGraph(): checking reads " << r1 << " and " << r2 << std::endl;
@@ -1090,22 +1030,15 @@ void TheoryArrays::computeCareGraph()
// MODEL GENERATION
/////////////////////////////////////////////////////////////////////////////
-bool TheoryArrays::collectModelInfo(TheoryModel* m)
+bool TheoryArrays::collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet)
{
- // Compute terms appearing in assertions and shared terms, and also
- // include additional reads due to the RIntro1 and RIntro2 rules.
- std::set<Node> termSet;
- computeRelevantTerms(termSet);
-
- // Send the equality engine information to the model
- if (!m->assertEqualityEngine(d_equalityEngine, &termSet))
- {
- return false;
- }
-
+ // termSet contains terms appearing in assertions and shared terms, and also
+ // includes additional reads due to the RIntro1 and RIntro2 rules.
NodeManager* nm = NodeManager::currentNM();
// Compute arrays that we need to produce representatives for
std::vector<Node> arrays;
+
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
for (; !eqcs_i.isFinished(); ++eqcs_i) {
Node eqc = (*eqcs_i);
@@ -1158,12 +1091,14 @@ bool TheoryArrays::collectModelInfo(TheoryModel* m)
//}
// Loop through all array equivalence classes that need a representative computed
- for (size_t i=0; i<arrays.size(); ++i) {
- TNode n = arrays[i];
- TNode nrep = d_equalityEngine->getRepresentative(n);
+ for (size_t i = 0; i < arrays.size(); ++i)
+ {
+ TNode n = arrays[i];
+ TNode nrep = d_equalityEngine->getRepresentative(n);
- //if (fullModel) {
- // Compute default value for this array - there is one default value for every mayEqual equivalence class
+ // if (fullModel) {
+ // Compute default value for this array - there is one default value for
+ // every mayEqual equivalence class
TNode mayRep = d_mayEqualEqualityEngine.getRepresentative(nrep);
it = d_defValues.find(mayRep);
// If this mayEqual EC doesn't have a default value associated, get the next available default value for the associated array element type
@@ -1265,7 +1200,7 @@ Node TheoryArrays::getSkolem(TNode ref, const string& name, const TypeNode& type
Node d = skolem.eqNode(ref);
Debug("arrays-model-based") << "Asserting skolem equality " << d << endl;
d_equalityEngine->assertEquality(d, true, d_true);
- Assert(!d_conflict);
+ Assert(!d_state.isInConflict());
d_skolemAssertions.push_back(d);
d_skolemIndex = d_skolemIndex + 1;
}
@@ -1274,145 +1209,11 @@ Node TheoryArrays::getSkolem(TNode ref, const string& name, const TypeNode& type
return skolem;
}
-
-void TheoryArrays::check(Effort e) {
- if (done() && !fullEffort(e)) {
- return;
- }
-
- getOutputChannel().spendResource(ResourceManager::Resource::TheoryCheckStep);
-
- TimerStat::CodeTimer checkTimer(d_checkTime);
-
- while (!done() && !d_conflict)
+void TheoryArrays::postCheck(Effort level)
+{
+ if ((options::arraysEagerLemmas() || fullEffort(level))
+ && !d_state.isInConflict() && options::arraysWeakEquivalence())
{
- // Get all the assertions
- Assertion assertion = get();
- TNode fact = assertion.d_assertion;
-
- Debug("arrays") << spaces(getSatContext()->getLevel()) << "TheoryArrays::check(): processing " << fact << std::endl;
-
- bool polarity = fact.getKind() != kind::NOT;
- TNode atom = polarity ? fact : fact[0];
-
- if (!assertion.d_isPreregistered)
- {
- if (atom.getKind() == kind::EQUAL) {
- if (!d_equalityEngine->hasTerm(atom[0]))
- {
- Assert(atom[0].isConst());
- d_equalityEngine->addTerm(atom[0]);
- }
- if (!d_equalityEngine->hasTerm(atom[1]))
- {
- Assert(atom[1].isConst());
- d_equalityEngine->addTerm(atom[1]);
- }
- }
- }
-
- // Do the work
- switch (fact.getKind()) {
- case kind::EQUAL:
- d_equalityEngine->assertEquality(fact, true, fact);
- break;
- case kind::SELECT:
- d_equalityEngine->assertPredicate(fact, true, fact);
- break;
- case kind::NOT:
- if (fact[0].getKind() == kind::SELECT) {
- d_equalityEngine->assertPredicate(fact[0], false, fact);
- }
- else if (!d_equalityEngine->areDisequal(fact[0][0], fact[0][1], false))
- {
- // Assert the dis-equality
- d_equalityEngine->assertEquality(fact[0], false, fact);
-
- // Apply ArrDiseq Rule if diseq is between arrays
- if(fact[0][0].getType().isArray() && !d_conflict) {
- if (d_conflict) { Debug("pf::array") << "Entering the skolemization branch" << std::endl; }
-
- NodeManager* nm = NodeManager::currentNM();
- TypeNode indexType = fact[0][0].getType()[0];
-
- TNode k;
- // k is the skolem for this disequality.
- if (!d_proofsEnabled) {
- Debug("pf::array") << "Check: kind::NOT: array theory making a skolem" << std::endl;
-
- // If not in replay mode, generate a fresh skolem variable
- k = getSkolem(fact,
- "array_ext_index",
- indexType,
- "an extensional lemma index variable from the theory of arrays",
- false);
-
- // Register this skolem for the proof replay phase
- PROOF(ProofManager::getSkolemizationManager()->registerSkolem(fact, k));
- } else {
- if (!ProofManager::getSkolemizationManager()->hasSkolem(fact)) {
- // In the solution pass we didn't need this skolem. Therefore, we don't need it
- // in this reply pass, either.
- break;
- }
-
- // Reuse the same skolem as in the solution pass
- k = ProofManager::getSkolemizationManager()->getSkolem(fact);
- Debug("pf::array") << "Skolem = " << k << std::endl;
- }
-
- Node ak = nm->mkNode(kind::SELECT, fact[0][0], k);
- Node bk = nm->mkNode(kind::SELECT, fact[0][1], k);
- Node eq = ak.eqNode(bk);
- Node lemma = fact[0].orNode(eq.notNode());
-
- // In solve mode we don't care if ak and bk are registered. If they aren't, they'll be registered
- // when we output the lemma. However, in replay need the lemma to be propagated, and so we
- // preregister manually.
- if (d_proofsEnabled) {
- if (!d_equalityEngine->hasTerm(ak))
- {
- preRegisterTermInternal(ak);
- }
- if (!d_equalityEngine->hasTerm(bk))
- {
- preRegisterTermInternal(bk);
- }
- }
-
- if (options::arraysPropagate() > 0 && d_equalityEngine->hasTerm(ak)
- && d_equalityEngine->hasTerm(bk))
- {
- // Propagate witness disequality - might produce a conflict
- d_permRef.push_back(lemma);
- Debug("pf::array") << "Asserting to the equality engine:" << std::endl
- << "\teq = " << eq << std::endl
- << "\treason = " << fact << std::endl;
-
- d_equalityEngine->assertEquality(eq, false, fact, d_reasonExt);
- ++d_numProp;
- }
-
- if (!d_proofsEnabled) {
- // If this is the solution pass, generate the lemma. Otherwise, don't generate it -
- // as this is the lemma that we're reproving...
- Trace("arrays-lem")<<"Arrays::addExtLemma " << lemma <<"\n";
- d_out->lemma(lemma);
- ++d_numExt;
- }
- } else {
- Debug("pf::array") << "Check: kind::NOT: array theory NOT making a skolem" << std::endl;
- d_modelConstraints.push_back(fact);
- }
- }
- break;
- default:
- Unreachable();
- break;
- }
- }
-
- if ((options::arraysEagerLemmas() || fullEffort(e)) && !d_conflict && options::arraysWeakEquivalence()) {
// Replay all array merges to update weak equivalence data structures
context::CDList<Node>::iterator it = d_arrayMerges.begin(), iend = d_arrayMerges.end();
TNode a, b, eq;
@@ -1488,7 +1289,7 @@ void TheoryArrays::check(Effort e) {
lemma = mkAnd(conjunctions, true);
// LSH FIXME: which kind of arrays lemma is this
Trace("arrays-lem") << "Arrays::addExtLemma " << lemma <<"\n";
- d_out->lemma(lemma, RULE_INVALID, LemmaProperty::SEND_ATOMS);
+ d_out->lemma(lemma, LemmaProperty::SEND_ATOMS);
d_readTableContext->pop();
Trace("arrays") << spaces(getSatContext()->getLevel()) << "Arrays::check(): done" << endl;
return;
@@ -1499,10 +1300,13 @@ void TheoryArrays::check(Effort e) {
d_readTableContext->pop();
}
- if(!options::arraysEagerLemmas() && fullEffort(e) && !d_conflict && !options::arraysWeakEquivalence()) {
+ if (!options::arraysEagerLemmas() && fullEffort(level)
+ && !d_state.isInConflict() && !options::arraysWeakEquivalence())
+ {
// generate the lemmas on the worklist
Trace("arrays-lem")<< "Arrays::discharging lemmas. Number of queued lemmas: " << d_RowQueue.size() << "\n";
- while (d_RowQueue.size() > 0 && !d_conflict) {
+ while (d_RowQueue.size() > 0 && !d_state.isInConflict())
+ {
if (dischargeLemmas()) {
break;
}
@@ -1512,6 +1316,84 @@ void TheoryArrays::check(Effort e) {
Trace("arrays") << spaces(getSatContext()->getLevel()) << "Arrays::check(): done" << endl;
}
+bool TheoryArrays::preNotifyFact(
+ TNode atom, bool pol, TNode fact, bool isPrereg, bool isInternal)
+{
+ if (!isPrereg)
+ {
+ if (atom.getKind() == kind::EQUAL)
+ {
+ if (!d_equalityEngine->hasTerm(atom[0]))
+ {
+ Assert(atom[0].isConst());
+ d_equalityEngine->addTerm(atom[0]);
+ }
+ if (!d_equalityEngine->hasTerm(atom[1]))
+ {
+ Assert(atom[1].isConst());
+ d_equalityEngine->addTerm(atom[1]);
+ }
+ }
+ }
+ return false;
+}
+
+void TheoryArrays::notifyFact(TNode atom, bool pol, TNode fact, bool isInternal)
+{
+ // if a disequality
+ if (atom.getKind() == kind::EQUAL && !pol)
+ {
+ // Apply ArrDiseq Rule if diseq is between arrays
+ if (fact[0][0].getType().isArray() && !d_state.isInConflict())
+ {
+ NodeManager* nm = NodeManager::currentNM();
+ TypeNode indexType = fact[0][0].getType()[0];
+
+ TNode k;
+ // k is the skolem for this disequality.
+ Debug("pf::array") << "Check: kind::NOT: array theory making a skolem"
+ << std::endl;
+
+ // If not in replay mode, generate a fresh skolem variable
+ k = getSkolem(
+ fact,
+ "array_ext_index",
+ indexType,
+ "an extensional lemma index variable from the theory of arrays",
+ false);
+
+ Node ak = nm->mkNode(kind::SELECT, fact[0][0], k);
+ Node bk = nm->mkNode(kind::SELECT, fact[0][1], k);
+ Node eq = ak.eqNode(bk);
+ Node lemma = fact[0].orNode(eq.notNode());
+
+ if (options::arraysPropagate() > 0 && d_equalityEngine->hasTerm(ak)
+ && d_equalityEngine->hasTerm(bk))
+ {
+ // Propagate witness disequality - might produce a conflict
+ d_permRef.push_back(lemma);
+ Debug("pf::array") << "Asserting to the equality engine:" << std::endl
+ << "\teq = " << eq << std::endl
+ << "\treason = " << fact << std::endl;
+
+ d_equalityEngine->assertEquality(eq, false, fact);
+ ++d_numProp;
+ }
+
+ // If this is the solution pass, generate the lemma. Otherwise, don't
+ // generate it - as this is the lemma that we're reproving...
+ Trace("arrays-lem") << "Arrays::addExtLemma " << lemma << "\n";
+ d_out->lemma(lemma);
+ ++d_numExt;
+ }
+ else
+ {
+ Debug("pf::array") << "Check: kind::NOT: array theory NOT making a skolem"
+ << std::endl;
+ d_modelConstraints.push_back(fact);
+ }
+ }
+}
Node TheoryArrays::mkAnd(std::vector<TNode>& conjunctions, bool invert, unsigned startIndex)
{
@@ -1716,7 +1598,8 @@ void TheoryArrays::mergeArrays(TNode a, TNode b)
}
// If no more to do, break
- if (d_conflict || d_mergeQueue.empty()) {
+ if (d_state.isInConflict() || d_mergeQueue.empty())
+ {
break;
}
@@ -1916,7 +1799,8 @@ void TheoryArrays::propagate(RowLemmaType lem)
if (!bjExists) {
preRegisterTermInternal(bj);
}
- d_equalityEngine->assertEquality(aj_eq_bj, true, reason, d_reasonRow);
+ d_equalityEngine->assertEquality(
+ aj_eq_bj, true, reason, theory::eq::MERGED_THROUGH_ROW);
++d_numProp;
return;
}
@@ -1927,7 +1811,8 @@ void TheoryArrays::propagate(RowLemmaType lem)
(aj.isConst() && bj.isConst()) ? d_true : aj.eqNode(bj).notNode();
Node i_eq_j = i.eqNode(j);
d_permRef.push_back(reason);
- d_equalityEngine->assertEquality(i_eq_j, true, reason, d_reasonRow);
+ d_equalityEngine->assertEquality(
+ i_eq_j, true, reason, theory::eq::MERGED_THROUGH_ROW);
++d_numProp;
return;
}
@@ -1938,7 +1823,8 @@ void TheoryArrays::queueRowLemma(RowLemmaType lem)
{
Debug("pf::array") << "Array solver: queue row lemma called" << std::endl;
- if (d_conflict || d_RowAlreadyAdded.contains(lem)) {
+ if (d_state.isInConflict() || d_RowAlreadyAdded.contains(lem))
+ {
return;
}
TNode a, b, i, j;
@@ -1965,33 +1851,23 @@ void TheoryArrays::queueRowLemma(RowLemmaType lem)
propagate(lem);
}
- // If equivalent lemma already exists, don't enqueue this one
- if (d_useArrTable) {
- Node tableEntry = NodeManager::currentNM()->mkNode(kind::ARR_TABLE_FUN, a, b, i, j);
- if (d_equalityEngine->getSize(tableEntry) != 1)
- {
- return;
- }
- }
-
// Prefer equality between indexes so as not to introduce new read terms
if (options::arraysEagerIndexSplitting() && !bothExist
&& !d_equalityEngine->areDisequal(i, j, false))
{
Node i_eq_j;
- if (!d_proofsEnabled) {
- i_eq_j = d_valuation.ensureLiteral(i.eqNode(j)); // TODO: think about this
- } else {
- i_eq_j = i.eqNode(j);
- }
-
+ i_eq_j = d_valuation.ensureLiteral(i.eqNode(j)); // TODO: think about this
+#if 0
+ i_eq_j = i.eqNode(j);
+#endif
getOutputChannel().requirePhase(i_eq_j, true);
d_decisionRequests.push(i_eq_j);
}
// TODO: maybe add triggers here
- if ((options::arraysEagerLemmas() || bothExist) && !d_proofsEnabled) {
+ if (options::arraysEagerLemmas() || bothExist)
+ {
// Make sure that any terms introduced by rewriting are appropriately stored in the equality database
Node aj2 = Rewriter::rewrite(aj);
if (aj != aj2) {
@@ -2099,7 +1975,8 @@ bool TheoryArrays::dischargeLemmas()
int prop = options::arraysPropagate();
if (prop > 0) {
propagate(l);
- if (d_conflict) {
+ if (d_state.isInConflict())
+ {
return true;
}
}
@@ -2170,26 +2047,14 @@ bool TheoryArrays::dischargeLemmas()
void TheoryArrays::conflict(TNode a, TNode b) {
Debug("pf::array") << "TheoryArrays::Conflict called" << std::endl;
- std::shared_ptr<eq::EqProof> proof = d_proofsEnabled ?
- std::make_shared<eq::EqProof>() : nullptr;
- d_conflictNode = explain(a.eqNode(b), proof.get());
+ explain(a.eqNode(b), d_conflictNode);
if (!d_inCheckModel) {
- std::unique_ptr<ProofArray> proof_array;
-
- if (d_proofsEnabled) {
- proof->debug_print("pf::array");
- proof_array.reset(new ProofArray(proof,
- /*row=*/d_reasonRow,
- /*row1=*/d_reasonRow1,
- /*ext=*/d_reasonExt));
- }
-
- d_out->conflict(d_conflictNode, std::move(proof_array));
+ d_out->conflict(d_conflictNode);
}
- d_conflict = true;
+ d_state.notifyInConflict();
}
TheoryArrays::TheoryArraysDecisionStrategy::TheoryArraysDecisionStrategy(
@@ -2263,13 +2128,8 @@ TrustNode TheoryArrays::expandDefinition(Node node)
return TrustNode::null();
}
-void TheoryArrays::computeRelevantTerms(std::set<Node>& termSet,
- bool includeShared)
+void TheoryArrays::computeRelevantTerms(std::set<Node>& termSet)
{
- // include all standard terms
- std::set<Kind> irrKinds;
- computeRelevantTermsInternal(termSet, irrKinds, includeShared);
-
NodeManager* nm = NodeManager::currentNM();
// make sure RIntro1 reads are included in the relevant set of reads
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
diff --git a/src/theory/arrays/theory_arrays.h b/src/theory/arrays/theory_arrays.h
index 8cbf826c1..dea3d4136 100644
--- a/src/theory/arrays/theory_arrays.h
+++ b/src/theory/arrays/theory_arrays.h
@@ -26,7 +26,6 @@
#include "context/cdhashset.h"
#include "context/cdqueue.h"
#include "theory/arrays/array_info.h"
-#include "theory/arrays/array_proof_reconstruction.h"
#include "theory/arrays/theory_arrays_rewriter.h"
#include "theory/theory.h"
#include "theory/uf/equality_engine.h"
@@ -129,15 +128,6 @@ class TheoryArrays : public Theory {
/** conflicts in setModelVal */
IntStat d_numSetModelValConflicts;
- // Merge reason types
-
- /** Merge tag for ROW applications */
- unsigned d_reasonRow;
- /** Merge tag for ROW1 applications */
- unsigned d_reasonRow1;
- /** Merge tag for EXT applications */
- unsigned d_reasonExt;
-
public:
TheoryArrays(context::Context* c,
context::UserContext* u,
@@ -215,9 +205,8 @@ class TheoryArrays : public Theory {
/** Should be called to propagate the literal. */
bool propagateLit(TNode literal);
- /** Explain why this literal is true by adding assumptions */
- void explain(TNode literal, std::vector<TNode>& assumptions,
- eq::EqProof* proof);
+ /** Explain why this literal is true by building an explanation */
+ void explain(TNode literal, Node& exp);
/** For debugging only- checks invariants about when things are preregistered*/
context::CDHashSet<Node, NodeHashFunction > d_isPreRegistered;
@@ -227,7 +216,6 @@ class TheoryArrays : public Theory {
public:
void preRegisterTerm(TNode n) override;
- Node explain(TNode n, eq::EqProof* proof);
TrustNode explain(TNode n) override;
/////////////////////////////////////////////////////////////////////////////
@@ -252,7 +240,6 @@ class TheoryArrays : public Theory {
public:
void notifySharedTerm(TNode t) override;
- EqualityStatus getEqualityStatus(TNode a, TNode b) override;
void computeCareGraph() override;
bool isShared(TNode t)
{
@@ -264,7 +251,9 @@ class TheoryArrays : public Theory {
/////////////////////////////////////////////////////////////////////////////
public:
- bool collectModelInfo(TheoryModel* m) override;
+ /** Collect model values in m based on the relevant terms given by termSet */
+ bool collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet) override;
/////////////////////////////////////////////////////////////////////////////
// NOTIFICATIONS
@@ -278,8 +267,18 @@ class TheoryArrays : public Theory {
// MAIN SOLVER
/////////////////////////////////////////////////////////////////////////////
- public:
- void check(Effort e) override;
+ //--------------------------------- standard check
+ /** Post-check, called after the fact queue of the theory is processed. */
+ void postCheck(Effort level) override;
+ /** Pre-notify fact, return true if processed. */
+ bool preNotifyFact(TNode atom,
+ bool pol,
+ TNode fact,
+ bool isPrereg,
+ bool isInternal) override;
+ /** Notify fact */
+ void notifyFact(TNode atom, bool pol, TNode fact, bool isInternal) override;
+ //--------------------------------- end standard check
private:
TNode weakEquivGetRep(TNode node);
@@ -342,9 +341,6 @@ class TheoryArrays : public Theory {
/** The notify class for d_equalityEngine */
NotifyClass d_notify;
- /** Are we in conflict? */
- context::CDO<bool> d_conflict;
-
/** Conflict when merging constants */
void conflict(TNode a, TNode b);
@@ -445,9 +441,6 @@ class TheoryArrays : public Theory {
bool d_inCheckModel;
int d_topLevel;
- /** An equality-engine callback for proof reconstruction */
- std::unique_ptr<ArrayProofReconstruction> d_proofReconstruction;
-
/**
* The decision strategy for the theory of arrays, which calls the
* getNextDecisionEngineRequest function below.
@@ -478,13 +471,11 @@ class TheoryArrays : public Theory {
* for the comparison between the indexes that appears in the lemma.
*/
Node getNextDecisionRequest();
-
/**
- * Compute relevant terms. This includes additional select nodes for the
+ * Compute relevant terms. This includes select nodes for the
* RIntro1 and RIntro2 rules.
*/
- void computeRelevantTerms(std::set<Node>& termSet,
- bool includeShared = true) override;
+ void computeRelevantTerms(std::set<Node>& termSet) override;
};/* class TheoryArrays */
}/* CVC4::theory::arrays namespace */
diff --git a/src/theory/builtin/proof_checker.cpp b/src/theory/builtin/proof_checker.cpp
index 7521d116e..cf27b516e 100644
--- a/src/theory/builtin/proof_checker.cpp
+++ b/src/theory/builtin/proof_checker.cpp
@@ -16,6 +16,7 @@
#include "expr/skolem_manager.h"
#include "smt/term_formula_removal.h"
+#include "theory/evaluator.h"
#include "theory/rewriter.h"
#include "theory/theory.h"
@@ -29,6 +30,9 @@ const char* toString(MethodId id)
switch (id)
{
case MethodId::RW_REWRITE: return "RW_REWRITE";
+ case MethodId::RW_EXT_REWRITE: return "RW_EXT_REWRITE";
+ case MethodId::RW_REWRITE_EQ_EXT: return "RW_REWRITE_EQ_EXT";
+ case MethodId::RW_EVALUATE: return "RW_EVALUATE";
case MethodId::RW_IDENTITY: return "RW_IDENTITY";
case MethodId::SB_DEFAULT: return "SB_DEFAULT";
case MethodId::SB_LITERAL: return "SB_LITERAL";
@@ -56,6 +60,7 @@ void BuiltinProofRuleChecker::registerTo(ProofChecker* pc)
pc->registerChecker(PfRule::SCOPE, this);
pc->registerChecker(PfRule::SUBS, this);
pc->registerChecker(PfRule::REWRITE, this);
+ pc->registerChecker(PfRule::EVALUATE, this);
pc->registerChecker(PfRule::MACRO_SR_EQ_INTRO, this);
pc->registerChecker(PfRule::MACRO_SR_PRED_INTRO, this);
pc->registerChecker(PfRule::MACRO_SR_PRED_ELIM, this);
@@ -63,6 +68,7 @@ void BuiltinProofRuleChecker::registerTo(ProofChecker* pc)
pc->registerChecker(PfRule::THEORY_REWRITE, this);
pc->registerChecker(PfRule::REMOVE_TERM_FORMULA_AXIOM, this);
// trusted rules
+ pc->registerTrustedChecker(PfRule::THEORY_LEMMA, this, 1);
pc->registerTrustedChecker(PfRule::PREPROCESS, this, 2);
pc->registerTrustedChecker(PfRule::PREPROCESS_LEMMA, this, 2);
pc->registerTrustedChecker(PfRule::THEORY_PREPROCESS, this, 2);
@@ -70,16 +76,6 @@ void BuiltinProofRuleChecker::registerTo(ProofChecker* pc)
pc->registerTrustedChecker(PfRule::WITNESS_AXIOM, this, 2);
}
-Node BuiltinProofRuleChecker::applyTheoryRewrite(Node n, bool preRewrite)
-{
- TheoryId tid = Theory::theoryOf(n);
- Rewriter* rewriter = Rewriter::getInstance();
- Node nkr = preRewrite ? rewriter->preRewrite(tid, n).d_node
- : rewriter->postRewrite(tid, n).d_node;
- return nkr;
-}
-
-
Node BuiltinProofRuleChecker::applySubstitutionRewrite(
Node n, const std::vector<Node>& exp, MethodId ids, MethodId idr)
{
@@ -95,7 +91,20 @@ Node BuiltinProofRuleChecker::applyRewrite(Node n, MethodId idr)
{
return Rewriter::rewrite(n);
}
- else if (idr == MethodId::RW_IDENTITY)
+ if (idr == MethodId::RW_EXT_REWRITE)
+ {
+ return d_ext_rewriter.extendedRewrite(n);
+ }
+ if (idr == MethodId::RW_REWRITE_EQ_EXT)
+ {
+ return Rewriter::rewriteEqualityExt(n);
+ }
+ if (idr == MethodId::RW_EVALUATE)
+ {
+ Evaluator eval;
+ return eval.eval(n, {}, {}, false);
+ }
+ if (idr == MethodId::RW_IDENTITY)
{
// does nothing
return n;
@@ -228,7 +237,7 @@ Node BuiltinProofRuleChecker::checkInternal(PfRule id,
{
exp.push_back(children[i]);
}
- Node res = applySubstitution(args[0], exp);
+ Node res = applySubstitution(args[0], exp, ids);
return args[0].eqNode(res);
}
else if (id == PfRule::REWRITE)
@@ -243,6 +252,13 @@ Node BuiltinProofRuleChecker::checkInternal(PfRule id,
Node res = applyRewrite(args[0], idr);
return args[0].eqNode(res);
}
+ else if (id == PfRule::EVALUATE)
+ {
+ Assert(children.empty());
+ Assert(args.size() == 1);
+ Node res = applyRewrite(args[0], MethodId::RW_EVALUATE);
+ return args[0].eqNode(res);
+ }
else if (id == PfRule::MACRO_SR_EQ_INTRO)
{
Assert(1 <= args.size() && args.size() <= 3);
@@ -334,13 +350,14 @@ Node BuiltinProofRuleChecker::checkInternal(PfRule id,
Assert(args.size() == 1);
return RemoveTermFormulas::getAxiomFor(args[0]);
}
- else if (id == PfRule::PREPROCESS || id == PfRule::PREPROCESS_LEMMA
- || id == PfRule::THEORY_PREPROCESS
- || id == PfRule::THEORY_PREPROCESS_LEMMA
- || id == PfRule::WITNESS_AXIOM)
+ else if (id == PfRule::PREPROCESS || id == PfRule::THEORY_PREPROCESS
+ || id == PfRule::WITNESS_AXIOM || id == PfRule::THEORY_LEMMA
+ || id == PfRule::PREPROCESS_LEMMA || id == PfRule::THEORY_REWRITE)
{
+ // "trusted" rules
Assert(children.empty());
- Assert(args.size() == 1);
+ Assert(!args.empty());
+ Assert(args[0].getType().isBoolean());
return args[0];
}
// no rule
@@ -390,6 +407,23 @@ void BuiltinProofRuleChecker::addMethodIds(std::vector<Node>& args,
}
}
+bool BuiltinProofRuleChecker::getTheoryId(TNode n, TheoryId& tid)
+{
+ uint32_t i;
+ if (!getUInt32(n, i))
+ {
+ return false;
+ }
+ tid = static_cast<TheoryId>(i);
+ return true;
+}
+
+Node BuiltinProofRuleChecker::mkTheoryIdNode(TheoryId tid)
+{
+ return NodeManager::currentNM()->mkConst(
+ Rational(static_cast<uint32_t>(tid)));
+}
+
} // namespace builtin
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/builtin/proof_checker.h b/src/theory/builtin/proof_checker.h
index 7e46587b7..3251b4e9e 100644
--- a/src/theory/builtin/proof_checker.h
+++ b/src/theory/builtin/proof_checker.h
@@ -20,11 +20,12 @@
#include "expr/node.h"
#include "expr/proof_checker.h"
#include "expr/proof_node.h"
+#include "theory/quantifiers/extended_rewrite.h"
namespace CVC4 {
namespace theory {
-/**
+/**
* Identifiers for rewriters and substitutions, which we abstractly
* classify as "methods". Methods have a unique identifier in the internal
* proof calculus implemented by the checker below.
@@ -41,6 +42,12 @@ enum class MethodId : uint32_t
//---------------------------- Rewriters
// Rewriter::rewrite(n)
RW_REWRITE,
+ // d_ext_rew.extendedRewrite(n);
+ RW_EXT_REWRITE,
+ // Rewriter::rewriteExtEquality(n)
+ RW_REWRITE_EQ_EXT,
+ // Evaluator::evaluate(n)
+ RW_EVALUATE,
// identity
RW_IDENTITY,
//---------------------------- Substitutions
@@ -75,21 +82,10 @@ class BuiltinProofRuleChecker : public ProofRuleChecker
* specifying a call to Rewriter::rewrite.
* @return The rewritten form of n.
*/
- static Node applyRewrite(Node n, MethodId idr = MethodId::RW_REWRITE);
- /**
- * Apply small-step rewrite on n in skolem form (either pre- or
- * post-rewrite). This encapsulates the exact behavior of a THEORY_REWRITE
- * step in a proof.
- *
- * @param n The node to rewrite
- * @param preRewrite If true, performs a pre-rewrite or a post-rewrite
- * otherwise
- * @return The rewritten form of n
- */
- static Node applyTheoryRewrite(Node n, bool preRewrite);
+ Node applyRewrite(Node n, MethodId idr = MethodId::RW_REWRITE);
/**
* Get substitution. Updates vars/subs to the substitution specified by
- * exp (e.g. as an equality) for the substitution method ids.
+ * exp for the substitution method ids.
*/
static bool getSubstitution(Node exp,
TNode& var,
@@ -123,10 +119,10 @@ class BuiltinProofRuleChecker : public ProofRuleChecker
* @param idr The method identifier of the rewriter.
* @return The substituted, rewritten form of n.
*/
- static Node applySubstitutionRewrite(Node n,
- const std::vector<Node>& exp,
- MethodId ids = MethodId::SB_DEFAULT,
- MethodId idr = MethodId::RW_REWRITE);
+ Node applySubstitutionRewrite(Node n,
+ const std::vector<Node>& exp,
+ MethodId ids = MethodId::SB_DEFAULT,
+ MethodId idr = MethodId::RW_REWRITE);
/** get a method identifier from a node, return false if we fail */
static bool getMethodId(TNode n, MethodId& i);
/**
@@ -144,6 +140,11 @@ class BuiltinProofRuleChecker : public ProofRuleChecker
*/
static void addMethodIds(std::vector<Node>& args, MethodId ids, MethodId idr);
+ /** get a TheoryId from a node, return false if we fail */
+ static bool getTheoryId(TNode n, TheoryId& tid);
+ /** Make a TheoryId into a node */
+ static Node mkTheoryIdNode(TheoryId tid);
+
/** Register all rules owned by this rule checker into pc. */
void registerTo(ProofChecker* pc) override;
protected:
@@ -151,6 +152,9 @@ class BuiltinProofRuleChecker : public ProofRuleChecker
Node checkInternal(PfRule id,
const std::vector<Node>& children,
const std::vector<Node>& args) override;
+
+ /** extended rewriter object */
+ quantifiers::ExtendedRewriter d_ext_rewriter;
};
} // namespace builtin
diff --git a/src/theory/bv/bitblast/aig_bitblaster.h b/src/theory/bv/bitblast/aig_bitblaster.h
index 1e1b5bab4..fef45cdf5 100644
--- a/src/theory/bv/bitblast/aig_bitblaster.h
+++ b/src/theory/bv/bitblast/aig_bitblaster.h
@@ -89,12 +89,6 @@ class AigBitblaster : public TBitblaster<Abc_Obj_t*>
prop::SatSolver* getSatSolver() override { return d_satSolver.get(); }
- void setProofLog(proof::BitVectorProof* bvp) override
- {
- // Proofs are currently not supported with ABC
- Unimplemented();
- }
-
class Statistics
{
public:
diff --git a/src/theory/bv/bitblast/bitblaster.h b/src/theory/bv/bitblast/bitblaster.h
index defc66b74..74e3c3f56 100644
--- a/src/theory/bv/bitblast/bitblaster.h
+++ b/src/theory/bv/bitblast/bitblaster.h
@@ -24,8 +24,8 @@
#include <vector>
#include "expr/node.h"
-#include "proof/bitvector_proof.h"
#include "prop/bv_sat_solver_notify.h"
+#include "prop/sat_solver.h"
#include "prop/sat_solver_types.h"
#include "smt/smt_engine_scope.h"
#include "theory/bv/bitblast/bitblast_strategies_template.h"
@@ -64,7 +64,6 @@ class TBitblaster
// 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();
@@ -91,7 +90,6 @@ class TBitblaster
bool hasBBTerm(TNode node) const;
void getBBTerm(TNode node, Bits& bits) const;
virtual void storeBBTerm(TNode term, const Bits& bits);
- virtual void setProofLog(proof::BitVectorProof* bvp);
/**
* Return a constant representing the value of a in the model.
@@ -186,8 +184,7 @@ TBitblaster<T>::TBitblaster()
: d_termCache(),
d_modelCache(),
d_nullContext(new context::Context()),
- d_cnfStream(),
- d_bvp(nullptr)
+ d_cnfStream()
{
initAtomBBStrategies();
initTermBBStrategies();
@@ -218,20 +215,6 @@ 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 4acd1d2f8..627a17bc5 100644
--- a/src/theory/bv/bitblast/eager_bitblaster.cpp
+++ b/src/theory/bv/bitblast/eager_bitblaster.cpp
@@ -72,7 +72,7 @@ EagerBitblaster::EagerBitblaster(TheoryBV* theory_bv, context::Context* c)
d_bitblastingRegistrar.get(),
d_nullContext.get(),
rm,
- options::proof(),
+ false,
"EagerBitblaster"));
}
@@ -87,8 +87,7 @@ void EagerBitblaster::bbFormula(TNode node)
}
else
{
- d_cnfStream->convertAndAssert(
- node, false, false, RULE_INVALID, TNode::null());
+ d_cnfStream->convertAndAssert(node, false, false);
}
}
@@ -116,10 +115,7 @@ void EagerBitblaster::bbAtom(TNode node)
? d_atomBBStrategies[normalized.getKind()](normalized, this)
: normalized;
- if (!options::proof())
- {
- atom_bb = Rewriter::rewrite(atom_bb);
- }
+ atom_bb = Rewriter::rewrite(atom_bb);
// asserting that the atom is true iff the definition holds
Node atom_definition =
@@ -127,21 +123,14 @@ void EagerBitblaster::bbAtom(TNode node)
AlwaysAssert(options::bitblastMode() == options::BitblastMode::EAGER);
storeBBAtom(node, atom_bb);
- d_cnfStream->convertAndAssert(
- atom_definition, false, false, RULE_INVALID, TNode::null());
+ d_cnfStream->convertAndAssert(atom_definition, false, false);
}
void EagerBitblaster::storeBBAtom(TNode atom, Node atom_bb) {
- if (d_bvp) {
- d_bvp->registerAtomBB(atom.toExpr(), atom_bb.toExpr());
- }
d_bbAtoms.insert(atom);
}
void EagerBitblaster::storeBBTerm(TNode node, const Bits& bits) {
- if (d_bvp) {
- d_bvp->registerTermBB(node.toExpr());
- }
d_termCache.insert(std::make_pair(node, bits));
}
diff --git a/src/theory/bv/bitblast/eager_bitblaster.h b/src/theory/bv/bitblast/eager_bitblaster.h
index a8b7ccbe5..da9488d43 100644
--- a/src/theory/bv/bitblast/eager_bitblaster.h
+++ b/src/theory/bv/bitblast/eager_bitblaster.h
@@ -23,8 +23,6 @@
#include "theory/bv/bitblast/bitblaster.h"
-#include "proof/bitvector_proof.h"
-#include "proof/resolution_bitvector_proof.h"
#include "prop/cnf_stream.h"
#include "prop/sat_solver.h"
diff --git a/src/theory/bv/bitblast/lazy_bitblaster.cpp b/src/theory/bv/bitblast/lazy_bitblaster.cpp
index c3a305952..3109d6ed7 100644
--- a/src/theory/bv/bitblast/lazy_bitblaster.cpp
+++ b/src/theory/bv/bitblast/lazy_bitblaster.cpp
@@ -19,7 +19,6 @@
#include "theory/bv/bitblast/lazy_bitblaster.h"
#include "options/bv_options.h"
-#include "proof/proof_manager.h"
#include "prop/cnf_stream.h"
#include "prop/sat_solver.h"
#include "prop/sat_solver_factory.h"
@@ -84,7 +83,7 @@ TLazyBitblaster::TLazyBitblaster(context::Context* c,
d_nullRegistrar.get(),
d_nullContext.get(),
rm,
- options::proof(),
+ false,
"LazyBitblaster"));
d_satSolverNotify.reset(
@@ -161,8 +160,7 @@ void TLazyBitblaster::bbAtom(TNode node)
Assert(!atom_bb.isNull());
Node atom_definition = nm->mkNode(kind::EQUAL, node, atom_bb);
storeBBAtom(node, atom_bb);
- d_cnfStream->convertAndAssert(
- atom_definition, false, false, RULE_INVALID, TNode::null());
+ d_cnfStream->convertAndAssert(atom_definition, false, false);
return;
}
@@ -173,28 +171,19 @@ void TLazyBitblaster::bbAtom(TNode node)
? d_atomBBStrategies[normalized.getKind()](normalized, this)
: normalized;
- if (!options::proof())
- {
- atom_bb = Rewriter::rewrite(atom_bb);
- }
+ atom_bb = Rewriter::rewrite(atom_bb);
// asserting that the atom is true iff the definition holds
Node atom_definition = nm->mkNode(kind::EQUAL, node, atom_bb);
storeBBAtom(node, atom_bb);
- d_cnfStream->convertAndAssert(
- atom_definition, false, false, RULE_INVALID, TNode::null());
+ d_cnfStream->convertAndAssert(atom_definition, false, false);
}
void TLazyBitblaster::storeBBAtom(TNode atom, Node atom_bb) {
- // No need to store the definition for the lazy bit-blaster (unless proofs are enabled).
- if( d_bvp != NULL ){
- d_bvp->registerAtomBB(atom.toExpr(), atom_bb.toExpr());
- }
d_bbAtoms.insert(atom);
}
void TLazyBitblaster::storeBBTerm(TNode node, const Bits& bits) {
- if( d_bvp ){ d_bvp->registerTermBB(node.toExpr()); }
d_termCache.insert(std::make_pair(node, bits));
}
@@ -540,7 +529,8 @@ Node TLazyBitblaster::getModelFromSatSolver(TNode a, bool fullModel) {
bool TLazyBitblaster::collectModelInfo(TheoryModel* m, bool fullModel)
{
std::set<Node> termSet;
- d_bv->computeRelevantTerms(termSet);
+ const std::set<Kind>& irrKinds = m->getIrrelevantKinds();
+ d_bv->computeAssertedTerms(termSet, irrKinds, true);
for (std::set<Node>::const_iterator it = termSet.begin(); it != termSet.end(); ++it) {
TNode var = *it;
diff --git a/src/theory/bv/bitblast/lazy_bitblaster.h b/src/theory/bv/bitblast/lazy_bitblaster.h
index a355d42c4..bc930aec4 100644
--- a/src/theory/bv/bitblast/lazy_bitblaster.h
+++ b/src/theory/bv/bitblast/lazy_bitblaster.h
@@ -19,7 +19,6 @@
#ifndef CVC4__THEORY__BV__BITBLAST__LAZY_BITBLASTER_H
#define CVC4__THEORY__BV__BITBLAST__LAZY_BITBLASTER_H
-#include "proof/resolution_bitvector_proof.h"
#include "theory/bv/bitblast/bitblaster.h"
#include "context/cdhashmap.h"
diff --git a/src/theory/bv/bv_eager_solver.cpp b/src/theory/bv/bv_eager_solver.cpp
index 36aa72da3..d1490374d 100644
--- a/src/theory/bv/bv_eager_solver.cpp
+++ b/src/theory/bv/bv_eager_solver.cpp
@@ -33,8 +33,7 @@ EagerBitblastSolver::EagerBitblastSolver(context::Context* c, TheoryBV* bv)
d_bitblaster(),
d_aigBitblaster(),
d_useAig(options::bitvectorAig()),
- d_bv(bv),
- d_bvp(nullptr)
+ d_bv(bv)
{
}
@@ -55,10 +54,6 @@ void EagerBitblastSolver::initialize() {
#endif
} else {
d_bitblaster.reset(new EagerBitblaster(d_bv, d_context));
- THEORY_PROOF(if (d_bvp) {
- d_bitblaster->setProofLog(d_bvp);
- d_bvp->setBitblaster(d_bitblaster.get());
- });
}
}
@@ -127,11 +122,6 @@ bool EagerBitblastSolver::collectModelInfo(TheoryModel* m, bool fullModel)
return d_bitblaster->collectModelInfo(m, fullModel);
}
-void EagerBitblastSolver::setProofLog(proof::BitVectorProof* bvp)
-{
- d_bvp = bvp;
-}
-
} // namespace bv
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/bv/bv_eager_solver.h b/src/theory/bv/bv_eager_solver.h
index 6182832e9..e0b55c23b 100644
--- a/src/theory/bv/bv_eager_solver.h
+++ b/src/theory/bv/bv_eager_solver.h
@@ -23,7 +23,6 @@
#include <vector>
#include "expr/node.h"
-#include "proof/resolution_bitvector_proof.h"
#include "theory/bv/theory_bv.h"
#include "theory/theory_model.h"
@@ -48,7 +47,6 @@ class EagerBitblastSolver {
bool isInitialized();
void initialize();
bool collectModelInfo(theory::TheoryModel* m, bool fullModel);
- void setProofLog(proof::BitVectorProof* bvp);
private:
context::CDHashSet<Node, NodeHashFunction> d_assertionSet;
@@ -61,7 +59,6 @@ class EagerBitblastSolver {
bool d_useAig;
TheoryBV* d_bv;
- 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 725b61f95..f4b88b719 100644
--- a/src/theory/bv/bv_subtheory.h
+++ b/src/theory/bv/bv_subtheory.h
@@ -25,10 +25,6 @@
namespace CVC4 {
-namespace proof {
-class BitVectorProof;
-}
-
namespace theory {
class TheoryModel;
@@ -72,7 +68,6 @@ class SubtheorySolver {
SubtheorySolver(context::Context* c, TheoryBV* bv)
: d_context(c),
d_bv(bv),
- d_bvp(nullptr),
d_assertionQueue(c),
d_assertionIndex(c, 0) {}
virtual ~SubtheorySolver() {}
@@ -93,7 +88,7 @@ class SubtheorySolver {
return res;
}
virtual void assertFact(TNode fact) { d_assertionQueue.push_back(fact); }
- virtual void setProofLog(proof::BitVectorProof* bvp) {}
+
AssertionQueue::const_iterator assertionsBegin() {
return d_assertionQueue.begin();
}
@@ -107,8 +102,6 @@ class SubtheorySolver {
/** The bit-vector theory */
TheoryBV* d_bv;
- /** proof log */
- proof::ResolutionBitVectorProof* d_bvp;
AssertionQueue d_assertionQueue;
context::CDO<uint32_t> d_assertionIndex;
}; /* class SubtheorySolver */
diff --git a/src/theory/bv/bv_subtheory_algebraic.cpp b/src/theory/bv/bv_subtheory_algebraic.cpp
index e5a416a1b..80a6aeb86 100644
--- a/src/theory/bv/bv_subtheory_algebraic.cpp
+++ b/src/theory/bv/bv_subtheory_algebraic.cpp
@@ -715,7 +715,8 @@ bool AlgebraicSolver::collectModelInfo(TheoryModel* model, bool fullModel)
Debug("bitvector-model") << "AlgebraicSolver::collectModelInfo\n";
AlwaysAssert(!d_quickSolver->inConflict());
set<Node> termSet;
- d_bv->computeRelevantTerms(termSet);
+ const std::set<Kind>& irrKinds = model->getIrrelevantKinds();
+ d_bv->computeAssertedTerms(termSet, irrKinds, true);
// collect relevant terms that the bv theory abstracts to variables
// (variables and parametric terms such as select apply_uf)
diff --git a/src/theory/bv/bv_subtheory_bitblast.cpp b/src/theory/bv/bv_subtheory_bitblast.cpp
index 8f87bc4b8..28c70a5b8 100644
--- a/src/theory/bv/bv_subtheory_bitblast.cpp
+++ b/src/theory/bv/bv_subtheory_bitblast.cpp
@@ -18,7 +18,6 @@
#include "decision/decision_attributes.h"
#include "options/bv_options.h"
#include "options/decision_options.h"
-#include "proof/proof_manager.h"
#include "smt/smt_statistics_registry.h"
#include "theory/bv/abstraction.h"
#include "theory/bv/bitblast/lazy_bitblaster.h"
@@ -276,12 +275,6 @@ void BitblastSolver::setConflict(TNode conflict) {
d_bv->setConflict(final_conflict);
}
-void BitblastSolver::setProofLog(proof::BitVectorProof* bvp)
-{
- d_bitblaster->setProofLog( bvp );
- bvp->setBitblaster(d_bitblaster.get());
-}
-
}/* namespace CVC4::theory::bv */
}/* namespace CVC4::theory */
}/* namespace CVC4 */
diff --git a/src/theory/bv/bv_subtheory_bitblast.h b/src/theory/bv/bv_subtheory_bitblast.h
index a2b099609..60ef08d93 100644
--- a/src/theory/bv/bv_subtheory_bitblast.h
+++ b/src/theory/bv/bv_subtheory_bitblast.h
@@ -24,10 +24,6 @@
namespace CVC4 {
-namespace proof {
-class ResolutionBitVectorProof;
-}
-
namespace theory {
namespace bv {
@@ -79,7 +75,6 @@ public:
void bitblastQueue();
void setAbstraction(AbstractionModule* module);
uint64_t computeAtomWeight(TNode atom);
- void setProofLog(proof::BitVectorProof* bvp) override;
};
} /* namespace CVC4::theory::bv */
diff --git a/src/theory/bv/bv_subtheory_core.cpp b/src/theory/bv/bv_subtheory_core.cpp
index d8f376a74..38c5cb482 100644
--- a/src/theory/bv/bv_subtheory_core.cpp
+++ b/src/theory/bv/bv_subtheory_core.cpp
@@ -354,7 +354,8 @@ bool CoreSolver::collectModelInfo(TheoryModel* m, bool fullModel)
}
}
set<Node> termSet;
- d_bv->computeRelevantTerms(termSet);
+ const std::set<Kind>& irrKinds = m->getIrrelevantKinds();
+ d_bv->computeAssertedTerms(termSet, irrKinds, true);
if (!m->assertEqualityEngine(d_equalityEngine, &termSet))
{
return false;
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index 1696d6185..d6492f177 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -18,8 +18,6 @@
#include "expr/node_algorithm.h"
#include "options/bv_options.h"
#include "options/smt_options.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
#include "smt/smt_statistics_registry.h"
#include "theory/bv/abstraction.h"
#include "theory/bv/bv_eager_solver.h"
@@ -83,19 +81,19 @@ TheoryBV::TheoryBV(context::Context* c,
return;
}
- if (options::bitvectorEqualitySolver() && !options::proof())
+ if (options::bitvectorEqualitySolver())
{
d_subtheories.emplace_back(new CoreSolver(c, this, d_extTheory.get()));
d_subtheoryMap[SUB_CORE] = d_subtheories.back().get();
}
- if (options::bitvectorInequalitySolver() && !options::proof())
+ if (options::bitvectorInequalitySolver())
{
d_subtheories.emplace_back(new InequalitySolver(c, u, this));
d_subtheoryMap[SUB_INEQUALITY] = d_subtheories.back().get();
}
- if (options::bitvectorAlgebraicSolver() && !options::proof())
+ if (options::bitvectorAlgebraicSolver())
{
d_subtheories.emplace_back(new AlgebraicSolver(c, this));
d_subtheoryMap[SUB_ALGEBRAIC] = d_subtheories.back().get();
@@ -230,8 +228,11 @@ TrustNode TheoryBV::expandDefinition(Node node)
TNode num = node[0], den = node[1];
Node den_eq_0 = nm->mkNode(kind::EQUAL, den, utils::mkZero(width));
- Node divTotalNumDen = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_UDIV_TOTAL :
- kind::BITVECTOR_UREM_TOTAL, num, den);
+ Node divTotalNumDen = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV
+ ? kind::BITVECTOR_UDIV_TOTAL
+ : kind::BITVECTOR_UREM_TOTAL,
+ num,
+ den);
Node divByZero = getBVDivByZero(node.getKind(), width);
Node divByZeroNum = nm->mkNode(kind::APPLY_UF, divByZero, num);
ret = nm->mkNode(kind::ITE, den_eq_0, divByZeroNum, divTotalNumDen);
@@ -327,7 +328,7 @@ void TheoryBV::check(Effort e)
if (done() && e<Theory::EFFORT_FULL) {
return;
}
-
+
//last call : do reductions on extended bitvector functions
if (e == Theory::EFFORT_LAST_CALL) {
std::vector<Node> nred = d_extTheory->getActive();
@@ -410,7 +411,7 @@ void TheoryBV::check(Effort e)
break;
}
}
-
+
//check extended functions
if (Theory::fullEffort(e)) {
//do inferences (adds external lemmas) TODO: this can be improved to add internal inferences
@@ -431,7 +432,9 @@ void TheoryBV::check(Effort e)
if( doExtfReductions( nred ) ){
return;
}
- }else{
+ }
+ else
+ {
d_needsLastCallCheck = true;
}
}
@@ -726,11 +729,13 @@ TrustNode TheoryBV::ppRewrite(TNode t)
} else if (RewriteRule<UltPlusOne>::applies(t)) {
Node result = RewriteRule<UltPlusOne>::run<false>(t);
res = Rewriter::rewrite(result);
- } else if( res.getKind() == kind::EQUAL &&
- ((res[0].getKind() == kind::BITVECTOR_PLUS &&
- RewriteRule<ConcatToMult>::applies(res[1])) ||
- (res[1].getKind() == kind::BITVECTOR_PLUS &&
- RewriteRule<ConcatToMult>::applies(res[0])))) {
+ }
+ else if (res.getKind() == kind::EQUAL
+ && ((res[0].getKind() == kind::BITVECTOR_PLUS
+ && RewriteRule<ConcatToMult>::applies(res[1]))
+ || (res[1].getKind() == kind::BITVECTOR_PLUS
+ && RewriteRule<ConcatToMult>::applies(res[0]))))
+ {
Node mult = RewriteRule<ConcatToMult>::applies(res[0])?
RewriteRule<ConcatToMult>::run<false>(res[0]) :
RewriteRule<ConcatToMult>::run<true>(res[1]);
@@ -743,9 +748,13 @@ TrustNode TheoryBV::ppRewrite(TNode t)
} else {
res = t;
}
- } else if (RewriteRule<SignExtendEqConst>::applies(t)) {
+ }
+ else if (RewriteRule<SignExtendEqConst>::applies(t))
+ {
res = RewriteRule<SignExtendEqConst>::run<false>(t);
- } else if (RewriteRule<ZeroExtendEqConst>::applies(t)) {
+ }
+ else if (RewriteRule<ZeroExtendEqConst>::applies(t))
+ {
res = RewriteRule<ZeroExtendEqConst>::run<false>(t);
}
else if (RewriteRule<NormalizeEqPlusNeg>::applies(t))
@@ -960,20 +969,6 @@ bool TheoryBV::applyAbstraction(const std::vector<Node>& assertions, std::vector
return changed;
}
-void TheoryBV::setProofLog(proof::BitVectorProof* bvp)
-{
- if (options::bitblastMode() == options::BitblastMode::EAGER)
- {
- d_eagerSolver->setProofLog(bvp);
- }
- else
- {
- for( unsigned i=0; i< d_subtheories.size(); i++ ){
- d_subtheories[i]->setProofLog( bvp );
- }
- }
-}
-
void TheoryBV::setConflict(Node conflict)
{
if (options::bvAbstraction())
diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h
index c6e9282f4..2f63f1a52 100644
--- a/src/theory/bv/theory_bv.h
+++ b/src/theory/bv/theory_bv.h
@@ -32,12 +32,7 @@
#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 theory {
@@ -123,8 +118,6 @@ class TheoryBV : public Theory {
bool applyAbstraction(const std::vector<Node>& assertions,
std::vector<Node>& new_assertions);
- void setProofLog(proof::BitVectorProof* bvp);
-
private:
class Statistics
{
@@ -197,7 +190,7 @@ class TheoryBV : public Theory {
std::unique_ptr<EagerBitblastSolver> d_eagerSolver;
std::unique_ptr<AbstractionModule> d_abstractionModule;
bool d_calledPreregister;
-
+
//for extended functions
bool d_needsLastCallCheck;
context::CDHashSet<Node, NodeHashFunction> d_extf_range_infer;
@@ -225,7 +218,7 @@ class TheoryBV : public Theory {
* (ite ((_ extract 1 0) x) 1 0)
*/
bool doExtfReductions( std::vector< Node >& terms );
-
+
bool wasPropagatedBySubtheory(TNode literal) const {
return d_propagatedBy.find(literal) != d_propagatedBy.end();
}
@@ -266,7 +259,11 @@ class TheoryBV : public Theory {
void sendConflict();
- void lemma(TNode node) { d_out->lemma(node, RULE_CONFLICT); d_lemmasAdded = true; }
+ void lemma(TNode node)
+ {
+ d_out->lemma(node);
+ d_lemmasAdded = true;
+ }
void checkForLemma(TNode node);
diff --git a/src/theory/combination_engine.cpp b/src/theory/combination_engine.cpp
index e1317cf29..f1e977fe3 100644
--- a/src/theory/combination_engine.cpp
+++ b/src/theory/combination_engine.cpp
@@ -113,7 +113,7 @@ eq::EqualityEngineNotify* CombinationEngine::getModelEqualityEngineNotify()
void CombinationEngine::sendLemma(TrustNode trn, TheoryId atomsTo)
{
- d_te.lemma(trn.getNode(), RULE_INVALID, false, LemmaProperty::NONE, atomsTo);
+ d_te.lemma(trn.getNode(), false, LemmaProperty::NONE, atomsTo);
}
void CombinationEngine::resetRound()
diff --git a/src/theory/datatypes/inference_manager.cpp b/src/theory/datatypes/inference_manager.cpp
new file mode 100644
index 000000000..1faf71aa9
--- /dev/null
+++ b/src/theory/datatypes/inference_manager.cpp
@@ -0,0 +1,126 @@
+/********************* */
+/*! \file inference_manager.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Datatypes inference manager
+ **/
+
+#include "theory/datatypes/inference_manager.h"
+
+#include "expr/dtype.h"
+#include "options/datatypes_options.h"
+#include "theory/theory.h"
+
+using namespace CVC4::kind;
+
+namespace CVC4 {
+namespace theory {
+namespace datatypes {
+
+DatatypesInference::DatatypesInference(Node conc, Node exp, ProofGenerator* pg)
+ : SimpleTheoryInternalFact(conc, exp, pg)
+{
+ // false is not a valid explanation
+ Assert(d_exp.isNull() || !d_exp.isConst() || d_exp.getConst<bool>());
+}
+
+bool DatatypesInference::mustCommunicateFact(Node n, Node exp)
+{
+ Trace("dt-lemma-debug") << "Compute for " << exp << " => " << n << std::endl;
+ bool addLemma = false;
+ if (options::dtInferAsLemmas() && !exp.isConst())
+ {
+ // all units are lemmas
+ addLemma = true;
+ }
+ else if (n.getKind() == EQUAL)
+ {
+ TypeNode tn = n[0].getType();
+ if (!tn.isDatatype())
+ {
+ addLemma = true;
+ }
+ else
+ {
+ const DType& dt = tn.getDType();
+ addLemma = dt.involvesExternalType();
+ }
+ }
+ else if (n.getKind() == LEQ || n.getKind() == OR)
+ {
+ addLemma = true;
+ }
+ if (addLemma)
+ {
+ Trace("dt-lemma-debug") << "Communicate " << n << std::endl;
+ return true;
+ }
+ Trace("dt-lemma-debug") << "Do not need to communicate " << n << std::endl;
+ return false;
+}
+
+bool DatatypesInference::process(TheoryInferenceManager* im)
+{
+ // check to see if we have to communicate it to the rest of the system
+ if (mustCommunicateFact(d_conc, d_exp))
+ {
+ // send it as an (explained) lemma
+ std::vector<Node> exp;
+ if (!d_exp.isNull() && !d_exp.isConst())
+ {
+ exp.push_back(d_exp);
+ }
+ return im->lemmaExp(d_conc, exp, {});
+ }
+ // assert the internal fact
+ bool polarity = d_conc.getKind() != NOT;
+ TNode atom = polarity ? d_conc : d_conc[0];
+ im->assertInternalFact(atom, polarity, d_exp);
+ return true;
+}
+
+InferenceManager::InferenceManager(Theory& t,
+ TheoryState& state,
+ ProofNodeManager* pnm)
+ : InferenceManagerBuffered(t, state, pnm)
+{
+}
+
+void InferenceManager::addPendingInference(Node conc,
+ Node exp,
+ ProofGenerator* pg)
+{
+ d_pendingFact.emplace_back(new DatatypesInference(conc, exp, pg));
+}
+
+void InferenceManager::process()
+{
+ // process pending lemmas, used infrequently, only for definitional lemmas
+ doPendingLemmas();
+ // now process the pending facts
+ doPendingFacts();
+}
+
+bool InferenceManager::sendLemmas(const std::vector<Node>& lemmas)
+{
+ bool ret = false;
+ for (const Node& lem : lemmas)
+ {
+ if (lemma(lem))
+ {
+ ret = true;
+ }
+ }
+ return ret;
+}
+
+} // namespace datatypes
+} // namespace theory
+} // namespace CVC4
diff --git a/src/theory/datatypes/inference_manager.h b/src/theory/datatypes/inference_manager.h
new file mode 100644
index 000000000..0dfdfb281
--- /dev/null
+++ b/src/theory/datatypes/inference_manager.h
@@ -0,0 +1,95 @@
+/********************* */
+/*! \file inference_manager.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Datatypes inference manager
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__THEORY__DATATYPES__INFERENCE_MANAGER_H
+#define CVC4__THEORY__DATATYPES__INFERENCE_MANAGER_H
+
+#include "context/cdhashmap.h"
+#include "expr/node.h"
+#include "theory/inference_manager_buffered.h"
+
+namespace CVC4 {
+namespace theory {
+namespace datatypes {
+
+/**
+ * A custom inference class. The main feature of this class is that it
+ * dynamically decides whether to process itself as a fact or as a lemma,
+ * based on the mustCommunicateFact method below.
+ */
+class DatatypesInference : public SimpleTheoryInternalFact
+{
+ public:
+ DatatypesInference(Node conc, Node exp, ProofGenerator* pg);
+ /**
+ * Must communicate fact method.
+ * The datatypes decision procedure makes "internal" inferences :
+ * (1) Unification : C( t1...tn ) = C( s1...sn ) => ti = si
+ * (2) Label : ~is_C1(t) ... ~is_C{i-1}(t) ~is_C{i+1}(t) ... ~is_Cn(t) =>
+ * is_Ci( t )
+ * (3) Instantiate : is_C( t ) => t = C( sel_1( t ) ... sel_n( t ) )
+ * (4) collapse selector : S( C( t1...tn ) ) = t'
+ * (5) collapse term size : size( C( t1...tn ) ) = 1 + size( t1 ) + ... +
+ * size( tn )
+ * (6) non-negative size : 0 <= size(t)
+ * This method returns true if the fact must be sent out as a lemma. If it
+ * returns false, then we assert the fact internally. We may need to
+ * communicate outwards if the conclusions involve other theories. Also
+ * communicate (6) and OR conclusions.
+ */
+ static bool mustCommunicateFact(Node n, Node exp);
+ /**
+ * Process this fact, possibly as a fact or as a lemma, depending on the
+ * above method.
+ */
+ bool process(TheoryInferenceManager* im) override;
+};
+
+/**
+ * The datatypes inference manager, which uses the above class for
+ * inferences.
+ */
+class InferenceManager : public InferenceManagerBuffered
+{
+ typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
+
+ public:
+ InferenceManager(Theory& t, TheoryState& state, ProofNodeManager* pnm);
+ ~InferenceManager() {}
+ /**
+ * Add pending inference, which may be processed as either a fact or
+ * a lemma based on mustCommunicateFact in DatatypesInference above.
+ */
+ void addPendingInference(Node conc, Node exp, ProofGenerator* pg = nullptr);
+ /**
+ * Process the current lemmas and facts. This is a custom method that can
+ * be seen as overriding the behavior of calling both doPendingLemmas and
+ * doPendingFacts. It determines whether facts should be sent as lemmas
+ * or processed internally.
+ */
+ void process();
+ /**
+ * Send lemmas with property NONE on the output channel immediately.
+ * Returns true if any lemma was sent.
+ */
+ bool sendLemmas(const std::vector<Node>& lemmas);
+};
+
+} // namespace datatypes
+} // namespace theory
+} // namespace CVC4
+
+#endif
diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp
index a98c77a5d..5253414a9 100644
--- a/src/theory/datatypes/theory_datatypes.cpp
+++ b/src/theory/datatypes/theory_datatypes.cpp
@@ -47,22 +47,18 @@ TheoryDatatypes::TheoryDatatypes(Context* c,
const LogicInfo& logicInfo,
ProofNodeManager* pnm)
: Theory(THEORY_DATATYPES, c, u, out, valuation, logicInfo, pnm),
- d_infer(c),
- d_infer_exp(c),
d_term_sk(u),
d_notify(*this),
d_labels(c),
d_selector_apps(c),
- d_conflict(c, false),
- d_addedLemma(false),
- d_addedFact(false),
d_collectTermsCache(c),
d_collectTermsCacheU(u),
d_functionTerms(c),
d_singleton_eq(u),
d_lemmas_produced_c(u),
d_sygusExtension(nullptr),
- d_state(c, u, valuation)
+ d_state(c, u, valuation),
+ d_im(*this, d_state, pnm)
{
d_true = NodeManager::currentNM()->mkConst( true );
@@ -71,6 +67,7 @@ TheoryDatatypes::TheoryDatatypes(Context* c,
// indicate we are using the default theory state object
d_theoryState = &d_state;
+ d_inferManager = &d_im;
}
TheoryDatatypes::~TheoryDatatypes() {
@@ -156,64 +153,43 @@ TNode TheoryDatatypes::getEqcConstructor( TNode r ) {
}
}
-void TheoryDatatypes::check(Effort e) {
- if (done() && e<EFFORT_FULL) {
- return;
- }
- Assert(d_pending.empty());
- d_addedLemma = false;
-
- if( e == EFFORT_LAST_CALL ){
+bool TheoryDatatypes::preCheck(Effort level)
+{
+ d_im.reset();
+ return false;
+}
+
+void TheoryDatatypes::postCheck(Effort level)
+{
+ if (level == EFFORT_LAST_CALL)
+ {
Assert(d_sygusExtension != nullptr);
- std::vector< Node > lemmas;
+ std::vector<Node> lemmas;
d_sygusExtension->check(lemmas);
- doSendLemmas( lemmas );
+ d_im.sendLemmas(lemmas);
return;
}
-
- TimerStat::CodeTimer checkTimer(d_checkTime);
-
- Trace("datatypes-check") << "Check effort " << e << std::endl;
- while(!done() && !d_conflict) {
- // Get all the assertions
- Assertion assertion = get();
- TNode fact = assertion.d_assertion;
- Trace("datatypes-assert") << "Assert " << fact << std::endl;
-
- TNode atom CVC4_UNUSED = fact.getKind() == kind::NOT ? fact[0] : fact;
-
- // extra debug check to make sure that the rewriter did its job correctly
- Assert(atom.getKind() != kind::EQUAL
- || (atom[0].getKind() != kind::TUPLE_UPDATE
- && atom[1].getKind() != kind::TUPLE_UPDATE
- && atom[0].getKind() != kind::RECORD_UPDATE
- && atom[1].getKind() != kind::RECORD_UPDATE))
- << "tuple/record escaped into datatypes decision procedure; should "
- "have been rewritten away";
-
- //assert the fact
- assertFact( fact, fact );
- flushPendingFacts();
- }
-
- if( e == EFFORT_FULL && !d_conflict && !d_addedLemma && !d_valuation.needCheck() ) {
+ else if (level == EFFORT_FULL && !d_state.isInConflict()
+ && !d_im.hasSentLemma() && !d_valuation.needCheck())
+ {
//check for cycles
- Assert(d_pending.empty());
+ Assert(!d_im.hasPendingFact());
do {
- d_addedFact = false;
+ d_im.reset();
Trace("datatypes-proc") << "Check cycles..." << std::endl;
checkCycles();
Trace("datatypes-proc") << "...finish check cycles" << std::endl;
- flushPendingFacts();
- if( d_conflict || d_addedLemma ){
+ d_im.process();
+ if (d_state.isInConflict() || d_im.hasSentLemma())
+ {
return;
}
- }while( d_addedFact );
-
+ } while (d_im.hasSentFact());
+
//check for splits
- Trace("datatypes-debug") << "Check for splits " << e << endl;
+ Trace("datatypes-debug") << "Check for splits " << endl;
do {
- d_addedFact = false;
+ d_im.reset();
std::map< TypeNode, Node > rec_singletons;
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(d_equalityEngine);
while( !eqcs_i.isFinished() ){
@@ -265,7 +241,7 @@ void TheoryDatatypes::check(Effort e) {
assumptions.push_back(assumption);
Node lemma = assumptions.size()==1 ? assumptions[0] : NodeManager::currentNM()->mkNode( OR, assumptions );
Trace("dt-singleton") << "*************Singleton equality lemma " << lemma << std::endl;
- doSendLemma( lemma );
+ d_im.lemma(lemma);
}
}
}else{
@@ -279,8 +255,6 @@ void TheoryDatatypes::check(Effort e) {
//all other cases
std::vector< bool > pcons;
getPossibleCons( eqc, n, pcons );
- //std::map< int, bool > sel_apps;
- //getSelectorsForCons( n, sel_apps );
//check if we do not need to resolve the constructor type for this equivalence class.
// this is if there are no selectors for this equivalence class, and its possible values are infinite,
// then do not split.
@@ -322,10 +296,8 @@ void TheoryDatatypes::check(Effort e) {
//this may not be necessary?
//if only one constructor, then this term must be this constructor
Node t = utils::mkTester(n, 0, dt);
- d_pending.push_back( t );
- d_pending_exp[ t ] = d_true;
+ d_im.addPendingInference(t, d_true);
Trace("datatypes-infer") << "DtInfer : 1-cons (full) : " << t << std::endl;
- d_infer.push_back( t );
}else{
Assert(consIndex != -1 || dt.isSygus());
if( options::dtBinarySplit() && consIndex!=-1 ){
@@ -335,14 +307,13 @@ void TheoryDatatypes::check(Effort e) {
NodeBuilder<> nb(kind::OR);
nb << test << test.notNode();
Node lemma = nb;
- doSendLemma( lemma );
+ d_im.lemma(lemma);
d_out->requirePhase( test, true );
}else{
Trace("dt-split") << "*************Split for constructors on " << n << endl;
Node lemma = utils::mkSplit(n, dt);
Trace("dt-split-debug") << "Split lemma is : " << lemma << std::endl;
- d_out->lemma(lemma, LemmaProperty::SEND_ATOMS);
- d_addedLemma = true;
+ d_im.lemma(lemma, LemmaProperty::SEND_ATOMS, false);
}
if( !options::dtBlastSplits() ){
break;
@@ -358,29 +329,32 @@ void TheoryDatatypes::check(Effort e) {
}
++eqcs_i;
}
- if (d_addedLemma)
+ if (d_im.hasSentLemma())
{
// clear pending facts: we added a lemma, so internal inferences are
// no longer necessary
- d_pending.clear();
- d_pending_exp.clear();
+ d_im.clearPendingFacts();
}
else
{
// we did not add a lemma, process internal inferences. This loop
// will repeat.
Trace("datatypes-debug") << "Flush pending facts..." << std::endl;
- flushPendingFacts();
+ d_im.process();
}
- }while( !d_conflict && !d_addedLemma && d_addedFact );
- Trace("datatypes-debug") << "Finished, conflict=" << d_conflict << ", lemmas=" << d_addedLemma << std::endl;
- if( !d_conflict ){
+ } while (!d_state.isInConflict() && !d_im.hasSentLemma()
+ && d_im.hasSentFact());
+ Trace("datatypes-debug")
+ << "Finished, conflict=" << d_state.isInConflict()
+ << ", lemmas=" << d_im.hasSentLemma() << std::endl;
+ if (!d_state.isInConflict())
+ {
Trace("dt-model-debug") << std::endl;
printModelDebug("dt-model-debug");
}
}
- Trace("datatypes-check") << "Finished check effort " << e << std::endl;
+ Trace("datatypes-check") << "Finished check effort " << level << std::endl;
if( Debug.isOn("datatypes") || Debug.isOn("datatypes-split") ) {
Notice() << "TheoryDatatypes::check(): done" << endl;
}
@@ -390,100 +364,17 @@ bool TheoryDatatypes::needsCheckLastEffort() {
return d_sygusExtension != nullptr;
}
-void TheoryDatatypes::flushPendingFacts(){
- //pending lemmas: used infrequently, only for definitional lemmas
- if( !d_pending_lem.empty() ){
- int i = 0;
- while( i<(int)d_pending_lem.size() ){
- doSendLemma( d_pending_lem[i] );
- i++;
- }
- d_pending_lem.clear();
- }
- int i = 0;
- while( !d_conflict && i<(int)d_pending.size() ){
- Node fact = d_pending[i];
- Node exp = d_pending_exp[ fact ];
- Trace("datatypes-debug") << "Assert fact (#" << (i+1) << "/" << d_pending.size() << ") " << fact << " with explanation " << exp << std::endl;
- //check to see if we have to communicate it to the rest of the system
- if( mustCommunicateFact( fact, exp ) ){
- Node lem = fact;
- if( exp.isNull() || exp==d_true ){
- Trace("dt-lemma-debug") << "Trivial explanation." << std::endl;
- }else{
- Trace("dt-lemma-debug") << "Get explanation..." << std::endl;
- std::vector< TNode > assumptions;
- //if( options::dtRExplainLemmas() ){
- explain( exp, assumptions );
- //}else{
- // ee_exp = exp;
- //}
- //Trace("dt-lemma-debug") << "Explanation : " << ee_exp << std::endl;
- if( assumptions.empty() ){
- lem = fact;
- }else{
- std::vector< Node > children;
- for (const TNode& assumption : assumptions)
- {
- children.push_back(assumption.negate());
- }
- children.push_back( fact );
- lem = NodeManager::currentNM()->mkNode( OR, children );
- }
- }
- Trace("dt-lemma") << "Datatypes lemma : " << lem << std::endl;
- doSendLemma( lem );
- }else{
- assertFact( fact, exp );
- d_addedFact = true;
- }
- Trace("datatypes-debug") << "Finished fact " << fact << ", now = " << d_conflict << " " << d_pending.size() << std::endl;
- i++;
- }
- d_pending.clear();
- d_pending_exp.clear();
-}
-
-bool TheoryDatatypes::doSendLemma( Node lem ) {
- if( d_lemmas_produced_c.find( lem )==d_lemmas_produced_c.end() ){
- Trace("dt-lemma-send") << "TheoryDatatypes::doSendLemma : " << lem << std::endl;
- d_lemmas_produced_c[lem] = true;
- d_out->lemma( lem );
- d_addedLemma = true;
- return true;
- }else{
- Trace("dt-lemma-send") << "TheoryDatatypes::doSendLemma : duplicate : "
- << lem << std::endl;
- return false;
- }
-}
-bool TheoryDatatypes::doSendLemmas( std::vector< Node >& lemmas ){
- bool ret = false;
- for (const Node& lem : lemmas)
- {
- bool cret = doSendLemma(lem);
- ret = ret || cret;
- }
- lemmas.clear();
- return ret;
-}
-
-void TheoryDatatypes::assertFact( Node fact, Node exp)
+void TheoryDatatypes::notifyFact(TNode atom,
+ bool polarity,
+ TNode fact,
+ bool isInternal)
{
- Trace("datatypes-debug") << "TheoryDatatypes::assertFact : " << fact << std::endl;
- bool polarity = fact.getKind() != kind::NOT;
- TNode atom = polarity ? fact : fact[0];
- if (atom.getKind() == kind::EQUAL) {
- d_equalityEngine->assertEquality(atom, polarity, exp);
- }else{
- d_equalityEngine->assertPredicate(atom, polarity, exp);
- }
// could be sygus-specific
if (d_sygusExtension)
{
std::vector< Node > lemmas;
d_sygusExtension->assertFact(atom, polarity, lemmas);
- doSendLemmas( lemmas );
+ d_im.sendLemmas(lemmas);
}
//add to tester if applicable
Node t_arg;
@@ -493,28 +384,37 @@ void TheoryDatatypes::assertFact( Node fact, Node exp)
Trace("dt-tester") << "Assert tester : " << atom << " for " << t_arg << std::endl;
Node rep = getRepresentative( t_arg );
EqcInfo* eqc = getOrMakeEqcInfo( rep, true );
- addTester( tindex, fact, eqc, rep, t_arg );
+ Node tst =
+ isInternal ? (polarity ? Node(atom) : atom.notNode()) : Node(fact);
+ addTester(tindex, tst, eqc, rep, t_arg);
Trace("dt-tester") << "Done assert tester." << std::endl;
Trace("dt-tester") << "Done pending merges." << std::endl;
- if( !d_conflict && polarity ){
+ if (!d_state.isInConflict() && polarity)
+ {
if (d_sygusExtension)
{
Trace("dt-tester") << "Assert tester to sygus : " << atom << std::endl;
- //Assert( !d_sygus_util->d_conflict );
std::vector< Node > lemmas;
d_sygusExtension->assertTester(tindex, t_arg, atom, lemmas);
Trace("dt-tester") << "Done assert tester to sygus." << std::endl;
- doSendLemmas( lemmas );
+ d_im.sendLemmas(lemmas);
}
}
}else{
Trace("dt-tester-debug") << "Assert (non-tester) : " << atom << std::endl;
}
Trace("datatypes-debug") << "TheoryDatatypes::assertFact : finished " << fact << std::endl;
+ // now, flush pending facts if this wasn't an internal call
+ if (!isInternal)
+ {
+ d_im.process();
+ }
}
-void TheoryDatatypes::preRegisterTerm(TNode n) {
- Debug("datatypes-prereg") << "TheoryDatatypes::preRegisterTerm() " << n << endl;
+void TheoryDatatypes::preRegisterTerm(TNode n)
+{
+ Debug("datatypes-prereg")
+ << "TheoryDatatypes::preRegisterTerm() " << n << endl;
collectTerms( n );
switch (n.getKind()) {
case kind::EQUAL:
@@ -530,12 +430,11 @@ void TheoryDatatypes::preRegisterTerm(TNode n) {
{
std::vector< Node > lemmas;
d_sygusExtension->preRegisterTerm(n, lemmas);
- doSendLemmas( lemmas );
+ d_im.sendLemmas(lemmas);
}
- // d_equalityEngine->addTriggerTerm(n, THEORY_DATATYPES);
break;
}
- flushPendingFacts();
+ d_im.process();
}
TrustNode TheoryDatatypes::expandDefinition(Node n)
@@ -699,21 +598,13 @@ TrustNode TheoryDatatypes::ppRewrite(TNode in)
return TrustNode::null();
}
-void TheoryDatatypes::notifySharedTerm(TNode t)
-{
- Debug("datatypes") << "TheoryDatatypes::notifySharedTerm(): " << t << " "
- << t.getType().isBoolean() << endl;
- d_equalityEngine->addTriggerTerm(t, THEORY_DATATYPES);
- Debug("datatypes") << "TheoryDatatypes::notifySharedTerm() finished"
- << std::endl;
-}
-
bool TheoryDatatypes::propagateLit(TNode literal)
{
Debug("dt::propagate") << "TheoryDatatypes::propagateLit(" << literal << ")"
<< std::endl;
// If already in conflict, no more propagation
- if (d_conflict) {
+ if (d_state.isInConflict())
+ {
Debug("dt::propagate") << "TheoryDatatypes::propagateLit(" << literal
<< "): already in conflict" << std::endl;
return false;
@@ -723,7 +614,7 @@ bool TheoryDatatypes::propagateLit(TNode literal)
bool ok = d_out->propagate(literal);
if (!ok) {
Trace("dt-conflict") << "CONFLICT: Eq engine propagate conflict " << std::endl;
- d_conflict = true;
+ d_state.notifyInConflict();
}
return ok;
}
@@ -805,7 +696,7 @@ void TheoryDatatypes::conflict(TNode a, TNode b){
d_conflictNode = explainLit(eq);
Trace("dt-conflict") << "CONFLICT: Eq engine conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
- d_conflict = true;
+ d_state.notifyInConflict();
}
/** called when a new equivalance class is created */
@@ -826,7 +717,8 @@ void TheoryDatatypes::eqNotifyMerge(TNode t1, TNode t2)
}
void TheoryDatatypes::merge( Node t1, Node t2 ){
- if( !d_conflict ){
+ if (!d_state.isInConflict())
+ {
TNode trep1 = t1;
TNode trep2 = t2;
Trace("datatypes-debug") << "Merge " << t1 << " " << t2 << std::endl;
@@ -855,7 +747,7 @@ void TheoryDatatypes::merge( Node t1, Node t2 ){
d_conflictNode = explainLit(unifEq);
Trace("dt-conflict") << "CONFLICT: Clash conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
- d_conflict = true;
+ d_state.notifyInConflict();
return;
}
else
@@ -864,22 +756,10 @@ void TheoryDatatypes::merge( Node t1, Node t2 ){
for( int i=0; i<(int)cons1.getNumChildren(); i++ ) {
if( !areEqual( cons1[i], cons2[i] ) ){
Node eq = cons1[i].eqNode( cons2[i] );
- d_pending.push_back( eq );
- d_pending_exp[ eq ] = unifEq;
+ d_im.addPendingInference(eq, unifEq);
Trace("datatypes-infer") << "DtInfer : cons-inj : " << eq << " by " << unifEq << std::endl;
- d_infer.push_back( eq );
- d_infer_exp.push_back( unifEq );
}
}
-/*
- for( unsigned i=0; i<rew.size(); i++ ){
- d_pending.push_back( rew[i] );
- d_pending_exp[ rew[i] ] = unifEq;
- Trace("datatypes-infer") << "DtInfer : cons-inj : " << rew[i] << " by " << unifEq << std::endl;
- d_infer.push_back( rew[i] );
- d_infer_exp.push_back( unifEq );
- }
-*/
}
}
Trace("datatypes-debug") << " instantiated : " << eqc1->d_inst << " " << eqc2->d_inst << std::endl;
@@ -889,7 +769,8 @@ void TheoryDatatypes::merge( Node t1, Node t2 ){
Trace("datatypes-debug") << " must check if it is okay to set the constructor." << std::endl;
checkInst = true;
addConstructor( eqc2->d_constructor.get(), eqc1, t1 );
- if( d_conflict ){
+ if (d_state.isInConflict())
+ {
return;
}
}
@@ -916,7 +797,8 @@ void TheoryDatatypes::merge( Node t1, Node t2 ){
Node t_arg = d_labels_args[t2][i];
unsigned tindex = d_labels_tindex[t2][i];
addTester( tindex, t, eqc1, t1, t_arg );
- if( d_conflict ){
+ if (d_state.isInConflict())
+ {
Trace("datatypes-debug") << " conflict!" << std::endl;
return;
}
@@ -940,7 +822,8 @@ void TheoryDatatypes::merge( Node t1, Node t2 ){
if( checkInst ){
Trace("datatypes-debug") << " checking instantiate" << std::endl;
instantiate( eqc1, t1 );
- if( d_conflict ){
+ if (d_state.isInConflict())
+ {
return;
}
}
@@ -979,6 +862,8 @@ int TheoryDatatypes::getLabelIndex( EqcInfo* eqc, Node n ){
return -1;
}else{
int tindex = utils::isTester(lbl);
+ Trace("datatypes-debug") << "Label of " << n << " is " << lbl
+ << " with tindex " << tindex << std::endl;
Assert(tindex != -1);
return tindex;
}
@@ -1033,9 +918,7 @@ Node TheoryDatatypes::getTermSkolemFor( Node n ) {
d_term_sk[n] = k;
Node eq = k.eqNode( n );
Trace("datatypes-infer") << "DtInfer : ref : " << eq << std::endl;
- d_pending_lem.push_back( eq );
- //doSendLemma( eq );
- //d_pending_exp[ eq ] = d_true;
+ d_im.addPendingLemma(eq);
return k;
}else{
return (*it).second;
@@ -1051,6 +934,7 @@ void TheoryDatatypes::addTester(
Trace("datatypes-debug") << "Add tester : " << t << " to eqc(" << n << ")" << std::endl;
Debug("datatypes-labels") << "Add tester " << t << " " << n << " " << eqc << std::endl;
bool tpolarity = t.getKind()!=NOT;
+ Assert((tpolarity ? t : t[0]).getKind() == APPLY_TESTER);
Node j, jt;
bool makeConflict = false;
int prevTIndex = getLabelIndex(eqc, n);
@@ -1068,7 +952,7 @@ void TheoryDatatypes::addTester(
d_conflictNode = mkAnd( assumptions );
Trace("dt-conflict") << "CONFLICT: Tester eq conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
- d_conflict = true;
+ d_state.notifyInConflict();
return;
}else{
makeConflict = true;
@@ -1122,16 +1006,8 @@ void TheoryDatatypes::addTester(
Debug("datatypes-labels") << "Labels at " << n_lbl << " / " << dt.getNumConstructors() << std::endl;
if( tpolarity ){
instantiate( eqc, n );
- for (unsigned i = 0, ncons = dt.getNumConstructors(); i < ncons; i++)
- {
- if( i!=ttindex && neg_testers.find( i )==neg_testers.end() ){
- Assert(n.getKind() != APPLY_CONSTRUCTOR);
- Node infer = utils::mkTester(n, i, dt).negate();
- Trace("datatypes-infer") << "DtInfer : neg label : " << infer << " by " << t << std::endl;
- d_infer.push_back( infer );
- d_infer_exp.push_back( t );
- }
- }
+ // We could propagate is-C1(x) => not is-C2(x) here for all other
+ // constructors, but empirically this hurts performance.
}else{
//check if we have reached the maximum number of testers
// in this case, add the positive tester
@@ -1167,18 +1043,15 @@ void TheoryDatatypes::addTester(
? NodeManager::currentNM()->mkConst(false)
: utils::mkTester(t_arg, testerIndex, dt);
Node t_concl_exp = ( nb.getNumChildren() == 1 ) ? nb.getChild( 0 ) : nb;
- d_pending.push_back( t_concl );
- d_pending_exp[ t_concl ] = t_concl_exp;
+ d_im.addPendingInference(t_concl, t_concl_exp);
Trace("datatypes-infer") << "DtInfer : label : " << t_concl << " by " << t_concl_exp << std::endl;
- d_infer.push_back( t_concl );
- d_infer_exp.push_back( t_concl_exp );
return;
}
}
}
}
if( makeConflict ){
- d_conflict = true;
+ d_state.notifyInConflict();
Debug("datatypes-labels") << "Explain " << j << " " << t << std::endl;
std::vector< TNode > assumptions;
explain( j, assumptions );
@@ -1245,7 +1118,7 @@ void TheoryDatatypes::addConstructor( Node c, EqcInfo* eqc, Node n ){
d_conflictNode = mkAnd( assumptions );
Trace("dt-conflict") << "CONFLICT: Tester merge eq conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
- d_conflict = true;
+ d_state.notifyInConflict();
return;
}
}
@@ -1332,10 +1205,7 @@ void TheoryDatatypes::collapseSelector( Node s, Node c ) {
Trace("datatypes-infer") << "DtInfer : collapse sel";
//Trace("datatypes-infer") << ( wrong ? " wrong" : "");
Trace("datatypes-infer") << " : " << eq << " by " << peq << std::endl;
- d_pending.push_back( eq );
- d_pending_exp[eq] = peq;
- d_infer.push_back( eq );
- d_infer_exp.push_back(peq);
+ d_im.addPendingInference(eq, peq);
}
}
}
@@ -1483,25 +1353,15 @@ void TheoryDatatypes::computeCareGraph(){
Trace("dt-cg-summary") << "...done, # pairs = " << n_pairs << std::endl;
}
-bool TheoryDatatypes::collectModelInfo(TheoryModel* m)
+bool TheoryDatatypes::collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet)
{
- Trace("dt-cmi") << "Datatypes : Collect model info "
+ Trace("dt-cmi") << "Datatypes : Collect model values "
<< d_equalityEngine->consistent() << std::endl;
Trace("dt-model") << std::endl;
printModelDebug( "dt-model" );
Trace("dt-model") << std::endl;
- std::set<Node> termSet;
-
- // Compute terms appearing in assertions and shared terms, and in inferred equalities
- computeRelevantTerms(termSet);
-
- //combine the equality engine
- if (!m->assertEqualityEngine(d_equalityEngine, &termSet))
- {
- return false;
- }
-
//get all constructors
eq::EqClassesIterator eqccs_i = eq::EqClassesIterator(d_equalityEngine);
std::vector< Node > cons;
@@ -1649,7 +1509,7 @@ Node TheoryDatatypes::getSingletonLemma( TypeNode tn, bool pol ) {
Node v2 = NodeManager::currentNM()->mkSkolem( "k2", tn );
a = v1.eqNode( v2 ).negate();
//send out immediately as lemma
- doSendLemma( a );
+ d_im.lemma(a);
Trace("dt-singleton") << "******** assert " << a << " to avoid singleton cardinality for type " << tn << std::endl;
}
d_singleton_lemma[index][tn] = a;
@@ -1707,7 +1567,7 @@ void TheoryDatatypes::collectTerms( Node n ) {
Node lem = nm->mkNode(LEQ, d_zero, n);
Trace("datatypes-infer")
<< "DtInfer : size geq zero : " << lem << std::endl;
- d_pending_lem.push_back(lem);
+ d_im.addPendingLemma(lem);
}
else if (nk == DT_HEIGHT_BOUND && n[1].getConst<Rational>().isZero())
{
@@ -1732,7 +1592,7 @@ void TheoryDatatypes::collectTerms( Node n ) {
: nm->mkNode(OR, children));
}
Trace("datatypes-infer") << "DtInfer : zero height : " << lem << std::endl;
- d_pending_lem.push_back(lem);
+ d_im.addPendingLemma(lem);
}
}
@@ -1761,6 +1621,7 @@ Node TheoryDatatypes::getInstantiateCons(Node n, const DType& dt, int index)
}
void TheoryDatatypes::instantiate( EqcInfo* eqc, Node n ){
+ Trace("datatypes-debug") << "Instantiate: " << n << std::endl;
//add constructor to equivalence class if not done so already
int index = getLabelIndex( eqc, n );
if (index == -1 || eqc->d_inst)
@@ -1791,13 +1652,10 @@ void TheoryDatatypes::instantiate( EqcInfo* eqc, Node n ){
eq = tt.eqNode(tt_cons);
Debug("datatypes-inst") << "DtInstantiate : " << eqc << " " << eq
<< std::endl;
- d_pending.push_back(eq);
- d_pending_exp[eq] = exp;
+ d_im.addPendingInference(eq, exp);
Trace("datatypes-infer-debug") << "inst : " << eqc << " " << n << std::endl;
Trace("datatypes-infer") << "DtInfer : instantiate : " << eq << " by " << exp
<< std::endl;
- d_infer.push_back(eq);
- d_infer_exp.push_back(exp);
}
void TheoryDatatypes::checkCycles() {
@@ -1832,7 +1690,7 @@ void TheoryDatatypes::checkCycles() {
d_conflictNode = mkAnd( expl );
Trace("dt-conflict") << "CONFLICT: Cycle conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
- d_conflict = true;
+ d_state.notifyInConflict();
return;
}
}
@@ -1882,11 +1740,8 @@ void TheoryDatatypes::checkCycles() {
Trace("dt-cdt") << std::endl;
Node eq = part_out[i][0].eqNode( part_out[i][j] );
Node eqExp = mkAnd( exp );
- d_pending.push_back( eq );
- d_pending_exp[ eq ] = eqExp;
+ d_im.addPendingInference(eq, eqExp);
Trace("datatypes-infer") << "DtInfer : cdt-bisimilar : " << eq << " by " << eqExp << std::endl;
- d_infer.push_back( eq );
- d_infer_exp.push_back( eqExp );
}
}
}
@@ -2061,39 +1916,6 @@ Node TheoryDatatypes::searchForCycle( TNode n, TNode on,
}
}
-bool TheoryDatatypes::mustCommunicateFact( Node n, Node exp ){
- //the datatypes decision procedure makes "internal" inferences apart from the equality engine :
- // (1) Unification : C( t1...tn ) = C( s1...sn ) => ti = si
- // (2) Label : ~is_C1( t ) ... ~is_C{i-1}( t ) ~is_C{i+1}( t ) ... ~is_Cn( t ) => is_Ci( t )
- // (3) Instantiate : is_C( t ) => t = C( sel_1( t ) ... sel_n( t ) )
- // (4) collapse selector : S( C( t1...tn ) ) = t'
- // (5) collapse term size : size( C( t1...tn ) ) = 1 + size( t1 ) + ... + size( tn )
- // (6) non-negative size : 0 <= size( t )
- //We may need to communicate outwards if the conclusions involve other theories. Also communicate (6) and OR conclusions.
- Trace("dt-lemma-debug") << "Compute for " << exp << " => " << n << std::endl;
- bool addLemma = false;
- if( options::dtInferAsLemmas() && exp!=d_true ){
- addLemma = true;
- }else if( n.getKind()==EQUAL ){
- TypeNode tn = n[0].getType();
- if( !tn.isDatatype() ){
- addLemma = true;
- }else{
- const DType& dt = tn.getDType();
- addLemma = dt.involvesExternalType();
- }
- }else if( n.getKind()==LEQ || n.getKind()==OR ){
- addLemma = true;
- }
- if( addLemma ){
- Trace("dt-lemma-debug") << "Communicate " << n << std::endl;
- return true;
- }else{
- Trace("dt-lemma-debug") << "Do not need to communicate " << n << std::endl;
- return false;
- }
-}
-
bool TheoryDatatypes::hasTerm(TNode a) { return d_equalityEngine->hasTerm(a); }
bool TheoryDatatypes::areEqual( TNode a, TNode b ){
@@ -2218,15 +2040,8 @@ Node TheoryDatatypes::mkAnd( std::vector< TNode >& assumptions ) {
}
}
-void TheoryDatatypes::computeRelevantTerms(std::set<Node>& termSet,
- bool includeShared)
+void TheoryDatatypes::computeRelevantTerms(std::set<Node>& termSet)
{
- // Compute terms appearing in assertions and shared terms
- std::set<Kind> irrKinds;
- // testers are not relevant for model construction
- irrKinds.insert(APPLY_TESTER);
- computeRelevantTermsInternal(termSet, irrKinds, includeShared);
-
Trace("dt-cmi") << "Have " << termSet.size() << " relevant terms..."
<< std::endl;
@@ -2267,8 +2082,6 @@ void TheoryDatatypes::computeRelevantTerms(std::set<Node>& termSet,
}
++eqcs_i;
}
- Trace("dt-cmi") << "After adding non-singletons, has " << termSet.size()
- << " relevant terms..." << std::endl;
}
std::pair<bool, Node> TheoryDatatypes::entailmentCheck(TNode lit)
diff --git a/src/theory/datatypes/theory_datatypes.h b/src/theory/datatypes/theory_datatypes.h
index 0d5df098d..37a4f81f7 100644
--- a/src/theory/datatypes/theory_datatypes.h
+++ b/src/theory/datatypes/theory_datatypes.h
@@ -26,6 +26,7 @@
#include "expr/attribute.h"
#include "expr/node_trie.h"
#include "theory/datatypes/datatypes_rewriter.h"
+#include "theory/datatypes/inference_manager.h"
#include "theory/datatypes/sygus_extension.h"
#include "theory/theory.h"
#include "theory/uf/equality_engine.h"
@@ -43,9 +44,6 @@ class TheoryDatatypes : public Theory {
typedef context::CDHashMap<Node, bool, NodeHashFunction> BoolMap;
typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeMap;
- /** inferences */
- NodeList d_infer;
- NodeList d_infer_exp;
Node d_true;
Node d_zero;
/** mkAnd */
@@ -70,6 +68,7 @@ class TheoryDatatypes : public Theory {
TNode t2,
bool value) override
{
+ AlwaysAssert(tag == THEORY_DATATYPES);
Debug("dt") << "NotifyClass::eqNotifyTriggerTermMerge(" << tag << ", " << t1 << ", " << t2 << ")" << std::endl;
if (value) {
return d_dt.propagateLit(t1.eqNode(t2));
@@ -169,20 +168,6 @@ private:
/** selector apps for eqch equivalence class */
NodeUIntMap d_selector_apps;
std::map< Node, std::vector< Node > > d_selector_apps_data;
- /** Are we in conflict */
- context::CDO<bool> d_conflict;
- /** added lemma
- *
- * This flag is set to true during a full effort check if this theory
- * called d_out->lemma(...).
- */
- bool d_addedLemma;
- /** added fact
- *
- * This flag is set to true during a full effort check if this theory
- * added an internal fact to its equality engine.
- */
- bool d_addedFact;
/** The conflict node */
Node d_conflictNode;
/**
@@ -195,10 +180,6 @@ private:
* collectTerms(...) on.
*/
BoolMap d_collectTermsCacheU;
- /** pending assertions/merges */
- std::vector< Node > d_pending_lem;
- std::vector< Node > d_pending;
- std::map< Node, Node > d_pending_exp;
/** All the function terms that the theory has seen */
context::CDList<TNode> d_functionTerms;
/** counter for forcing assignments (ensures fairness) */
@@ -218,12 +199,6 @@ private:
/** assert fact */
void assertFact( Node fact, Node exp );
- /** flush pending facts */
- void flushPendingFacts();
-
- /** do send lemma */
- bool doSendLemma( Node lem );
- bool doSendLemmas( std::vector< Node >& lem );
/** get or make eqc info */
EqcInfo* getOrMakeEqcInfo( TNode n, bool doMake = false );
@@ -263,9 +238,10 @@ private:
/** finish initialization */
void finishInit() override;
//--------------------------------- end initialization
-
/** propagate */
bool propagateLit(TNode literal);
+ /** Conflict when merging two constants */
+ void conflict(TNode a, TNode b);
/** explain */
void addAssumptions( std::vector<TNode>& assumptions, std::vector<TNode>& tassumptions );
void explainEquality( TNode a, TNode b, bool polarity, std::vector<TNode>& assumptions );
@@ -274,22 +250,25 @@ private:
TrustNode explain(TNode literal) override;
Node explainLit(TNode literal);
Node explain( std::vector< Node >& lits );
- /** Conflict when merging two constants */
- void conflict(TNode a, TNode b);
/** called when a new equivalance class is created */
void eqNotifyNewClass(TNode t);
/** called when two equivalance classes have merged */
void eqNotifyMerge(TNode t1, TNode t2);
- void check(Effort e) override;
+ //--------------------------------- standard check
+ /** Do we need a check call at last call effort? */
bool needsCheckLastEffort() override;
+ /** Pre-check, called before the fact queue of the theory is processed. */
+ bool preCheck(Effort level) override;
+ /** Post-check, called after the fact queue of the theory is processed. */
+ void postCheck(Effort level) override;
+ /** Notify fact */
+ void notifyFact(TNode atom, bool pol, TNode fact, bool isInternal) override;
+ //--------------------------------- end standard check
void preRegisterTerm(TNode n) override;
TrustNode expandDefinition(Node n) override;
TrustNode ppRewrite(TNode n) override;
- void notifySharedTerm(TNode t) override;
EqualityStatus getEqualityStatus(TNode a, TNode b) override;
- bool collectModelInfo(TheoryModel* m) override;
- void shutdown() override {}
std::string identify() const override
{
return std::string("TheoryDatatypes");
@@ -336,8 +315,6 @@ private:
Node getInstantiateCons(Node n, const DType& dt, int index);
/** check instantiate */
void instantiate( EqcInfo* eqc, Node n );
- /** must communicate fact */
- bool mustCommunicateFact( Node n, Node exp );
private:
//equality queries
bool hasTerm( TNode a );
@@ -346,12 +323,14 @@ private:
bool areCareDisequal( TNode x, TNode y );
TNode getRepresentative( TNode a );
+ /** Collect model values in m based on the relevant terms given by termSet */
+ bool collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet) override;
/**
- * Compute relevant terms. In addition to all terms in assertions and shared
- * terms, this includes datatypes in non-singleton equivalence classes.
+ * Compute relevant terms. This includes datatypes in non-singleton
+ * equivalence classes.
*/
- void computeRelevantTerms(std::set<Node>& termSet,
- bool includeShared = true) override;
+ void computeRelevantTerms(std::set<Node>& termSet) override;
/** sygus symmetry breaking utility */
std::unique_ptr<SygusExtension> d_sygusExtension;
@@ -360,6 +339,8 @@ private:
DatatypesRewriter d_rewriter;
/** A (default) theory state object */
TheoryState d_state;
+ /** The inference manager */
+ InferenceManager d_im;
};/* class TheoryDatatypes */
}/* CVC4::theory::datatypes namespace */
diff --git a/src/theory/engine_output_channel.cpp b/src/theory/engine_output_channel.cpp
index a271d6d9c..b6d9a19db 100644
--- a/src/theory/engine_output_channel.cpp
+++ b/src/theory/engine_output_channel.cpp
@@ -14,10 +14,6 @@
#include "theory/engine_output_channel.h"
-#include "proof/cnf_proof.h"
-#include "proof/lemma_proof.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
#include "prop/prop_engine.h"
#include "smt/smt_statistics_registry.h"
#include "theory/theory_engine.h"
@@ -71,9 +67,7 @@ void EngineOutputChannel::safePoint(ResourceManager::Resource r)
}
}
-theory::LemmaStatus EngineOutputChannel::lemma(TNode lemma,
- ProofRule rule,
- LemmaProperty p)
+theory::LemmaStatus EngineOutputChannel::lemma(TNode lemma, LemmaProperty p)
{
Debug("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma("
<< lemma << ")"
@@ -81,151 +75,15 @@ theory::LemmaStatus EngineOutputChannel::lemma(TNode lemma,
++d_statistics.lemmas;
d_engine->d_outputChannelUsed = true;
- PROOF({
- bool preprocess = isLemmaPropertyPreprocess(p);
- registerLemmaRecipe(lemma, lemma, preprocess, d_theory);
- });
-
TrustNode tlem = TrustNode::mkTrustLemma(lemma);
theory::LemmaStatus result = d_engine->lemma(
tlem.getNode(),
- rule,
false,
p,
isLemmaPropertySendAtoms(p) ? d_theory : theory::THEORY_LAST);
return result;
}
-void EngineOutputChannel::registerLemmaRecipe(Node lemma,
- Node originalLemma,
- bool preprocess,
- theory::TheoryId theoryId)
-{
- // During CNF conversion, conjunctions will be broken down into
- // multiple lemmas. In order for the recipes to match, we have to do
- // the same here.
- NodeManager* nm = NodeManager::currentNM();
-
- if (preprocess) lemma = d_engine->preprocess(lemma);
-
- bool negated = (lemma.getKind() == NOT);
- Node nnLemma = negated ? lemma[0] : lemma;
-
- switch (nnLemma.getKind())
- {
- case AND:
- if (!negated)
- {
- for (unsigned i = 0; i < nnLemma.getNumChildren(); ++i)
- registerLemmaRecipe(nnLemma[i], originalLemma, false, theoryId);
- }
- else
- {
- NodeBuilder<> builder(OR);
- for (unsigned i = 0; i < nnLemma.getNumChildren(); ++i)
- builder << nnLemma[i].negate();
-
- Node disjunction =
- (builder.getNumChildren() == 1) ? builder[0] : builder;
- registerLemmaRecipe(disjunction, originalLemma, false, theoryId);
- }
- break;
-
- case EQUAL:
- if (nnLemma[0].getType().isBoolean())
- {
- if (!negated)
- {
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[1].negate()),
- originalLemma,
- false,
- theoryId);
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1]),
- originalLemma,
- false,
- theoryId);
- }
- else
- {
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[1]),
- originalLemma,
- false,
- theoryId);
- registerLemmaRecipe(
- nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1].negate()),
- originalLemma,
- false,
- theoryId);
- }
- }
- break;
-
- case ITE:
- if (!negated)
- {
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1]),
- originalLemma,
- false,
- theoryId);
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[2]),
- originalLemma,
- false,
- theoryId);
- }
- else
- {
- registerLemmaRecipe(
- nm->mkNode(OR, nnLemma[0].negate(), nnLemma[1].negate()),
- originalLemma,
- false,
- theoryId);
- registerLemmaRecipe(nm->mkNode(OR, nnLemma[0], nnLemma[2].negate()),
- originalLemma,
- false,
- theoryId);
- }
- break;
-
- default: break;
- }
-
- // Theory lemmas have one step that proves the empty clause
- LemmaProofRecipe proofRecipe;
- Node emptyNode;
- LemmaProofRecipe::ProofStep proofStep(theoryId, emptyNode);
-
- // Remember the original lemma, so we can report this later when asked to
- proofRecipe.setOriginalLemma(originalLemma);
-
- // Record the assertions and rewrites
- Node rewritten;
- if (lemma.getKind() == OR)
- {
- for (unsigned i = 0; i < lemma.getNumChildren(); ++i)
- {
- rewritten = theory::Rewriter::rewrite(lemma[i]);
- if (rewritten != lemma[i])
- {
- proofRecipe.addRewriteRule(lemma[i].negate(), rewritten.negate());
- }
- proofStep.addAssertion(lemma[i]);
- proofRecipe.addBaseAssertion(rewritten);
- }
- }
- else
- {
- rewritten = theory::Rewriter::rewrite(lemma);
- if (rewritten != lemma)
- {
- proofRecipe.addRewriteRule(lemma.negate(), rewritten.negate());
- }
- proofStep.addAssertion(lemma);
- proofRecipe.addBaseAssertion(rewritten);
- }
- proofRecipe.addStep(proofStep);
- ProofManager::getCnfProof()->setProofRecipe(&proofRecipe);
-}
-
theory::LemmaStatus EngineOutputChannel::splitLemma(TNode lemma, bool removable)
{
Debug("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma("
@@ -238,7 +96,7 @@ theory::LemmaStatus EngineOutputChannel::splitLemma(TNode lemma, bool removable)
TrustNode tlem = TrustNode::mkTrustLemma(lemma);
LemmaProperty p = removable ? LemmaProperty::REMOVABLE : LemmaProperty::NONE;
theory::LemmaStatus result =
- d_engine->lemma(tlem.getNode(), RULE_SPLIT, false, p, d_theory);
+ d_engine->lemma(tlem.getNode(), false, p, d_theory);
return result;
}
@@ -251,13 +109,11 @@ bool EngineOutputChannel::propagate(TNode literal)
return d_engine->propagate(literal, d_theory);
}
-void EngineOutputChannel::conflict(TNode conflictNode,
- std::unique_ptr<Proof> proof)
+void EngineOutputChannel::conflict(TNode conflictNode)
{
Trace("theory::conflict")
<< "EngineOutputChannel<" << d_theory << ">::conflict(" << conflictNode
<< ")" << std::endl;
- Assert(!proof); // Theory shouldn't be producing proofs yet
++d_statistics.conflicts;
d_engine->d_outputChannelUsed = true;
TrustNode tConf = TrustNode::mkTrustConflict(conflictNode);
@@ -274,7 +130,7 @@ void EngineOutputChannel::demandRestart()
Trace("theory::restart") << "EngineOutputChannel<" << d_theory
<< ">::restart(" << restartVar << ")" << std::endl;
++d_statistics.restartDemands;
- lemma(restartVar, RULE_INVALID, LemmaProperty::REMOVABLE);
+ lemma(restartVar, LemmaProperty::REMOVABLE);
}
void EngineOutputChannel::requirePhase(TNode n, bool phase)
@@ -329,7 +185,6 @@ LemmaStatus EngineOutputChannel::trustedLemma(TrustNode plem, LemmaProperty p)
// now, call the normal interface for lemma
return d_engine->lemma(
plem.getNode(),
- RULE_INVALID,
false,
p,
isLemmaPropertySendAtoms(p) ? d_theory : theory::THEORY_LAST);
diff --git a/src/theory/engine_output_channel.h b/src/theory/engine_output_channel.h
index 3e959898f..99f812ed4 100644
--- a/src/theory/engine_output_channel.h
+++ b/src/theory/engine_output_channel.h
@@ -45,12 +45,10 @@ class EngineOutputChannel : public theory::OutputChannel
void safePoint(ResourceManager::Resource r) override;
- void conflict(TNode conflictNode,
- std::unique_ptr<Proof> pf = nullptr) override;
+ void conflict(TNode conflictNode) override;
bool propagate(TNode literal) override;
theory::LemmaStatus lemma(TNode lemma,
- ProofRule rule,
LemmaProperty p = LemmaProperty::NONE) override;
theory::LemmaStatus splitLemma(TNode lemma, bool removable = false) override;
diff --git a/src/theory/ext_theory.h b/src/theory/ext_theory.h
index 420932bfe..2721bc89e 100644
--- a/src/theory/ext_theory.h
+++ b/src/theory/ext_theory.h
@@ -36,6 +36,7 @@
#include <map>
#include <set>
+#include "context/cdhashmap.h"
#include "context/cdhashset.h"
#include "context/context.h"
#include "expr/node.h"
diff --git a/src/theory/fp/theory_fp.cpp b/src/theory/fp/theory_fp.cpp
index 4c59b1c06..5eb9e576d 100644
--- a/src/theory/fp/theory_fp.cpp
+++ b/src/theory/fp/theory_fp.cpp
@@ -1023,7 +1023,8 @@ bool TheoryFp::collectModelInfo(TheoryModel* m)
{
std::set<Node> relevantTerms;
// Work out which variables are needed
- computeRelevantTerms(relevantTerms);
+ const std::set<Kind>& irrKinds = m->getIrrelevantKinds();
+ computeAssertedTerms(relevantTerms, irrKinds);
// this override behavior to not assert equality engine
return collectModelValues(m, relevantTerms);
}
diff --git a/src/theory/inference_manager_buffered.cpp b/src/theory/inference_manager_buffered.cpp
index adbcc3033..8a7713121 100644
--- a/src/theory/inference_manager_buffered.cpp
+++ b/src/theory/inference_manager_buffered.cpp
@@ -49,24 +49,34 @@ void InferenceManagerBuffered::addPendingLemma(Node lem,
LemmaProperty p,
ProofGenerator* pg)
{
- d_pendingLem.push_back(std::make_shared<Lemma>(lem, p, pg));
+ // make the simple theory lemma
+ d_pendingLem.emplace_back(new SimpleTheoryLemma(lem, p, pg));
}
-void InferenceManagerBuffered::addPendingLemma(std::shared_ptr<Lemma> lemma)
+void InferenceManagerBuffered::addPendingLemma(
+ std::unique_ptr<TheoryInference> lemma)
{
d_pendingLem.emplace_back(std::move(lemma));
}
-void InferenceManagerBuffered::addPendingFact(Node fact, Node exp)
+void InferenceManagerBuffered::addPendingFact(Node conc,
+ Node exp,
+ ProofGenerator* pg)
{
- Assert(fact.getKind() != AND && fact.getKind() != OR);
- d_pendingFact.push_back(std::pair<Node, Node>(fact, exp));
+ // make a simple theory internal fact
+ Assert(conc.getKind() != AND && conc.getKind() != OR);
+ d_pendingFact.emplace_back(new SimpleTheoryInternalFact(conc, exp, pg));
+}
+
+void InferenceManagerBuffered::addPendingFact(
+ std::unique_ptr<TheoryInference> fact)
+{
+ d_pendingFact.emplace_back(std::move(fact));
}
void InferenceManagerBuffered::addPendingPhaseRequirement(Node lit, bool pol)
{
- // must ensure rewritten
- lit = Rewriter::rewrite(lit);
+ // it is the responsibility of the caller to ensure lit is rewritten
d_pendingReqPhase[lit] = pol;
}
@@ -75,14 +85,9 @@ void InferenceManagerBuffered::doPendingFacts()
size_t i = 0;
while (!d_theoryState.isInConflict() && i < d_pendingFact.size())
{
- std::pair<Node, Node>& pfact = d_pendingFact[i];
- Node fact = pfact.first;
- Node exp = pfact.second;
- bool polarity = fact.getKind() != NOT;
- TNode atom = polarity ? fact : fact[0];
- // no double negation or conjunctive conclusions
- Assert(atom.getKind() != NOT && atom.getKind() != AND);
- assertInternalFact(atom, polarity, exp);
+ // process this fact, which notice may enqueue more pending facts in this
+ // loop.
+ d_pendingFact[i]->process(this);
i++;
}
d_pendingFact.clear();
@@ -90,20 +95,10 @@ void InferenceManagerBuffered::doPendingFacts()
void InferenceManagerBuffered::doPendingLemmas()
{
- // process all the pending lemmas
- for (const std::shared_ptr<Lemma>& plem : d_pendingLem)
+ for (const std::unique_ptr<TheoryInference>& plem : d_pendingLem)
{
- if (!plem->notifySend())
- {
- // the lemma indicated that it should not be sent after all
- continue;
- }
- Node lem = plem->d_node;
- LemmaProperty p = plem->d_property;
- ProofGenerator* pg = plem->d_pg;
- Assert(!lem.isNull());
- // send (trusted) lemma on the output channel with property p
- trustedLemma(TrustNode::mkTrustLemma(lem, pg), p);
+ // process this lemma
+ plem->process(this);
}
d_pendingLem.clear();
}
@@ -113,10 +108,24 @@ void InferenceManagerBuffered::doPendingPhaseRequirements()
// process the pending require phase calls
for (const std::pair<const Node, bool>& prp : d_pendingReqPhase)
{
- d_out.requirePhase(prp.first, prp.second);
+ requirePhase(prp.first, prp.second);
}
d_pendingReqPhase.clear();
}
+void InferenceManagerBuffered::clearPendingFacts() { d_pendingFact.clear(); }
+void InferenceManagerBuffered::clearPendingLemmas() { d_pendingLem.clear(); }
+void InferenceManagerBuffered::clearPendingPhaseRequirements()
+{
+ d_pendingReqPhase.clear();
+}
+
+
+ std::size_t InferenceManagerBuffered::numPendingLemmas() const {
+ return d_pendingLem.size();
+ }
+ std::size_t InferenceManagerBuffered::numPendingFacts() const {
+ return d_pendingFact.size();
+ }
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/inference_manager_buffered.h b/src/theory/inference_manager_buffered.h
index bb46ef566..62c3c9b55 100644
--- a/src/theory/inference_manager_buffered.h
+++ b/src/theory/inference_manager_buffered.h
@@ -19,45 +19,13 @@
#include "context/cdhashmap.h"
#include "expr/node.h"
+#include "theory/theory_inference.h"
#include "theory/theory_inference_manager.h"
namespace CVC4 {
namespace theory {
/**
- * A lemma base class. This class is an abstract data structure for storing
- * pending lemmas in the inference manager below.
- */
-class Lemma
-{
- public:
- Lemma(Node n, LemmaProperty p, ProofGenerator* pg)
- : d_node(n), d_property(p), d_pg(pg)
- {
- }
- virtual ~Lemma() {}
- /**
- * Called just before this lemma is sent on the output channel. The purpose
- * of this callback is to do any specific process of the lemma, e.g. take
- * debug statistics, cache, etc.
- *
- * @return true if the lemma should be sent on the output channel.
- */
- virtual bool notifySend() { return true; }
- /** The lemma to send */
- Node d_node;
- /** The lemma property (see OutputChannel::lemma) */
- LemmaProperty d_property;
- /**
- * The proof generator for this lemma, which if non-null, is wrapped in a
- * TrustNode to be set on the output channel via trustedLemma at the time
- * the lemma is sent. This proof generator must be able to provide a proof
- * for d_node in the remainder of the user context.
- */
- ProofGenerator* d_pg;
-};
-
-/**
* The buffered inference manager. This class implements standard methods
* for buffering facts, lemmas and phase requirements.
*/
@@ -67,7 +35,7 @@ class InferenceManagerBuffered : public TheoryInferenceManager
InferenceManagerBuffered(Theory& t,
TheoryState& state,
ProofNodeManager* pnm);
- ~InferenceManagerBuffered() {}
+ virtual ~InferenceManagerBuffered() {}
/**
* Have we processed an inference during this call to check? In particular,
* this returns true if we have a pending fact or lemma, or have encountered
@@ -92,21 +60,25 @@ class InferenceManagerBuffered : public TheoryInferenceManager
ProofGenerator* pg = nullptr);
/**
* Add pending lemma, where lemma can be a (derived) class of the
- * above one. Pending lemmas are sent to the output channel using
- * doPendingLemmas.
+ * theory inference base class.
*/
- void addPendingLemma(std::shared_ptr<Lemma> lemma);
+ void addPendingLemma(std::unique_ptr<TheoryInference> lemma);
/**
* Add pending fact, which adds a fact on the pending fact queue. It must
* be the case that:
- * (1) exp => fact is valid,
+ * (1) exp => conc is valid,
* (2) exp is a literal (or conjunction of literals) that holds in the
* equality engine of the theory.
*
* Pending facts are sent to the equality engine of this class using
* doPendingFacts.
*/
- void addPendingFact(Node fact, Node exp);
+ void addPendingFact(Node conc, Node exp, ProofGenerator* pg = nullptr);
+ /**
+ * Add pending fact, where fact can be a (derived) class of the
+ * theory inference base class.
+ */
+ void addPendingFact(std::unique_ptr<TheoryInference> fact);
/** Add pending phase requirement
*
* This method is called to indicate this class should send a phase
@@ -145,12 +117,23 @@ class InferenceManagerBuffered : public TheoryInferenceManager
* phase requirements and clears d_pendingReqPhase.
*/
void doPendingPhaseRequirements();
+ /** Clear pending facts, without processing */
+ void clearPendingFacts();
+ /** Clear pending lemmas, without processing */
+ void clearPendingLemmas();
+ /** Clear pending phase requirements, without processing */
+ void clearPendingPhaseRequirements();
+
+ /** Returns the number of pending lemmas. */
+ std::size_t numPendingLemmas() const;
+ /** Returns the number of pending facts. */
+ std::size_t numPendingFacts() const;
protected:
- /** A set of pending lemmas */
- std::vector<std::shared_ptr<Lemma>> d_pendingLem;
- /** A set of pending facts, paired with their explanations */
- std::vector<std::pair<Node, Node>> d_pendingFact;
+ /** A set of pending inferences to be processed as lemmas */
+ std::vector<std::unique_ptr<TheoryInference>> d_pendingLem;
+ /** A set of pending inferences to be processed as facts */
+ std::vector<std::unique_ptr<TheoryInference>> d_pendingFact;
/** A map from literals to their pending phase requirement */
std::map<Node, bool> d_pendingReqPhase;
};
diff --git a/src/theory/logic_info.cpp b/src/theory/logic_info.cpp
index 9805f602e..878815811 100644
--- a/src/theory/logic_info.cpp
+++ b/src/theory/logic_info.cpp
@@ -23,6 +23,7 @@
#include <string>
#include "base/check.h"
+#include "base/configuration.h"
#include "expr/kind.h"
using namespace std;
@@ -43,7 +44,12 @@ LogicInfo::LogicInfo()
d_higherOrder(true),
d_locked(false)
{
- for(TheoryId id = THEORY_FIRST; id < THEORY_LAST; ++id) {
+ for (TheoryId id = THEORY_FIRST; id < THEORY_LAST; ++id)
+ {
+ if (id == THEORY_FP && !Configuration::isBuiltWithSymFPU())
+ {
+ continue;
+ }
enableTheory(id);
}
}
diff --git a/src/theory/mkrewriter b/src/theory/mkrewriter
index 3c27f1b53..871927760 100755
--- a/src/theory/mkrewriter
+++ b/src/theory/mkrewriter
@@ -243,10 +243,6 @@ check_builtin_theory_seen
## output
-# generate warnings about incorrect #line annotations in templates
-nl -ba -s' ' "$template" | grep '^ *[0-9][0-9]* # *line' |
- awk '{OFS="";if($1+1!=$3) print "'"$template"':",$1,": warning: incorrect annotation \"#line ",$3,"\" (it should be \"#line ",($1+1),"\")"}' >&2
-
text=$(cat "$template")
for var in \
rewriter_includes \
diff --git a/src/theory/mktheorytraits b/src/theory/mktheorytraits
index a87203015..1b1350abe 100755
--- a/src/theory/mktheorytraits
+++ b/src/theory/mktheorytraits
@@ -214,20 +214,15 @@ function enumerator {
lineno=${BASH_LINENO[0]}
check_theory_seen
type_enumerator_includes="${type_enumerator_includes}
-#line $lineno \"$kf\"
#include \"$3\""
if expr "$type_constants" : '.* '"$1"' ' &>/dev/null; then
mk_type_enumerator_type_constant_cases="${mk_type_enumerator_type_constant_cases}
-#line $lineno \"$kf\"
case $1:
-#line $lineno \"$kf\"
return new $2(type, tep);
"
elif expr "$type_kinds" : '.* '"$1"' ' &>/dev/null; then
mk_type_enumerator_cases="${mk_type_enumerator_cases}
-#line $lineno \"$kf\"
case kind::$1:
-#line $lineno \"$kf\"
return new $2(type, tep);
"
else
@@ -395,10 +390,6 @@ check_builtin_theory_seen
eval "theory_constructors=\"$theory_constructors\""
-# generate warnings about incorrect #line annotations in templates
-nl -ba -s' ' "$template" | grep '^ *[0-9][0-9]* # *line' |
- awk '{OFS="";if($1+1!=$3) print "'"$template"':",$1,": warning: incorrect annotation \"#line ",$3,"\" (it should be \"#line ",($1+1),"\")"}' >&2
-
text=$(cat "$template")
for var in \
theory_traits \
diff --git a/src/theory/output_channel.cpp b/src/theory/output_channel.cpp
index c918438ee..ad60dbe0e 100644
--- a/src/theory/output_channel.cpp
+++ b/src/theory/output_channel.cpp
@@ -93,11 +93,6 @@ TNode LemmaStatus::getRewrittenLemma() const { return d_rewrittenLemma; }
unsigned LemmaStatus::getLevel() const { return d_level; }
-LemmaStatus OutputChannel::lemma(TNode n, LemmaProperty p)
-{
- return lemma(n, RULE_INVALID, p);
-}
-
LemmaStatus OutputChannel::split(TNode n)
{
return splitLemma(n.orNode(n.notNode()));
diff --git a/src/theory/output_channel.h b/src/theory/output_channel.h
index 0fd610c58..23d7d8784 100644
--- a/src/theory/output_channel.h
+++ b/src/theory/output_channel.h
@@ -22,11 +22,9 @@
#include <memory>
#include "expr/proof_node.h"
-#include "proof/proof_manager.h"
#include "smt/logic_exception.h"
#include "theory/interrupted.h"
#include "theory/trust_node.h"
-#include "util/proof.h"
#include "util/resource_manager.h"
namespace CVC4 {
@@ -135,10 +133,8 @@ class OutputChannel {
* assigned false), or else a literal by itself (in the case of a
* unit conflict) which is assigned TRUE (and T-conflicting) in the
* current assignment.
- * @param pf - a proof of the conflict. This is only non-null if proofs
- * are enabled.
*/
- virtual void conflict(TNode n, std::unique_ptr<Proof> pf = nullptr) = 0;
+ virtual void conflict(TNode n) = 0;
/**
* Propagate a theory literal.
@@ -153,19 +149,11 @@ class OutputChannel {
* been detected. (This requests a split.)
*
* @param n - a theory lemma valid at decision level 0
- * @param rule - the proof rule for this lemma
* @param p The properties of the lemma
* @return the "status" of the lemma, including user level at which
* the lemma resides; the lemma will be removed when this user level pops
*/
- virtual LemmaStatus lemma(TNode n,
- ProofRule rule,
- LemmaProperty p = LemmaProperty::NONE) = 0;
-
- /**
- * Variant of the lemma function that does not require providing a proof rule.
- */
- virtual LemmaStatus lemma(TNode n, LemmaProperty p = LemmaProperty::NONE);
+ virtual LemmaStatus lemma(TNode n, LemmaProperty p = LemmaProperty::NONE) = 0;
/**
* Request a split on a new theory atom. This is equivalent to
diff --git a/src/theory/quantifiers/fun_def_process.cpp b/src/theory/quantifiers/fun_def_process.cpp
index 2c5eab94c..eb87db4de 100644
--- a/src/theory/quantifiers/fun_def_process.cpp
+++ b/src/theory/quantifiers/fun_def_process.cpp
@@ -14,13 +14,15 @@
** This class implements pre-process steps for admissible recursive function definitions (Reynolds et al IJCAR2016)
**/
+#include "theory/quantifiers/fun_def_process.h"
+
#include <vector>
-#include "theory/quantifiers/fun_def_process.h"
+#include "options/smt_options.h"
+#include "proof/proof_manager.h"
#include "theory/quantifiers/quantifiers_attributes.h"
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/term_util.h"
-#include "proof/proof_manager.h"
using namespace CVC4;
using namespace std;
@@ -86,7 +88,10 @@ void FunDefFmf::simplify( std::vector< Node >& assertions ) {
Trace("fmf-fun-def") << " to " << std::endl;
Node new_q = NodeManager::currentNM()->mkNode( FORALL, bvl, bd );
new_q = Rewriter::rewrite( new_q );
- PROOF( ProofManager::currentPM()->addDependence(new_q, assertions[i]); );
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(new_q, assertions[i]);
+ }
assertions[i] = new_q;
Trace("fmf-fun-def") << " " << assertions[i] << std::endl;
fd_assertions.push_back( i );
@@ -120,7 +125,10 @@ void FunDefFmf::simplify( std::vector< Node >& assertions ) {
<< std::endl;
Trace("fmf-fun-def-rewrite") << " to " << std::endl;
Trace("fmf-fun-def-rewrite") << " " << n << std::endl;
- PROOF(ProofManager::currentPM()->addDependence(n, assertions[i]););
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(n, assertions[i]);
+ }
assertions[i] = n;
}
}
@@ -175,8 +183,12 @@ Node FunDefFmf::simplifyFormula( Node n, bool pol, bool hasPol, std::vector< Nod
c = simplifyFormula( n[i], newPol, newHasPol, cconstraints, hd, false, visited, visited_cons );
if( branch_pos ){
// if at a branching position, the other constraints don't matter if this is satisfied
- Node bcons = cconstraints.empty() ? NodeManager::currentNM()->mkConst( true ) :
- ( cconstraints.size()==1 ? cconstraints[0] : NodeManager::currentNM()->mkNode( AND, cconstraints ) );
+ Node bcons = cconstraints.empty()
+ ? NodeManager::currentNM()->mkConst(true)
+ : (cconstraints.size() == 1
+ ? cconstraints[0]
+ : NodeManager::currentNM()->mkNode(
+ AND, cconstraints));
branch_constraints.push_back( bcons );
Trace("fmf-fun-def-debug2") << "Branching constraint at arg " << i << " is " << bcons << std::endl;
}
@@ -201,10 +213,14 @@ Node FunDefFmf::simplifyFormula( Node n, bool pol, bool hasPol, std::vector< Nod
// in the default case, we care about all conditions
branch_cond = constraints.size()==1 ? constraints[0] : NodeManager::currentNM()->mkNode( AND, constraints );
for( unsigned i=0; i<n.getNumChildren(); i++ ){
- // if this child holds with forcing polarity (true child of OR or false child of AND),
- // then we only care about its associated recursive conditions
- branch_cond = NodeManager::currentNM()->mkNode( kind::ITE,
- ( n.getKind()==OR ? n[i] : n[i].negate() ), branch_constraints[i], branch_cond );
+ // if this child holds with forcing polarity (true child of OR or
+ // false child of AND), then we only care about its associated
+ // recursive conditions
+ branch_cond = NodeManager::currentNM()->mkNode(
+ kind::ITE,
+ (n.getKind() == OR ? n[i] : n[i].negate()),
+ branch_constraints[i],
+ branch_cond);
}
}
Trace("fmf-fun-def-debug2") << "Made branching condition " << branch_cond << std::endl;
diff --git a/src/theory/quantifiers/instantiate.cpp b/src/theory/quantifiers/instantiate.cpp
index 77b61e9dd..04b6e0dda 100644
--- a/src/theory/quantifiers/instantiate.cpp
+++ b/src/theory/quantifiers/instantiate.cpp
@@ -16,6 +16,8 @@
#include "expr/node_algorithm.h"
#include "options/quantifiers_options.h"
+#include "options/smt_options.h"
+#include "proof/proof_manager.h"
#include "smt/smt_statistics_registry.h"
#include "theory/quantifiers/cegqi/inst_strategy_cegqi.h"
#include "theory/quantifiers/first_order_model.h"
@@ -577,18 +579,21 @@ void Instantiate::getInstantiatedQuantifiedFormulas(std::vector<Node>& qs)
bool Instantiate::getUnsatCoreLemmas(std::vector<Node>& active_lemmas)
{
// only if unsat core available
- if (options::proof())
+ if (options::unsatCores())
{
if (!ProofManager::currentPM()->unsatCoreAvailable())
{
return false;
}
}
+ else
+ {
+ return false;
+ }
Trace("inst-unsat-core") << "Get instantiations in unsat core..."
<< std::endl;
- ProofManager::currentPM()->getLemmasInUnsatCore(theory::THEORY_QUANTIFIERS,
- active_lemmas);
+ ProofManager::currentPM()->getLemmasInUnsatCore(active_lemmas);
if (Trace.isOn("inst-unsat-core"))
{
Trace("inst-unsat-core") << "Quantifiers lemmas in unsat core: "
@@ -602,27 +607,6 @@ bool Instantiate::getUnsatCoreLemmas(std::vector<Node>& active_lemmas)
return true;
}
-bool Instantiate::getUnsatCoreLemmas(std::vector<Node>& active_lemmas,
- std::map<Node, Node>& weak_imp)
-{
- if (getUnsatCoreLemmas(active_lemmas))
- {
- for (unsigned i = 0, size = active_lemmas.size(); i < size; ++i)
- {
- Node n = ProofManager::currentPM()->getWeakestImplicantInUnsatCore(
- active_lemmas[i]);
- if (n != active_lemmas[i])
- {
- Trace("inst-unsat-core") << " weaken : " << active_lemmas[i] << " -> "
- << n << std::endl;
- }
- weak_imp[active_lemmas[i]] = n;
- }
- return true;
- }
- return false;
-}
-
void Instantiate::getInstantiationTermVectors(
Node q, std::vector<std::vector<Node> >& tvecs)
{
diff --git a/src/theory/quantifiers/instantiate.h b/src/theory/quantifiers/instantiate.h
index cb40bbbbc..8b1e0f7fc 100644
--- a/src/theory/quantifiers/instantiate.h
+++ b/src/theory/quantifiers/instantiate.h
@@ -268,21 +268,6 @@ class Instantiate : public QuantifiersUtil
* This method returns false if the unsat core is not available.
*/
bool getUnsatCoreLemmas(std::vector<Node>& active_lemmas);
- /** get unsat core lemmas
- *
- * If this method returns true, then it appends to active_lemmas all lemmas
- * that are in the unsat core that originated from the theory of quantifiers.
- * This method returns false if the unsat core is not available.
- *
- * It also computes a weak implicant for each of these lemmas. For each lemma
- * L in active_lemmas, this is a formula L' such that:
- * L => L'
- * and replacing L by L' in the unsat core results in a set that is still
- * unsatisfiable. The map weak_imp stores this formula for each formula in
- * active_lemmas.
- */
- bool getUnsatCoreLemmas(std::vector<Node>& active_lemmas,
- std::map<Node, Node>& weak_imp);
/** get explanation for instantiation lemmas
*
*
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index dd59628c1..2e69080e7 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -217,7 +217,7 @@ QuantifiersEngine::QuantifiersEngine(context::Context* c,
if (options::sygus() || options::sygusInst())
{
d_sygus_tdb.reset(new quantifiers::TermDbSygus(c, this));
- }
+ }
d_util.push_back(d_instantiate.get());
@@ -575,12 +575,12 @@ void QuantifiersEngine::check( Theory::Effort e ){
Trace("quant-engine-debug2") << "Quantifiers Engine call to check, level = " << e << ", needsCheck=" << needsCheck << std::endl;
if( needsCheck ){
- //flush previous lemmas (for instance, if was interupted), or other lemmas to process
+ //flush previous lemmas (for instance, if was interrupted), or other lemmas to process
flushLemmas();
if( d_hasAddedLemma ){
return;
}
-
+
double clSet = 0;
if( Trace.isOn("quant-engine") ){
clSet = double(clock())/double(CLOCKS_PER_SEC);
@@ -805,7 +805,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
Trace("quant-engine") << ", added lemma = " << d_hasAddedLemma;
Trace("quant-engine") << std::endl;
}
-
+
Trace("quant-engine-debug2") << "Finished quantifiers engine check." << std::endl;
}else{
Trace("quant-engine-debug2") << "Quantifiers Engine does not need check." << std::endl;
@@ -1035,7 +1035,7 @@ bool QuantifiersEngine::removeLemma( Node lem ) {
void QuantifiersEngine::addRequirePhase( Node lit, bool req ){
d_phase_req_waiting[lit] = req;
}
-
+
void QuantifiersEngine::markRelevant( Node q ) {
d_model->markRelevant( q );
}
@@ -1048,9 +1048,10 @@ bool QuantifiersEngine::theoryEngineNeedsCheck() const
return d_te->needCheck();
}
-void QuantifiersEngine::setConflict() {
- d_conflict = true;
- d_conflict_c = true;
+void QuantifiersEngine::setConflict()
+{
+ d_conflict = true;
+ d_conflict_c = true;
}
bool QuantifiersEngine::getInstWhenNeedsCheck( Theory::Effort e ) {
@@ -1123,10 +1124,6 @@ bool QuantifiersEngine::getUnsatCoreLemmas( std::vector< Node >& active_lemmas )
return d_instantiate->getUnsatCoreLemmas(active_lemmas);
}
-bool QuantifiersEngine::getUnsatCoreLemmas( std::vector< Node >& active_lemmas, std::map< Node, Node >& weak_imp ) {
- return d_instantiate->getUnsatCoreLemmas(active_lemmas, weak_imp);
-}
-
void QuantifiersEngine::getInstantiationTermVectors( Node q, std::vector< std::vector< Node > >& tvecs ) {
d_instantiate->getInstantiationTermVectors(q, tvecs);
}
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index eca108587..6afc4f925 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -265,8 +265,6 @@ public:
Node getInstantiatedConjunction(Node q);
/** get unsat core lemmas */
bool getUnsatCoreLemmas(std::vector<Node>& active_lemmas);
- bool getUnsatCoreLemmas(std::vector<Node>& active_lemmas,
- std::map<Node, Node>& weak_imp);
/** get explanation for instantiation lemmas */
void getExplanationForInstLemmas(const std::vector<Node>& lems,
std::map<Node, Node>& quant,
@@ -317,7 +315,7 @@ public:
~Statistics();
};/* class QuantifiersEngine::Statistics */
Statistics d_statistics;
-
+
private:
/** reference to theory engine object */
TheoryEngine* d_te;
diff --git a/src/theory/rewriter.cpp b/src/theory/rewriter.cpp
index f2e13d1e0..9238525dc 100644
--- a/src/theory/rewriter.cpp
+++ b/src/theory/rewriter.cpp
@@ -21,6 +21,7 @@
#include "smt/smt_engine.h"
#include "smt/smt_engine_scope.h"
#include "smt/smt_statistics_registry.h"
+#include "theory/builtin/proof_checker.h"
#include "theory/rewriter_tables.h"
#include "theory/theory.h"
#include "util/resource_manager.h"
@@ -115,13 +116,18 @@ TrustNode Rewriter::rewriteWithProof(TNode node,
return TrustNode::mkTrustRewrite(node, ret, d_tpg.get());
}
-void Rewriter::setProofChecker(ProofChecker* pc)
+void Rewriter::setProofNodeManager(ProofNodeManager* pnm)
{
// if not already initialized with proof support
if (d_tpg == nullptr)
{
- d_pnm.reset(new ProofNodeManager(pc));
- d_tpg.reset(new TConvProofGenerator(d_pnm.get()));
+ // the rewriter is staticly determinstic, thus use static cache policy
+ // for the term conversion proof generator
+ d_tpg.reset(new TConvProofGenerator(pnm,
+ nullptr,
+ TConvPolicy::FIXPOINT,
+ TConvCachePolicy::STATIC,
+ "Rewriter::TConvProofGenerator"));
}
}
@@ -391,7 +397,7 @@ RewriteResponse Rewriter::preRewrite(theory::TheoryId theoryId,
d_theoryRewriters[theoryId]->preRewriteWithProof(n);
// process the trust rewrite response: store the proof step into
// tcpg if necessary and then convert to rewrite response.
- return processTrustRewriteResponse(tresponse, true, tcpg);
+ return processTrustRewriteResponse(theoryId, tresponse, true, tcpg);
}
return d_theoryRewriters[theoryId]->preRewrite(n);
}
@@ -412,7 +418,7 @@ RewriteResponse Rewriter::postRewrite(theory::TheoryId theoryId,
// same as above, for post-rewrite
TrustRewriteResponse tresponse =
d_theoryRewriters[theoryId]->postRewriteWithProof(n);
- return processTrustRewriteResponse(tresponse, false, tcpg);
+ return processTrustRewriteResponse(theoryId, tresponse, false, tcpg);
}
return d_theoryRewriters[theoryId]->postRewrite(n);
}
@@ -420,6 +426,7 @@ RewriteResponse Rewriter::postRewrite(theory::TheoryId theoryId,
}
RewriteResponse Rewriter::processTrustRewriteResponse(
+ theory::TheoryId theoryId,
const TrustRewriteResponse& tresponse,
bool isPre,
TConvProofGenerator* tcpg)
@@ -433,13 +440,14 @@ RewriteResponse Rewriter::processTrustRewriteResponse(
ProofGenerator* pg = trn.getGenerator();
if (pg == nullptr)
{
+ Node tidn = builtin::BuiltinProofRuleChecker::mkTheoryIdNode(theoryId);
// add small step trusted rewrite
NodeManager* nm = NodeManager::currentNM();
tcpg->addRewriteStep(proven[0],
proven[1],
PfRule::THEORY_REWRITE,
{},
- {proven[0], nm->mkConst(isPre)});
+ {proven, tidn, nm->mkConst(isPre)});
}
else
{
diff --git a/src/theory/rewriter.h b/src/theory/rewriter.h
index c57844f23..113749a75 100644
--- a/src/theory/rewriter.h
+++ b/src/theory/rewriter.h
@@ -80,7 +80,7 @@ class Rewriter {
/**
* Rewrite with proof production, which is managed by the term conversion
* proof generator managed by this class (d_tpg). This method requires a call
- * to setProofChecker prior to this call.
+ * to setProofNodeManager prior to this call.
*
* @param node The node to rewrite.
* @param elimTheoryRewrite Whether we also want fine-grained proofs for
@@ -94,8 +94,8 @@ class Rewriter {
bool elimTheoryRewrite = false,
bool isExtEq = false);
- /** Set proof checker */
- void setProofChecker(ProofChecker* pc);
+ /** Set proof node manager */
+ void setProofNodeManager(ProofNodeManager* pnm);
/**
* Garbage collects the rewrite caches.
@@ -189,6 +189,7 @@ class Rewriter {
TConvProofGenerator* tcpg = nullptr);
/** processes a trust rewrite response */
RewriteResponse processTrustRewriteResponse(
+ theory::TheoryId theoryId,
const TrustRewriteResponse& tresponse,
bool isPre,
TConvProofGenerator* tcpg);
@@ -226,8 +227,6 @@ class Rewriter {
RewriteEnvironment d_re;
- /** The proof node manager */
- std::unique_ptr<ProofNodeManager> d_pnm;
/** The proof generator */
std::unique_ptr<TConvProofGenerator> d_tpg;
#ifdef CVC4_ASSERTIONS
diff --git a/src/theory/sets/theory_sets.cpp b/src/theory/sets/theory_sets.cpp
index 63ebacc23..cb42f09d5 100644
--- a/src/theory/sets/theory_sets.cpp
+++ b/src/theory/sets/theory_sets.cpp
@@ -67,12 +67,12 @@ void TheorySets::finishInit()
d_valuation.setUnevaluatedKind(WITNESS);
// functions we are doing congruence over
- d_equalityEngine->addFunctionKind(kind::SINGLETON);
- d_equalityEngine->addFunctionKind(kind::UNION);
- d_equalityEngine->addFunctionKind(kind::INTERSECTION);
- d_equalityEngine->addFunctionKind(kind::SETMINUS);
- d_equalityEngine->addFunctionKind(kind::MEMBER);
- d_equalityEngine->addFunctionKind(kind::SUBSET);
+ d_equalityEngine->addFunctionKind(SINGLETON);
+ d_equalityEngine->addFunctionKind(UNION);
+ d_equalityEngine->addFunctionKind(INTERSECTION);
+ d_equalityEngine->addFunctionKind(SETMINUS);
+ d_equalityEngine->addFunctionKind(MEMBER);
+ d_equalityEngine->addFunctionKind(SUBSET);
// relation operators
d_equalityEngine->addFunctionKind(PRODUCT);
d_equalityEngine->addFunctionKind(JOIN);
@@ -88,19 +88,26 @@ void TheorySets::finishInit()
d_internal->finishInit();
}
-void TheorySets::notifySharedTerm(TNode n) { d_internal->addSharedTerm(n); }
+void TheorySets::postCheck(Effort level) { d_internal->postCheck(level); }
-void TheorySets::check(Effort e) {
- if (done() && e < Theory::EFFORT_FULL) {
- return;
- }
- TimerStat::CodeTimer checkTimer(d_checkTime);
- d_internal->check(e);
+bool TheorySets::preNotifyFact(
+ TNode atom, bool polarity, TNode fact, bool isPrereg, bool isInternal)
+{
+ return d_internal->preNotifyFact(atom, polarity, fact);
+}
+
+void TheorySets::notifyFact(TNode atom,
+ bool polarity,
+ TNode fact,
+ bool isInternal)
+{
+ d_internal->notifyFact(atom, polarity, fact);
}
-bool TheorySets::collectModelInfo(TheoryModel* m)
+bool TheorySets::collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet)
{
- return d_internal->collectModelInfo(m);
+ return d_internal->collectModelValues(m, termSet);
}
void TheorySets::computeCareGraph() {
@@ -113,15 +120,12 @@ TrustNode TheorySets::explain(TNode node)
return TrustNode::mkTrustPropExp(node, exp, nullptr);
}
-EqualityStatus TheorySets::getEqualityStatus(TNode a, TNode b) {
- return d_internal->getEqualityStatus(a, b);
-}
-
Node TheorySets::getModelValue(TNode node) {
return Node::null();
}
-void TheorySets::preRegisterTerm(TNode node) {
+void TheorySets::preRegisterTerm(TNode node)
+{
d_internal->preRegisterTerm(node);
}
@@ -157,7 +161,7 @@ Theory::PPAssertStatus TheorySets::ppAssert(TNode in, SubstitutionMap& outSubsti
Theory::PPAssertStatus status = Theory::PP_ASSERT_STATUS_UNSOLVED;
// this is based off of Theory::ppAssert
- if (in.getKind() == kind::EQUAL)
+ if (in.getKind() == EQUAL)
{
if (in[0].isVar() && isLegalElimination(in[0], in[1]))
{
diff --git a/src/theory/sets/theory_sets.h b/src/theory/sets/theory_sets.h
index a7fb31dab..7787c0f9b 100644
--- a/src/theory/sets/theory_sets.h
+++ b/src/theory/sets/theory_sets.h
@@ -58,12 +58,23 @@ class TheorySets : public Theory
void finishInit() override;
//--------------------------------- end initialization
- void notifySharedTerm(TNode) override;
- void check(Effort) override;
- bool collectModelInfo(TheoryModel* m) override;
+ //--------------------------------- standard check
+ /** Post-check, called after the fact queue of the theory is processed. */
+ void postCheck(Effort level) override;
+ /** Pre-notify fact, return true if processed. */
+ bool preNotifyFact(TNode atom,
+ bool pol,
+ TNode fact,
+ bool isPrereg,
+ bool isInternal) override;
+ /** Notify fact */
+ void notifyFact(TNode atom, bool pol, TNode fact, bool isInternal) override;
+ //--------------------------------- end standard check
+ /** Collect model values in m based on the relevant terms given by termSet */
+ bool collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet) override;
void computeCareGraph() override;
TrustNode explain(TNode) override;
- EqualityStatus getEqualityStatus(TNode a, TNode b) override;
Node getModelValue(TNode) override;
std::string identify() const override { return "THEORY_SETS"; }
void preRegisterTerm(TNode node) override;
@@ -71,6 +82,7 @@ class TheorySets : public Theory
PPAssertStatus ppAssert(TNode in, SubstitutionMap& outSubstitutions) override;
void presolve() override;
bool isEntailed(Node n, bool pol);
+
private:
/** Functions to handle callbacks from equality engine */
class NotifyClass : public eq::EqualityEngineNotify
diff --git a/src/theory/sets/theory_sets_private.cpp b/src/theory/sets/theory_sets_private.cpp
index 3c9414606..c432c8039 100644
--- a/src/theory/sets/theory_sets_private.cpp
+++ b/src/theory/sets/theory_sets_private.cpp
@@ -276,74 +276,21 @@ bool TheorySetsPrivate::assertFact(Node fact, Node exp)
<< ", exp = " << exp << std::endl;
bool polarity = fact.getKind() != kind::NOT;
TNode atom = polarity ? fact : fact[0];
- if (!d_state.isEntailed(atom, polarity))
+ if (d_state.isEntailed(atom, polarity))
{
- if (atom.getKind() == kind::EQUAL)
- {
- d_equalityEngine->assertEquality(atom, polarity, exp);
- }
- else
- {
- d_equalityEngine->assertPredicate(atom, polarity, exp);
- }
- if (!d_state.isInConflict())
- {
- if (atom.getKind() == kind::MEMBER && polarity)
- {
- // check if set has a value, if so, we can propagate
- Node r = d_equalityEngine->getRepresentative(atom[1]);
- EqcInfo* e = getOrMakeEqcInfo(r, true);
- if (e)
- {
- Node s = e->d_singleton;
- if (!s.isNull())
- {
- Node pexp = NodeManager::currentNM()->mkNode(
- kind::AND, atom, atom[1].eqNode(s));
- d_keep.insert(pexp);
- if (s.getKind() == kind::SINGLETON)
- {
- if (s[0] != atom[0])
- {
- Trace("sets-prop")
- << "Propagate mem-eq : " << pexp << std::endl;
- Node eq = s[0].eqNode(atom[0]);
- d_keep.insert(eq);
- assertFact(eq, pexp);
- }
- }
- else
- {
- Trace("sets-prop")
- << "Propagate mem-eq conflict : " << pexp << std::endl;
- d_im.conflict(pexp);
- }
- }
- }
- // add to membership list
- NodeIntMap::iterator mem_i = d_members.find(r);
- int n_members = 0;
- if (mem_i != d_members.end())
- {
- n_members = (*mem_i).second;
- }
- d_members[r] = n_members + 1;
- if (n_members < (int)d_members_data[r].size())
- {
- d_members_data[r][n_members] = atom;
- }
- else
- {
- d_members_data[r].push_back(atom);
- }
- }
- }
- return true;
+ return false;
+ }
+ if (atom.getKind() == kind::EQUAL)
+ {
+ d_equalityEngine->assertEquality(atom, polarity, exp);
}
else
{
- return false;
+ d_equalityEngine->assertPredicate(atom, polarity, exp);
}
+ // call the notify new fact method
+ notifyFact(atom, polarity, exp);
+ return true;
}
void TheorySetsPrivate::fullEffortReset()
@@ -950,26 +897,10 @@ void TheorySetsPrivate::checkReduceComprehensions()
}
}
-/**************************** TheorySetsPrivate *****************************/
-/**************************** TheorySetsPrivate *****************************/
-/**************************** TheorySetsPrivate *****************************/
+//--------------------------------- standard check
-void TheorySetsPrivate::check(Theory::Effort level)
+void TheorySetsPrivate::postCheck(Theory::Effort level)
{
- Trace("sets-check") << "Sets check effort " << level << std::endl;
- if (level == Theory::EFFORT_LAST_CALL)
- {
- return;
- }
- while (!d_external.done() && !d_state.isInConflict())
- {
- // Get all the assertions
- Assertion assertion = d_external.get();
- TNode fact = assertion.d_assertion;
- Trace("sets-assert") << "Assert from input " << fact << std::endl;
- // assert the fact
- assertFact(fact, fact);
- }
Trace("sets-check") << "Sets finished assertions effort " << level
<< std::endl;
// invoke full effort check, relations check
@@ -989,18 +920,75 @@ void TheorySetsPrivate::check(Theory::Effort level)
}
}
Trace("sets-check") << "Sets finish Check effort " << level << std::endl;
-} /* TheorySetsPrivate::check() */
+}
-/************************ Sharing ************************/
-/************************ Sharing ************************/
-/************************ Sharing ************************/
+bool TheorySetsPrivate::preNotifyFact(TNode atom, bool polarity, TNode fact)
+{
+ // use entailment check (is this necessary?)
+ return d_state.isEntailed(atom, polarity);
+}
-void TheorySetsPrivate::addSharedTerm(TNode n)
+void TheorySetsPrivate::notifyFact(TNode atom, bool polarity, TNode fact)
{
- Debug("sets") << "[sets] TheorySetsPrivate::addSharedTerm( " << n << ")"
- << std::endl;
- d_equalityEngine->addTriggerTerm(n, THEORY_SETS);
+ if (d_state.isInConflict())
+ {
+ return;
+ }
+ if (atom.getKind() == kind::MEMBER && polarity)
+ {
+ // check if set has a value, if so, we can propagate
+ Node r = d_equalityEngine->getRepresentative(atom[1]);
+ EqcInfo* e = getOrMakeEqcInfo(r, true);
+ if (e)
+ {
+ Node s = e->d_singleton;
+ if (!s.isNull())
+ {
+ Node pexp = NodeManager::currentNM()->mkNode(
+ kind::AND, atom, atom[1].eqNode(s));
+ d_keep.insert(pexp);
+ if (s.getKind() == kind::SINGLETON)
+ {
+ if (s[0] != atom[0])
+ {
+ Trace("sets-prop") << "Propagate mem-eq : " << pexp << std::endl;
+ Node eq = s[0].eqNode(atom[0]);
+ d_keep.insert(eq);
+ // triggers an internal inference
+ assertFact(eq, pexp);
+ }
+ }
+ else
+ {
+ Trace("sets-prop")
+ << "Propagate mem-eq conflict : " << pexp << std::endl;
+ d_im.conflict(pexp);
+ }
+ }
+ }
+ // add to membership list
+ NodeIntMap::iterator mem_i = d_members.find(r);
+ int n_members = 0;
+ if (mem_i != d_members.end())
+ {
+ n_members = (*mem_i).second;
+ }
+ d_members[r] = n_members + 1;
+ if (n_members < (int)d_members_data[r].size())
+ {
+ d_members_data[r][n_members] = atom;
+ }
+ else
+ {
+ d_members_data[r].push_back(atom);
+ }
+ }
}
+//--------------------------------- end standard check
+
+/************************ Sharing ************************/
+/************************ Sharing ************************/
+/************************ Sharing ************************/
void TheorySetsPrivate::addCarePairs(TNodeTrie* t1,
TNodeTrie* t2,
@@ -1193,37 +1181,6 @@ bool TheorySetsPrivate::isCareArg(Node n, unsigned a)
}
}
-EqualityStatus TheorySetsPrivate::getEqualityStatus(TNode a, TNode b)
-{
- Assert(d_equalityEngine->hasTerm(a) && d_equalityEngine->hasTerm(b));
- if (d_equalityEngine->areEqual(a, b))
- {
- // The terms are implied to be equal
- return EQUALITY_TRUE;
- }
- if (d_equalityEngine->areDisequal(a, b, false))
- {
- // The terms are implied to be dis-equal
- return EQUALITY_FALSE;
- }
- return EQUALITY_UNKNOWN;
- /*
- Node aModelValue = d_external.d_valuation.getModelValue(a);
- if(aModelValue.isNull()) { return EQUALITY_UNKNOWN; }
- Node bModelValue = d_external.d_valuation.getModelValue(b);
- if(bModelValue.isNull()) { return EQUALITY_UNKNOWN; }
- if( aModelValue == bModelValue ) {
- // The term are true in current model
- return EQUALITY_TRUE_IN_MODEL;
- } else {
- return EQUALITY_FALSE_IN_MODEL;
- }
- */
- // }
- // //TODO: can we be more precise sometimes?
- // return EQUALITY_UNKNOWN;
-}
-
/******************** Model generation ********************/
/******************** Model generation ********************/
/******************** Model generation ********************/
@@ -1258,18 +1215,10 @@ std::string traceElements(const Node& set)
} // namespace
-bool TheorySetsPrivate::collectModelInfo(TheoryModel* m)
+bool TheorySetsPrivate::collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet)
{
- Trace("sets-model") << "Set collect model info" << std::endl;
- set<Node> termSet;
- // Compute terms appearing in assertions and shared terms
- d_external.computeRelevantTerms(termSet);
-
- // Assert equalities and disequalities to the model
- if (!m->assertEqualityEngine(d_equalityEngine, &termSet))
- {
- return false;
- }
+ Trace("sets-model") << "Set collect model values" << std::endl;
NodeManager* nm = NodeManager::currentNM();
std::map<Node, Node> mvals;
diff --git a/src/theory/sets/theory_sets_private.h b/src/theory/sets/theory_sets_private.h
index af780eadc..0df1eabc5 100644
--- a/src/theory/sets/theory_sets_private.h
+++ b/src/theory/sets/theory_sets_private.h
@@ -172,18 +172,23 @@ class TheorySetsPrivate {
*/
void finishInit();
+ //--------------------------------- standard check
+ /** Post-check, called after the fact queue of the theory is processed. */
+ void postCheck(Theory::Effort level);
+ /** Preprocess fact, return true if processed. */
+ bool preNotifyFact(TNode atom, bool polarity, TNode fact);
+ /** Notify new fact */
+ void notifyFact(TNode atom, bool polarity, TNode fact);
+ //--------------------------------- end standard check
+
+ /** Collect model values in m based on the relevant terms given by termSet */
void addSharedTerm(TNode);
-
- void check(Theory::Effort);
-
- bool collectModelInfo(TheoryModel* m);
+ bool collectModelValues(TheoryModel* m, const std::set<Node>& termSet);
void computeCareGraph();
Node explain(TNode);
- EqualityStatus getEqualityStatus(TNode a, TNode b);
-
void preRegisterTerm(TNode node);
/** expandDefinition
diff --git a/src/theory/sort_inference.cpp b/src/theory/sort_inference.cpp
index 144f5b54d..feb266a20 100644
--- a/src/theory/sort_inference.cpp
+++ b/src/theory/sort_inference.cpp
@@ -24,7 +24,6 @@
#include "options/quantifiers_options.h"
#include "options/smt_options.h"
#include "options/uf_options.h"
-#include "proof/proof_manager.h"
#include "theory/rewriter.h"
#include "theory/quantifiers/quant_util.h"
diff --git a/src/theory/strings/inference_manager.cpp b/src/theory/strings/inference_manager.cpp
index dce038fbf..811c040f3 100644
--- a/src/theory/strings/inference_manager.cpp
+++ b/src/theory/strings/inference_manager.cpp
@@ -28,19 +28,17 @@ namespace CVC4 {
namespace theory {
namespace strings {
-InferenceManager::InferenceManager(context::Context* c,
- context::UserContext* u,
+InferenceManager::InferenceManager(Theory& t,
SolverState& s,
TermRegistry& tr,
ExtTheory& e,
- OutputChannel& out,
- SequencesStatistics& statistics)
- : d_state(s),
+ SequencesStatistics& statistics,
+ ProofNodeManager* pnm)
+ : TheoryInferenceManager(t, s, pnm),
+ d_state(s),
d_termReg(tr),
d_extt(e),
- d_out(out),
- d_statistics(statistics),
- d_keep(c)
+ d_statistics(statistics)
{
NodeManager* nm = NodeManager::currentNM();
d_zero = nm->mkConst(Rational(0));
@@ -49,14 +47,6 @@ InferenceManager::InferenceManager(context::Context* c,
d_false = nm->mkConst(false);
}
-void InferenceManager::sendAssumption(TNode lit)
-{
- bool polarity = lit.getKind() != kind::NOT;
- TNode atom = polarity ? lit : lit[0];
- // assert pending fact
- assertPendingFact(atom, polarity, lit);
-}
-
bool InferenceManager::sendInternalInference(std::vector<Node>& exp,
Node conc,
Inference infer)
@@ -299,7 +289,7 @@ void InferenceManager::doPendingFacts()
TNode atom = polarity ? fact : fact[0];
// no double negation or double (conjunctive) conclusions
Assert(atom.getKind() != NOT && atom.getKind() != AND);
- assertPendingFact(atom, polarity, exp);
+ assertInternalFact(atom, polarity, exp);
}
}
else
@@ -308,13 +298,8 @@ void InferenceManager::doPendingFacts()
TNode atom = polarity ? facts : facts[0];
// no double negation or double (conjunctive) conclusions
Assert(atom.getKind() != NOT && atom.getKind() != AND);
- assertPendingFact(atom, polarity, exp);
+ assertInternalFact(atom, polarity, exp);
}
- // Must reference count the equality and its explanation, which is not done
- // by the equality engine. Notice that we do not need to do this for
- // external assertions, which enter as facts through sendAssumption.
- d_keep.insert(facts);
- d_keep.insert(exp);
i++;
}
d_pending.clear();
@@ -392,68 +377,6 @@ void InferenceManager::doPendingLemmas()
d_pendingReqPhase.clear();
}
-void InferenceManager::assertPendingFact(Node atom, bool polarity, Node exp)
-{
- eq::EqualityEngine* ee = d_state.getEqualityEngine();
- Trace("strings-pending") << "Assert pending fact : " << atom << " "
- << polarity << " from " << exp << std::endl;
- Assert(atom.getKind() != OR) << "Infer error: a split.";
- if (atom.getKind() == EQUAL)
- {
- // we must ensure these terms are registered
- Trace("strings-pending-debug") << " Register term" << std::endl;
- for (const Node& t : atom)
- {
- // terms in the equality engine are already registered, hence skip
- // currently done for only string-like terms, but this could potentially
- // be avoided.
- if (!ee->hasTerm(t) && t.getType().isStringLike())
- {
- d_termReg.registerTerm(t, 0);
- }
- }
- Trace("strings-pending-debug") << " Now assert equality" << std::endl;
- ee->assertEquality(atom, polarity, exp);
- Trace("strings-pending-debug") << " Finished assert equality" << std::endl;
- }
- else
- {
- ee->assertPredicate(atom, polarity, exp);
- if (atom.getKind() == STRING_IN_REGEXP)
- {
- if (polarity && atom[1].getKind() == REGEXP_CONCAT)
- {
- Node eqc = ee->getRepresentative(atom[0]);
- d_state.addEndpointsToEqcInfo(atom, atom[1], eqc);
- }
- }
- }
- // process the conflict
- if (!d_state.isInConflict())
- {
- Node pc = d_state.getPendingConflict();
- if (!pc.isNull())
- {
- std::vector<Node> a;
- a.push_back(pc);
- Trace("strings-pending")
- << "Process pending conflict " << pc << std::endl;
- Node conflictNode = mkExplain(a);
- d_state.notifyInConflict();
- Trace("strings-conflict")
- << "CONFLICT: Eager prefix : " << conflictNode << std::endl;
- ++(d_statistics.d_conflictsEagerPrefix);
- d_out.conflict(conflictNode);
- }
- }
- Trace("strings-pending-debug") << " Now collect terms" << std::endl;
- // Collect extended function terms in the atom. Notice that we must register
- // all extended functions occurring in assertions and shared terms. We
- // make a similar call to registerTermRec in TheoryStrings::addSharedTerm.
- d_extt.registerTermRec(atom);
- Trace("strings-pending-debug") << " Finished collect terms" << std::endl;
-}
-
bool InferenceManager::hasProcessed() const
{
return d_state.isInConflict() || !d_pendingLem.empty() || !d_pending.empty();
@@ -475,7 +398,6 @@ Node InferenceManager::mkExplain(const std::vector<Node>& a,
{
utils::flattenOp(AND, ac, aconj);
}
- eq::EqualityEngine* ee = d_state.getEqualityEngine();
for (const Node& apc : aconj)
{
if (std::find(noExplain.begin(), noExplain.end(), apc) != noExplain.end())
@@ -492,12 +414,12 @@ Node InferenceManager::mkExplain(const std::vector<Node>& a,
Debug("strings-explain") << "Add to explanation " << apc << std::endl;
if (apc.getKind() == NOT && apc[0].getKind() == EQUAL)
{
- Assert(ee->hasTerm(apc[0][0]));
- Assert(ee->hasTerm(apc[0][1]));
+ Assert(d_ee->hasTerm(apc[0][0]));
+ Assert(d_ee->hasTerm(apc[0][1]));
// ensure that we are ready to explain the disequality
- AlwaysAssert(ee->areDisequal(apc[0][0], apc[0][1], true));
+ AlwaysAssert(d_ee->areDisequal(apc[0][0], apc[0][1], true));
}
- Assert(apc.getKind() != EQUAL || ee->areEqual(apc[0], apc[1]));
+ Assert(apc.getKind() != EQUAL || d_ee->areEqual(apc[0], apc[1]));
// now, explain
explain(apc, antec_exp);
}
@@ -522,7 +444,6 @@ void InferenceManager::explain(TNode literal,
{
Debug("strings-explain") << "Explain " << literal << " "
<< d_state.isInConflict() << std::endl;
- eq::EqualityEngine* ee = d_state.getEqualityEngine();
bool polarity = literal.getKind() != NOT;
TNode atom = polarity ? literal : literal[0];
std::vector<TNode> tassumptions;
@@ -530,14 +451,14 @@ void InferenceManager::explain(TNode literal,
{
if (atom[0] != atom[1])
{
- Assert(ee->hasTerm(atom[0]));
- Assert(ee->hasTerm(atom[1]));
- ee->explainEquality(atom[0], atom[1], polarity, tassumptions);
+ Assert(d_ee->hasTerm(atom[0]));
+ Assert(d_ee->hasTerm(atom[1]));
+ d_ee->explainEquality(atom[0], atom[1], polarity, tassumptions);
}
}
else
{
- ee->explainPredicate(atom, polarity, tassumptions);
+ d_ee->explainPredicate(atom, polarity, tassumptions);
}
for (const TNode a : tassumptions)
{
diff --git a/src/theory/strings/inference_manager.h b/src/theory/strings/inference_manager.h
index 016891737..dc46f1683 100644
--- a/src/theory/strings/inference_manager.h
+++ b/src/theory/strings/inference_manager.h
@@ -29,6 +29,7 @@
#include "theory/strings/sequences_stats.h"
#include "theory/strings/solver_state.h"
#include "theory/strings/term_registry.h"
+#include "theory/theory_inference_manager.h"
#include "theory/uf/equality_engine.h"
namespace CVC4 {
@@ -65,28 +66,20 @@ namespace strings {
* theory of strings, e.g. sendPhaseRequirement, setIncomplete, and
* with the extended theory object e.g. markCongruent.
*/
-class InferenceManager
+class InferenceManager : public TheoryInferenceManager
{
typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap;
public:
- InferenceManager(context::Context* c,
- context::UserContext* u,
+ InferenceManager(Theory& t,
SolverState& s,
TermRegistry& tr,
ExtTheory& e,
- OutputChannel& out,
- SequencesStatistics& statistics);
+ SequencesStatistics& statistics,
+ ProofNodeManager* pnm);
~InferenceManager() {}
- /** send assumption
- *
- * This is called when a fact is asserted to TheoryStrings. It adds lit
- * to the equality engine maintained by this class immediately.
- */
- void sendAssumption(TNode lit);
-
/** send internal inferences
*
* This is called when we have inferred exp => conc, where exp is a set
@@ -292,23 +285,12 @@ class InferenceManager
// ------------------------------------------------- end extended theory
private:
- /** assert pending fact
- *
- * This asserts atom with polarity to the equality engine of this class,
- * where exp is the explanation of why (~) atom holds.
- *
- * This call may trigger further initialization steps involving the terms
- * of atom, including calls to registerTerm.
- */
- void assertPendingFact(Node atom, bool polarity, Node exp);
/** Reference to the solver state of the theory of strings. */
SolverState& d_state;
/** Reference to the term registry of theory of strings */
TermRegistry& d_termReg;
/** the extended theory object for the theory of strings */
ExtTheory& d_extt;
- /** A reference to the output channel of the theory of strings. */
- OutputChannel& d_out;
/** Reference to the statistics for the theory of strings/sequences. */
SequencesStatistics& d_statistics;
@@ -326,13 +308,6 @@ class InferenceManager
std::map<Node, bool> d_pendingReqPhase;
/** A list of pending lemmas to be sent on the output channel. */
std::vector<InferInfo> d_pendingLem;
- /**
- * The keep set of this class. This set is maintained to ensure that
- * facts and their explanations are ref-counted. Since facts and their
- * explanations are SAT-context-dependent, this set is also
- * SAT-context-dependent.
- */
- NodeSet d_keep;
};
} // namespace strings
diff --git a/src/theory/strings/theory_strings.cpp b/src/theory/strings/theory_strings.cpp
index 0de0cc33c..3e60cbc44 100644
--- a/src/theory/strings/theory_strings.cpp
+++ b/src/theory/strings/theory_strings.cpp
@@ -46,7 +46,7 @@ TheoryStrings::TheoryStrings(context::Context* c,
d_state(c, u, d_valuation),
d_termReg(d_state, out, d_statistics, nullptr),
d_extTheory(this),
- d_im(c, u, d_state, d_termReg, d_extTheory, out, d_statistics),
+ d_im(*this, d_state, d_termReg, d_extTheory, d_statistics, pnm),
d_rewriter(&d_statistics.d_rewrites),
d_bsolver(d_state, d_im),
d_csolver(d_state, d_im, d_termReg, d_bsolver),
@@ -83,6 +83,8 @@ TheoryStrings::TheoryStrings(context::Context* c,
}
// use the state object as the official theory state
d_theoryState = &d_state;
+ // use the inference manager as the official inference manager
+ d_inferManager = &d_im;
}
TheoryStrings::~TheoryStrings() {
@@ -165,23 +167,6 @@ void TheoryStrings::notifySharedTerm(TNode t)
Debug("strings") << "TheoryStrings::notifySharedTerm() finished" << std::endl;
}
-EqualityStatus TheoryStrings::getEqualityStatus(TNode a, TNode b) {
- if (d_equalityEngine->hasTerm(a) && d_equalityEngine->hasTerm(b))
- {
- if (d_equalityEngine->areEqual(a, b))
- {
- // The terms are implied to be equal
- return EQUALITY_TRUE;
- }
- if (d_equalityEngine->areDisequal(a, b, false))
- {
- // The terms are implied to be dis-equal
- return EQUALITY_FALSE;
- }
- }
- return EQUALITY_UNKNOWN;
-}
-
bool TheoryStrings::propagateLit(TNode literal)
{
Debug("strings-propagate")
@@ -252,23 +237,10 @@ void TheoryStrings::presolve() {
// MODEL GENERATION
/////////////////////////////////////////////////////////////////////////////
-bool TheoryStrings::collectModelInfo(TheoryModel* m)
+bool TheoryStrings::collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet)
{
- Trace("strings-model") << "TheoryStrings : Collect model info" << std::endl;
- Trace("strings-model") << "TheoryStrings : assertEqualityEngine." << std::endl;
-
- std::set<Node> termSet;
-
- // Compute terms appearing in assertions and shared terms
- computeRelevantTerms(termSet);
- // assert the (relevant) portion of the equality engine to the model
- if (!m->assertEqualityEngine(d_equalityEngine, &termSet))
- {
- Unreachable()
- << "TheoryStrings::collectModelInfo: failed to assert equality engine"
- << std::endl;
- return false;
- }
+ Trace("strings-model") << "TheoryStrings : Collect model values" << std::endl;
std::map<TypeNode, std::unordered_set<Node, NodeHashFunction> > repSet;
// Generate model
@@ -653,25 +625,68 @@ TrustNode TheoryStrings::expandDefinition(Node node)
return TrustNode::null();
}
-void TheoryStrings::check(Effort e) {
- if (done() && e<EFFORT_FULL) {
- return;
+bool TheoryStrings::preNotifyFact(
+ TNode atom, bool pol, TNode fact, bool isPrereg, bool isInternal)
+{
+ // this is only required for internal facts, others are already registered
+ if (isInternal && atom.getKind() == EQUAL)
+ {
+ // we must ensure these terms are registered
+ for (const Node& t : atom)
+ {
+ // terms in the equality engine are already registered, hence skip
+ // currently done for only string-like terms, but this could potentially
+ // be avoided.
+ if (!d_equalityEngine->hasTerm(t) && t.getType().isStringLike())
+ {
+ d_termReg.registerTerm(t, 0);
+ }
+ }
}
+ return false;
+}
- TimerStat::CodeTimer checkTimer(d_checkTime);
-
- // Trace("strings-process") << "Theory of strings, check : " << e << std::endl;
- Trace("strings-check-debug")
- << "Theory of strings, check : " << e << std::endl;
- while (!done() && !d_state.isInConflict())
+void TheoryStrings::notifyFact(TNode atom,
+ bool polarity,
+ TNode fact,
+ bool isInternal)
+{
+ if (atom.getKind() == STRING_IN_REGEXP)
{
- // Get all the assertions
- Assertion assertion = get();
- TNode fact = assertion.d_assertion;
-
- Trace("strings-assertion") << "get assertion: " << fact << endl;
- d_im.sendAssumption(fact);
+ if (polarity && atom[1].getKind() == REGEXP_CONCAT)
+ {
+ Node eqc = d_equalityEngine->getRepresentative(atom[0]);
+ d_state.addEndpointsToEqcInfo(atom, atom[1], eqc);
+ }
}
+ // process pending conflicts due to reasoning about endpoints
+ if (!d_state.isInConflict())
+ {
+ Node pc = d_state.getPendingConflict();
+ if (!pc.isNull())
+ {
+ std::vector<Node> a;
+ a.push_back(pc);
+ Trace("strings-pending")
+ << "Process pending conflict " << pc << std::endl;
+ Node conflictNode = d_im.mkExplain(a);
+ Trace("strings-conflict")
+ << "CONFLICT: Eager prefix : " << conflictNode << std::endl;
+ ++(d_statistics.d_conflictsEagerPrefix);
+ d_im.conflict(conflictNode);
+ return;
+ }
+ }
+ Trace("strings-pending-debug") << " Now collect terms" << std::endl;
+ // Collect extended function terms in the atom. Notice that we must register
+ // all extended functions occurring in assertions and shared terms. We
+ // make a similar call to registerTermRec in TheoryStrings::addSharedTerm.
+ d_extTheory.registerTermRec(atom);
+ Trace("strings-pending-debug") << " Finished collect terms" << std::endl;
+}
+
+void TheoryStrings::postCheck(Effort e)
+{
d_im.doPendingFacts();
Assert(d_strat.isStrategyInit());
@@ -680,8 +695,10 @@ void TheoryStrings::check(Effort e) {
{
Trace("strings-check-debug")
<< "Theory of strings " << e << " effort check " << std::endl;
- if(Trace.isOn("strings-eqc")) {
- for( unsigned t=0; t<2; t++ ) {
+ if (Trace.isOn("strings-eqc"))
+ {
+ for (unsigned t = 0; t < 2; t++)
+ {
eq::EqClassesIterator eqcs2_i = eq::EqClassesIterator(d_equalityEngine);
Trace("strings-eqc") << (t==0 ? "STRINGS:" : "OTHER:") << std::endl;
while( !eqcs2_i.isFinished() ){
@@ -725,7 +742,9 @@ void TheoryStrings::check(Effort e) {
++(d_statistics.d_strategyRuns);
Trace("strings-check") << " * Run strategy..." << std::endl;
runStrategy(e);
- // flush the facts
+ // Send the facts *and* the lemmas. We send lemmas regardless of whether
+ // we send facts since some lemmas cannot be dropped. Other lemmas are
+ // otherwise avoided by aborting the strategy when a fact is ready.
addedFact = d_im.hasPendingFact();
addedLemma = d_im.hasPendingLemma();
d_im.doPendingFacts();
diff --git a/src/theory/strings/theory_strings.h b/src/theory/strings/theory_strings.h
index f4aa0675c..0f59e73dc 100644
--- a/src/theory/strings/theory_strings.h
+++ b/src/theory/strings/theory_strings.h
@@ -97,27 +97,33 @@ class TheoryStrings : public Theory {
void shutdown() override {}
/** add shared term */
void notifySharedTerm(TNode n) override;
- /** get equality status */
- EqualityStatus getEqualityStatus(TNode a, TNode b) override;
/** preregister term */
void preRegisterTerm(TNode n) override;
/** Expand definition */
TrustNode expandDefinition(Node n) override;
- /** Check at effort e */
- void check(Effort e) override;
- /** needs check last effort */
+ //--------------------------------- standard check
+ /** Do we need a check call at last call effort? */
bool needsCheckLastEffort() override;
+ bool preNotifyFact(TNode atom,
+ bool pol,
+ TNode fact,
+ bool isPrereg,
+ bool isInternal) override;
+ void notifyFact(TNode atom, bool pol, TNode fact, bool isInternal) override;
+ /** Post-check, called after the fact queue of the theory is processed. */
+ void postCheck(Effort level) override;
+ //--------------------------------- end standard check
+ /** propagate method */
+ bool propagateLit(TNode literal);
/** Conflict when merging two constants */
void conflict(TNode a, TNode b);
/** called when a new equivalence class is created */
void eqNotifyNewClass(TNode t);
/** preprocess rewrite */
TrustNode ppRewrite(TNode atom) override;
- /**
- * Get all relevant information in this theory regarding the current
- * model. Return false if a contradiction is discovered.
- */
- bool collectModelInfo(TheoryModel* m) override;
+ /** Collect model values in m based on the relevant terms given by termSet */
+ bool collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet) override;
private:
/** NotifyClass for equality engine */
@@ -171,8 +177,6 @@ class TheoryStrings : public Theory {
/** The solver state of the theory of strings */
SolverState& d_state;
};/* class TheoryStrings::NotifyClass */
- /** propagate method */
- bool propagateLit(TNode literal);
/** compute care graph */
void computeCareGraph() override;
/**
diff --git a/src/theory/strings/theory_strings_preprocess.cpp b/src/theory/strings/theory_strings_preprocess.cpp
index a752958b2..084e2ac91 100644
--- a/src/theory/strings/theory_strings_preprocess.cpp
+++ b/src/theory/strings/theory_strings_preprocess.cpp
@@ -19,6 +19,7 @@
#include <stdint.h>
#include "expr/kind.h"
+#include "options/smt_options.h"
#include "options/strings_options.h"
#include "proof/proof_manager.h"
#include "smt/logic_exception.h"
@@ -972,7 +973,10 @@ void StringsPreprocess::processAssertions( std::vector< Node > &vec_node ){
: NodeManager::currentNM()->mkNode(kind::AND, asserts);
if( res!=vec_node[i] ){
res = Rewriter::rewrite( res );
- PROOF( ProofManager::currentPM()->addDependence( res, vec_node[i] ); );
+ if (options::unsatCores())
+ {
+ ProofManager::currentPM()->addDependence(res, vec_node[i]);
+ }
vec_node[i] = res;
}
}
diff --git a/src/theory/theory.cpp b/src/theory/theory.cpp
index 66541a63e..3c603051c 100644
--- a/src/theory/theory.cpp
+++ b/src/theory/theory.cpp
@@ -23,6 +23,7 @@
#include "base/check.h"
#include "expr/node_algorithm.h"
+#include "options/smt_options.h"
#include "options/theory_options.h"
#include "smt/smt_statistics_registry.h"
#include "theory/ext_theory.h"
@@ -81,8 +82,7 @@ Theory::Theory(TheoryId id,
d_equalityEngine(nullptr),
d_allocEqualityEngine(nullptr),
d_theoryState(nullptr),
- d_inferManager(nullptr),
- d_proofsEnabled(false)
+ d_inferManager(nullptr)
{
smtStatisticsRegistry()->registerStat(&d_checkTime);
smtStatisticsRegistry()->registerStat(&d_computeCareGraphTime);
@@ -296,12 +296,12 @@ void Theory::computeCareGraph() {
switch (d_valuation.getEqualityStatus(a, b)) {
case EQUALITY_TRUE_AND_PROPAGATED:
case EQUALITY_FALSE_AND_PROPAGATED:
- // If we know about it, we should have propagated it, so we can skip
- break;
+ // If we know about it, we should have propagated it, so we can skip
+ break;
default:
- // Let's split on it
- addCarePair(a, b);
- break;
+ // Let's split on it
+ addCarePair(a, b);
+ break;
}
}
}
@@ -359,8 +359,15 @@ std::unordered_set<TNode, TNodeHashFunction> Theory::currentlySharedTerms() cons
bool Theory::collectModelInfo(TheoryModel* m)
{
+ // NOTE: the computation of termSet will be moved to model manager
+ // and passed as an argument to collectModelInfo.
std::set<Node> termSet;
// Compute terms appearing in assertions and shared terms
+ TheoryModel* tm = d_valuation.getModel();
+ Assert(tm != nullptr);
+ const std::set<Kind>& irrKinds = tm->getIrrelevantKinds();
+ computeAssertedTerms(termSet, irrKinds, true);
+ // Compute additional relevant terms (theory-specific)
computeRelevantTerms(termSet);
// if we are using an equality engine, assert it to the model
if (d_equalityEngine != nullptr)
@@ -375,7 +382,7 @@ bool Theory::collectModelInfo(TheoryModel* m)
}
void Theory::collectTerms(TNode n,
- set<Kind>& irrKinds,
+ const std::set<Kind>& irrKinds,
set<Node>& termSet) const
{
if (termSet.find(n) != termSet.end()) {
@@ -396,13 +403,11 @@ void Theory::collectTerms(TNode n,
}
}
-void Theory::computeRelevantTermsInternal(std::set<Node>& termSet,
- std::set<Kind>& irrKinds,
- bool includeShared) const
+void Theory::computeAssertedTerms(std::set<Node>& termSet,
+ const std::set<Kind>& irrKinds,
+ bool includeShared) const
{
// Collect all terms appearing in assertions
- irrKinds.insert(kind::EQUAL);
- irrKinds.insert(kind::NOT);
context::CDList<Assertion>::const_iterator assert_it = facts_begin(),
assert_it_end = facts_end();
for (; assert_it != assert_it_end; ++assert_it)
@@ -424,10 +429,9 @@ void Theory::computeRelevantTermsInternal(std::set<Node>& termSet,
}
}
-void Theory::computeRelevantTerms(std::set<Node>& termSet, bool includeShared)
+void Theory::computeRelevantTerms(std::set<Node>& termSet)
{
- std::set<Kind> irrKinds;
- computeRelevantTermsInternal(termSet, irrKinds, includeShared);
+ // by default, there are no additional relevant terms
}
bool Theory::collectModelValues(TheoryModel* m, const std::set<Node>& termSet)
diff --git a/src/theory/theory.h b/src/theory/theory.h
index c5fcf362c..176d4b672 100644
--- a/src/theory/theory.h
+++ b/src/theory/theory.h
@@ -183,26 +183,10 @@ class Theory {
//---------------------------------- private collect model info
/**
- * Scans the current set of assertions and shared terms top-down
- * until a theory-leaf is reached, and adds all terms found to
- * termSet. This is used by collectModelInfo to delimit the set of
- * terms that should be used when constructing a model.
- *
- * irrKinds: The kinds of terms that appear in assertions that should *not*
- * be included in termSet. Note that the kinds EQUAL and NOT are always
- * treated as irrelevant kinds.
- *
- * includeShared: Whether to include shared terms in termSet. Notice that
- * shared terms are not influenced by irrKinds.
- */
- void computeRelevantTermsInternal(std::set<Node>& termSet,
- std::set<Kind>& irrKinds,
- bool includeShared = true) const;
- /**
* Helper function for computeRelevantTerms
*/
void collectTerms(TNode n,
- std::set<Kind>& irrKinds,
+ const std::set<Kind>& irrKinds,
std::set<Node>& termSet) const;
//---------------------------------- end private collect model info
@@ -262,11 +246,6 @@ class Theory {
* the equality engine are used properly.
*/
TheoryInferenceManager* d_inferManager;
- /**
- * Whether proofs are enabled
- *
- */
- bool d_proofsEnabled;
/**
* Returns the next assertion in the assertFact() queue.
@@ -597,6 +576,7 @@ class Theory {
Unimplemented() << "Theory " << identify()
<< " propagated a node but doesn't implement the "
"Theory::explain() interface!";
+ return TrustNode::null();
}
//--------------------------------- check
@@ -688,13 +668,29 @@ class Theory {
*/
virtual bool collectModelInfo(TheoryModel* m);
/**
- * Same as above, but with empty irrKinds. This version can be overridden
- * by the theory, e.g. by restricting or extending the set of terms returned
- * by computeRelevantTermsInternal, which is called by default with no
- * irrKinds.
+ * Scans the current set of assertions and shared terms top-down
+ * until a theory-leaf is reached, and adds all terms found to
+ * termSet. This is used by collectModelInfo to delimit the set of
+ * terms that should be used when constructing a model.
+ *
+ * @param irrKinds The kinds of terms that appear in assertions that should *not*
+ * be included in termSet. Note that the kinds EQUAL and NOT are always
+ * treated as irrelevant kinds.
+ *
+ * @param includeShared Whether to include shared terms in termSet. Notice that
+ * shared terms are not influenced by irrKinds.
+ *
+ * TODO (project #39): this method will be deleted. The version in
+ * model manager will be used.
+ */
+ void computeAssertedTerms(std::set<Node>& termSet,
+ const std::set<Kind>& irrKinds,
+ bool includeShared = true) const;
+ /**
+ * Compute terms that are not necessarily part of the assertions or
+ * shared terms that should be considered relevant, add them to termSet.
*/
- virtual void computeRelevantTerms(std::set<Node>& termSet,
- bool includeShared = true);
+ virtual void computeRelevantTerms(std::set<Node>& termSet);
/**
* Collect model values, after equality information is added to the model.
* The argument termSet is the set of relevant terms returned by
@@ -824,15 +820,13 @@ class Theory {
*
* @return true iff facts have been asserted to this theory.
*/
- bool hasFacts() {
- return !d_facts.empty();
- }
+ bool hasFacts() { return !d_facts.empty(); }
/** Return total number of facts asserted to this theory */
size_t numAssertions() {
return d_facts.size();
}
-
+
typedef context::CDList<TNode>::const_iterator shared_terms_iterator;
/**
@@ -917,7 +911,7 @@ class Theory {
/* is extended function reduced */
virtual bool isExtfReduced( int effort, Node n, Node on, std::vector< Node >& exp ) { return n.isConst(); }
-
+
/**
* Get reduction for node
* If return value is not 0, then n is reduced.
@@ -927,9 +921,6 @@ class Theory {
* and return value should be <0.
*/
virtual int getReduction( int effort, Node n, Node& nr ) { return 0; }
-
- /** Turn on proof-production mode. */
- void produceProofs() { d_proofsEnabled = true; }
};/* class Theory */
std::ostream& operator<<(std::ostream& os, theory::Theory::Effort level);
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index c61879b6d..6837d4be5 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -28,14 +28,9 @@
#include "expr/node_visitor.h"
#include "options/bv_options.h"
#include "options/options.h"
-#include "options/proof_options.h"
#include "options/quantifiers_options.h"
#include "options/theory_options.h"
#include "preprocessing/assertion_pipeline.h"
-#include "proof/cnf_proof.h"
-#include "proof/lemma_proof.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
#include "smt/logic_exception.h"
#include "smt/term_formula_removal.h"
#include "theory/arith/arith_ite_utils.h"
@@ -256,10 +251,6 @@ TheoryEngine::TheoryEngine(context::Context* context,
d_true = NodeManager::currentNM()->mkConst<bool>(true);
d_false = NodeManager::currentNM()->mkConst<bool>(false);
-#ifdef CVC4_PROOF
- ProofManager::currentPM()->initTheoryProofEngine();
-#endif
-
smtStatisticsRegistry()->registerStat(&d_arithSubstitutionsAdded);
}
@@ -1150,23 +1141,6 @@ bool TheoryEngine::propagate(TNode literal, theory::TheoryId theory) {
assertToTheory(literal, literal, /* to */ THEORY_BUILTIN, /* from */ theory);
}
} else {
- // We could be propagating a unit-clause lemma. In this case, we need to provide a
- // recipe.
- // TODO: Consider putting this someplace else? This is the only refence to the proof
- // manager in this class.
-
- PROOF({
- LemmaProofRecipe proofRecipe;
- proofRecipe.addBaseAssertion(literal);
-
- Node emptyNode;
- LemmaProofRecipe::ProofStep proofStep(theory, emptyNode);
- proofStep.addAssertion(literal);
- proofRecipe.addStep(proofStep);
-
- ProofManager::getCnfProof()->setProofRecipe(&proofRecipe);
- });
-
// Just send off to the SAT solver
Assert(d_propEngine->isSatLiteral(literal));
assertToTheory(literal, literal, /* to */ THEORY_SAT_SOLVER, /* from */ theory);
@@ -1309,65 +1283,31 @@ static Node mkExplanation(const std::vector<NodeTheoryPair>& explanation) {
return conjunction;
}
-Node TheoryEngine::getExplanationAndRecipe(TNode node, LemmaProofRecipe* proofRecipe) {
- Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << "): current propagation index = " << d_propagationMapTimestamp << endl;
+Node TheoryEngine::getExplanation(TNode node)
+{
+ Debug("theory::explain") << "TheoryEngine::getExplanation(" << node
+ << "): current propagation index = "
+ << d_propagationMapTimestamp << endl;
bool polarity = node.getKind() != kind::NOT;
TNode atom = polarity ? node : node[0];
// If we're not in shared mode, explanations are simple
- if (!d_logicInfo.isSharingEnabled()) {
- Debug("theory::explain") << "TheoryEngine::getExplanation: sharing is NOT enabled. "
- << " Responsible theory is: "
- << theoryOf(atom)->getId() << std::endl;
+ if (!d_logicInfo.isSharingEnabled())
+ {
+ Debug("theory::explain")
+ << "TheoryEngine::getExplanation: sharing is NOT enabled. "
+ << " Responsible theory is: " << theoryOf(atom)->getId() << std::endl;
TrustNode texplanation = theoryOf(atom)->explain(node);
Node explanation = texplanation.getNode();
- Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << endl;
- PROOF({
- if(proofRecipe) {
- Node emptyNode;
- LemmaProofRecipe::ProofStep proofStep(theoryOf(atom)->getId(), emptyNode);
- proofStep.addAssertion(node);
- proofRecipe->addBaseAssertion(node);
-
- if (explanation.getKind() == kind::AND) {
- // If the explanation is a conjunction, the recipe for the corresponding lemma is
- // the negation of its conjuncts.
- Node flat = flattenAnd(explanation);
- for (unsigned i = 0; i < flat.getNumChildren(); ++i) {
- if (flat[i].isConst() && flat[i].getConst<bool>()) {
- ++ i;
- continue;
- }
- if (flat[i].getKind() == kind::NOT &&
- flat[i][0].isConst() && !flat[i][0].getConst<bool>()) {
- ++ i;
- continue;
- }
- Debug("theory::explain") << "TheoryEngine::getExplanationAndRecipe: adding recipe assertion: "
- << flat[i].negate() << std::endl;
- proofStep.addAssertion(flat[i].negate());
- proofRecipe->addBaseAssertion(flat[i].negate());
- }
- } else {
- // The recipe for proving it is by negating it. "True" is not an acceptable reason.
- if (!((explanation.isConst() && explanation.getConst<bool>()) ||
- (explanation.getKind() == kind::NOT &&
- explanation[0].isConst() && !explanation[0].getConst<bool>()))) {
- proofStep.addAssertion(explanation.negate());
- proofRecipe->addBaseAssertion(explanation.negate());
- }
- }
-
- proofRecipe->addStep(proofStep);
- }
- });
-
+ Debug("theory::explain") << "TheoryEngine::getExplanation(" << node
+ << ") => " << explanation << endl;
return explanation;
}
- Debug("theory::explain") << "TheoryEngine::getExplanation: sharing IS enabled" << std::endl;
+ Debug("theory::explain") << "TheoryEngine::getExplanation: sharing IS enabled"
+ << std::endl;
// Initial thing to explain
NodeTheoryPair toExplain(node, THEORY_SAT_SOLVER, d_propagationMapTimestamp);
@@ -1378,33 +1318,20 @@ Node TheoryEngine::getExplanationAndRecipe(TNode node, LemmaProofRecipe* proofRe
<< "TheoryEngine::getExplanation: explainer for node "
<< nodeExplainerPair.d_node
<< " is theory: " << nodeExplainerPair.d_theory << std::endl;
- TheoryId explainer = nodeExplainerPair.d_theory;
// Create the workplace for explanations
std::vector<NodeTheoryPair> explanationVector;
explanationVector.push_back(d_propagationMap[toExplain]);
// Process the explanation
- if (proofRecipe) {
- Node emptyNode;
- LemmaProofRecipe::ProofStep proofStep(explainer, emptyNode);
- proofStep.addAssertion(node);
- proofRecipe->addStep(proofStep);
- proofRecipe->addBaseAssertion(node);
- }
-
- getExplanation(explanationVector, proofRecipe);
+ getExplanation(explanationVector);
Node explanation = mkExplanation(explanationVector);
- Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << endl;
+ Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => "
+ << explanation << endl;
return explanation;
}
-Node TheoryEngine::getExplanation(TNode node) {
- LemmaProofRecipe *dontCareRecipe = NULL;
- return getExplanationAndRecipe(node, dontCareRecipe);
-}
-
struct AtomsCollect {
std::vector<TNode> d_atoms;
@@ -1504,7 +1431,6 @@ void TheoryEngine::ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::The
}
theory::LemmaStatus TheoryEngine::lemma(TNode node,
- ProofRule rule,
bool negated,
theory::LemmaProperty p,
theory::TheoryId atomsTo)
@@ -1567,8 +1493,7 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node,
// assert lemmas to prop engine
for (size_t i = 0, lsize = lemmas.size(); i < lsize; ++i)
{
- d_propEngine->assertLemma(
- lemmas[i], i == 0 && negated, removable, rule, node);
+ d_propEngine->assertLemma(lemmas[i], i == 0 && negated, removable);
}
// WARNING: Below this point don't assume lemmas[0] to be not negated.
@@ -1611,23 +1536,6 @@ void TheoryEngine::conflict(TNode conflict, TheoryId theoryId) {
<< CheckSatCommand(conflict.toExpr());
}
- LemmaProofRecipe* proofRecipe = NULL;
- PROOF({
- proofRecipe = new LemmaProofRecipe;
- Node emptyNode;
- LemmaProofRecipe::ProofStep proofStep(theoryId, emptyNode);
-
- if (conflict.getKind() == kind::AND) {
- for (unsigned i = 0; i < conflict.getNumChildren(); ++i) {
- proofStep.addAssertion(conflict[i].negate());
- }
- } else {
- proofStep.addAssertion(conflict.negate());
- }
-
- proofRecipe->addStep(proofStep);
- });
-
// In the multiple-theories case, we need to reconstruct the conflict
if (d_logicInfo.isSharingEnabled()) {
// Create the workplace for explanations
@@ -1635,67 +1543,29 @@ void TheoryEngine::conflict(TNode conflict, TheoryId theoryId) {
explanationVector.push_back(NodeTheoryPair(conflict, theoryId, d_propagationMapTimestamp));
// Process the explanation
- getExplanation(explanationVector, proofRecipe);
- PROOF(ProofManager::getCnfProof()->setProofRecipe(proofRecipe));
+ getExplanation(explanationVector);
Node fullConflict = mkExplanation(explanationVector);
Debug("theory::conflict") << "TheoryEngine::conflict(" << conflict << ", " << theoryId << "): full = " << fullConflict << endl;
Assert(properConflict(fullConflict));
lemma(fullConflict,
- RULE_CONFLICT,
true,
LemmaProperty::REMOVABLE,
THEORY_LAST);
} else {
// When only one theory, the conflict should need no processing
Assert(properConflict(conflict));
- PROOF({
- if (conflict.getKind() == kind::AND) {
- // If the conflict is a conjunction, the corresponding lemma is derived by negating
- // its conjuncts.
- for (unsigned i = 0; i < conflict.getNumChildren(); ++i) {
- if (conflict[i].isConst() && conflict[i].getConst<bool>()) {
- ++ i;
- continue;
- }
- if (conflict[i].getKind() == kind::NOT &&
- conflict[i][0].isConst() && !conflict[i][0].getConst<bool>()) {
- ++ i;
- continue;
- }
- proofRecipe->getStep(0)->addAssertion(conflict[i].negate());
- proofRecipe->addBaseAssertion(conflict[i].negate());
- }
- } else {
- proofRecipe->getStep(0)->addAssertion(conflict.negate());
- proofRecipe->addBaseAssertion(conflict.negate());
- }
-
- ProofManager::getCnfProof()->setProofRecipe(proofRecipe);
- });
-
- lemma(conflict, RULE_CONFLICT, true, LemmaProperty::REMOVABLE, THEORY_LAST);
+ lemma(conflict, true, LemmaProperty::REMOVABLE, THEORY_LAST);
}
-
- PROOF({
- delete proofRecipe;
- proofRecipe = NULL;
- });
}
-void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector, LemmaProofRecipe* proofRecipe) {
+void TheoryEngine::getExplanation(
+ std::vector<NodeTheoryPair>& explanationVector)
+{
Assert(explanationVector.size() > 0);
unsigned i = 0; // Index of the current literal we are processing
unsigned j = 0; // Index of the last literal we are keeping
- std::unique_ptr<std::set<Node>> inputAssertions = nullptr;
- PROOF({
- if (proofRecipe)
- {
- inputAssertions.reset(
- new std::set<Node>(proofRecipe->getStep(0)->getAssertions()));
- }
- });
// cache of nodes we have already explained by some theory
std::unordered_map<Node, size_t, NodeHashFunction> cache;
@@ -1768,22 +1638,6 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
explanationVector.push_back((*find).second);
++i;
- PROOF({
- if (toExplain.d_node != (*find).second.d_node)
- {
- Debug("pf::explain")
- << "TheoryEngine::getExplanation: Rewrite alert! toAssert = "
- << toExplain.d_node << ", toExplain = " << (*find).second.d_node
- << std::endl;
-
- if (proofRecipe)
- {
- proofRecipe->addRewriteRule(toExplain.d_node,
- (*find).second.d_node);
- }
- }
- })
-
continue;
}
}
@@ -1814,59 +1668,10 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
explanationVector.push_back(newExplain);
++ i;
-
- PROOF({
- if (proofRecipe && inputAssertions)
- {
- // If we're expanding the target node of the explanation (this is the
- // first expansion...), we don't want to add it as a separate proof
- // step. It is already part of the assertions.
- if (!ContainsKey(*inputAssertions, toExplain.d_node))
- {
- LemmaProofRecipe::ProofStep proofStep(toExplain.d_theory,
- toExplain.d_node);
- if (explanation.getKind() == kind::AND)
- {
- Node flat = flattenAnd(explanation);
- for (unsigned k = 0; k < flat.getNumChildren(); ++k)
- {
- // If a true constant or a negation of a false constant we can
- // ignore it
- if (!((flat[k].isConst() && flat[k].getConst<bool>())
- || (flat[k].getKind() == kind::NOT && flat[k][0].isConst()
- && !flat[k][0].getConst<bool>())))
- {
- proofStep.addAssertion(flat[k].negate());
- }
- }
- }
- else
- {
- if (!((explanation.isConst() && explanation.getConst<bool>())
- || (explanation.getKind() == kind::NOT
- && explanation[0].isConst()
- && !explanation[0].getConst<bool>())))
- {
- proofStep.addAssertion(explanation.negate());
- }
- }
- proofRecipe->addStep(proofStep);
- }
- }
- });
}
// Keep only the relevant literals
explanationVector.resize(j);
-
- PROOF({
- if (proofRecipe) {
- // The remaining literals are the base of the proof
- for (unsigned k = 0; k < explanationVector.size(); ++k) {
- proofRecipe->addBaseAssertion(explanationVector[k].d_node.negate());
- }
- }
- });
}
void TheoryEngine::setUserAttribute(const std::string& attr,
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index b1543ad0b..167bd6d75 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -53,7 +53,6 @@
namespace CVC4 {
class ResourceManager;
-class LemmaProofRecipe;
/**
* A pair of a theory and a node. This is used to mark the flow of
@@ -292,7 +291,6 @@ class TheoryEngine {
* @param p the properties of the lemma.
*/
theory::LemmaStatus lemma(TNode node,
- ProofRule rule,
bool negated,
theory::LemmaProperty p,
theory::TheoryId atomsTo);
@@ -442,14 +440,13 @@ class TheoryEngine {
bool markPropagation(TNode assertion, TNode originalAssertions, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId);
/**
- * Computes the explanation by travarsing the propagation graph and
+ * Computes the explanation by traversing the propagation graph and
* asking relevant theories to explain the propagations. Initially
* the explanation vector should contain only the element (node, theory)
* where the node is the one to be explained, and the theory is the
- * theory that sent the literal. The lemmaProofRecipe will contain a list
- * of the explanation steps required to produce the original node.
+ * theory that sent the literal.
*/
- void getExplanation(std::vector<NodeTheoryPair>& explanationVector, LemmaProofRecipe* lemmaProofRecipe);
+ void getExplanation(std::vector<NodeTheoryPair>& explanationVector);
public:
/**
@@ -570,12 +567,6 @@ class TheoryEngine {
Node getExplanation(TNode node);
/**
- * Returns an explanation of the node propagated to the SAT solver and the theory
- * that propagated it.
- */
- Node getExplanationAndRecipe(TNode node, LemmaProofRecipe* proofRecipe);
-
- /**
* Get the pointer to the model object used by this theory engine.
*/
theory::TheoryModel* getModel();
@@ -687,14 +678,15 @@ class TheoryEngine {
/**
* Get instantiation methods
* first inputs forall x.q[x] and returns ( q[a], ..., q[z] )
- * second inputs forall x.q[x] and returns ( a, ..., z )
- * third and fourth return mappings e.g. forall x.q1[x] -> ( q1[a]...q1[z] ) , ... , forall x.qn[x] -> ( qn[a]...qn[z] )
+ * second inputs forall x.q[x] and returns ( a, ..., z )
+ * third and fourth return mappings e.g. forall x.q1[x] -> ( q1[a]...q1[z] )
+ * , ... , forall x.qn[x] -> ( qn[a]...qn[z] )
*/
void getInstantiations( Node q, std::vector< Node >& insts );
void getInstantiationTermVectors( Node q, std::vector< std::vector< Node > >& tvecs );
void getInstantiations( std::map< Node, std::vector< Node > >& insts );
void getInstantiationTermVectors( std::map< Node, std::vector< std::vector< Node > > >& insts );
-
+
/**
* Get instantiated conjunction, returns q[t1] ^ ... ^ q[tn] where t1...tn are current set of instantiations for q.
* Can be used for quantifier elimination when satisfiable and q[t1] ^ ... ^ q[tn] |= q
@@ -726,7 +718,7 @@ private:
public:
/** Set user attribute.
- *
+ *
* This function is called when an attribute is set by a user. In SMT-LIBv2
* this is done via the syntax (! n :attr)
*/
@@ -736,7 +728,7 @@ private:
const std::string& str_value);
/** Handle user attribute.
- *
+ *
* Associates theory t with the attribute attr. Theory t will be
* notified whenever an attribute of name attr is set.
*/
diff --git a/src/theory/theory_inference.cpp b/src/theory/theory_inference.cpp
new file mode 100644
index 000000000..618dc640b
--- /dev/null
+++ b/src/theory/theory_inference.cpp
@@ -0,0 +1,63 @@
+/********************* */
+/*! \file theory_inference.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief The theory inference utility
+ **/
+
+#include "theory/theory_inference.h"
+
+#include "theory/theory_inference_manager.h"
+
+using namespace CVC4::kind;
+
+namespace CVC4 {
+namespace theory {
+
+SimpleTheoryLemma::SimpleTheoryLemma(Node n,
+ LemmaProperty p,
+ ProofGenerator* pg)
+ : d_node(n), d_property(p), d_pg(pg)
+{
+}
+
+bool SimpleTheoryLemma::process(TheoryInferenceManager* im)
+{
+ Assert(!d_node.isNull());
+ // send (trusted) lemma on the output channel with property p
+ return im->trustedLemma(TrustNode::mkTrustLemma(d_node, d_pg), d_property);
+}
+
+SimpleTheoryInternalFact::SimpleTheoryInternalFact(Node conc,
+ Node exp,
+ ProofGenerator* pg)
+ : d_conc(conc), d_exp(exp), d_pg(pg)
+{
+}
+
+bool SimpleTheoryInternalFact::process(TheoryInferenceManager* im)
+{
+ bool polarity = d_conc.getKind() != NOT;
+ TNode atom = polarity ? d_conc : d_conc[0];
+ // no double negation or conjunctive conclusions
+ Assert(atom.getKind() != NOT && atom.getKind() != AND);
+ if (d_pg != nullptr)
+ {
+ im->assertInternalFact(atom, polarity, {d_exp}, d_pg);
+ }
+ else
+ {
+ im->assertInternalFact(atom, polarity, d_exp);
+ }
+ return true;
+}
+
+} // namespace theory
+} // namespace CVC4
diff --git a/src/theory/theory_inference.h b/src/theory/theory_inference.h
new file mode 100644
index 000000000..8d98051bf
--- /dev/null
+++ b/src/theory/theory_inference.h
@@ -0,0 +1,106 @@
+/********************* */
+/*! \file theory_inference.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief The theory inference utility
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__THEORY__THEORY_INFERENCE_H
+#define CVC4__THEORY__THEORY_INFERENCE_H
+
+#include "expr/node.h"
+#include "theory/output_channel.h"
+
+namespace CVC4 {
+namespace theory {
+
+class TheoryInferenceManager;
+
+/**
+ * A theory inference base class. This class is an abstract data structure for
+ * storing pending lemmas or facts in the buffered inference manager. It can
+ * be seen a single use object capturing instructions for making a single
+ * call to TheoryInferenceManager for lemmas or facts.
+ */
+class TheoryInference
+{
+ public:
+ virtual ~TheoryInference() {}
+ /**
+ * Called by the provided inference manager to process this inference. This
+ * method should make call(s) to inference manager to process this
+ * inference, as well as processing any specific side effects. This method
+ * typically makes a single call to the provided inference manager e.g.
+ * d_im->trustedLemma or d_im->assertFactInternal. Notice it is the sole
+ * responsibility of this class to make this call; the inference manager
+ * does not call itself otherwise when processing pending inferences.
+ *
+ * @return true if the inference was successfully processed by the inference
+ * manager. This method for instance returns false if it corresponds to a
+ * lemma that was already cached by im and hence was discarded.
+ */
+ virtual bool process(TheoryInferenceManager* im) = 0;
+};
+
+/**
+ * A simple theory lemma with no side effects. Makes a single call to
+ * trustedLemma in its process method.
+ */
+class SimpleTheoryLemma : public TheoryInference
+{
+ public:
+ SimpleTheoryLemma(Node n, LemmaProperty p, ProofGenerator* pg);
+ virtual ~SimpleTheoryLemma() {}
+ /**
+ * Send the lemma using inference manager im, return true if the lemma was
+ * sent.
+ */
+ virtual bool process(TheoryInferenceManager* im) override;
+ /** The lemma to send */
+ Node d_node;
+ /** The lemma property (see OutputChannel::lemma) */
+ LemmaProperty d_property;
+ /**
+ * The proof generator for this lemma, which if non-null, is wrapped in a
+ * TrustNode to be set on the output channel via trustedLemma at the time
+ * the lemma is sent. This proof generator must be able to provide a proof
+ * for d_node in the remainder of the user context.
+ */
+ ProofGenerator* d_pg;
+};
+
+/**
+ * A simple internal fact with no side effects. Makes a single call to
+ * assertFactInternal in its process method.
+ */
+class SimpleTheoryInternalFact : public TheoryInference
+{
+ public:
+ SimpleTheoryInternalFact(Node conc, Node exp, ProofGenerator* pg);
+ virtual ~SimpleTheoryInternalFact() {}
+ /**
+ * Send the lemma using inference manager im, return true if the lemma was
+ * sent.
+ */
+ virtual bool process(TheoryInferenceManager* im) override;
+ /** The lemma to send */
+ Node d_conc;
+ /** The explanation */
+ Node d_exp;
+ /** The proof generator */
+ ProofGenerator* d_pg;
+};
+
+} // namespace theory
+} // namespace CVC4
+
+#endif
diff --git a/src/theory/theory_inference_manager.cpp b/src/theory/theory_inference_manager.cpp
index a42c33814..9405a8162 100644
--- a/src/theory/theory_inference_manager.cpp
+++ b/src/theory/theory_inference_manager.cpp
@@ -30,7 +30,10 @@ TheoryInferenceManager::TheoryInferenceManager(Theory& t,
d_out(t.getOutputChannel()),
d_ee(nullptr),
d_pnm(pnm),
- d_keep(t.getSatContext())
+ d_keep(t.getSatContext()),
+ d_lemmasSent(t.getUserContext()),
+ d_numCurrentLemmas(0),
+ d_numCurrentFacts(0)
{
}
@@ -47,6 +50,12 @@ void TheoryInferenceManager::setEqualityEngine(eq::EqualityEngine* ee)
}
}
+void TheoryInferenceManager::reset()
+{
+ d_numCurrentLemmas = 0;
+ d_numCurrentFacts = 0;
+}
+
void TheoryInferenceManager::conflictEqConstantMerge(TNode a, TNode b)
{
if (!d_theoryState.isInConflict())
@@ -75,6 +84,27 @@ void TheoryInferenceManager::trustedConflict(TrustNode tconf)
}
}
+void TheoryInferenceManager::conflictExp(PfRule id,
+ const std::vector<Node>& exp,
+ const std::vector<Node>& args)
+{
+ if (!d_theoryState.isInConflict())
+ {
+ if (d_pfee != nullptr)
+ {
+ // use proof equality engine to construct the trust node
+ TrustNode tconf = d_pfee->assertConflict(id, exp, args);
+ d_out.trustedConflict(tconf);
+ }
+ else
+ {
+ // version without proofs
+ Node conf = mkExplainPartial(exp, {});
+ conflict(conf);
+ }
+ }
+}
+
bool TheoryInferenceManager::propagateLit(TNode lit)
{
// If already in conflict, no more propagation
@@ -114,7 +144,7 @@ TrustNode TheoryInferenceManager::explainConflictEqConstantMerge(TNode a,
Node lit = a.eqNode(b);
if (d_pfee != nullptr)
{
- return d_pfee->explain(lit);
+ return d_pfee->assertConflict(lit);
}
if (d_ee != nullptr)
{
@@ -125,42 +155,107 @@ TrustNode TheoryInferenceManager::explainConflictEqConstantMerge(TNode a,
<< " mkTrustedConflictEqConstantMerge";
}
-LemmaStatus TheoryInferenceManager::lemma(TNode lem, LemmaProperty p)
+bool TheoryInferenceManager::lemma(TNode lem, LemmaProperty p, bool doCache)
+{
+ TrustNode tlem = TrustNode::mkTrustLemma(lem, nullptr);
+ return trustedLemma(tlem, p, doCache);
+}
+
+bool TheoryInferenceManager::trustedLemma(const TrustNode& tlem,
+ LemmaProperty p,
+ bool doCache)
+{
+ if (doCache)
+ {
+ if (!cacheLemma(tlem.getNode(), p))
+ {
+ return false;
+ }
+ }
+ d_numCurrentLemmas++;
+ d_out.trustedLemma(tlem, p);
+ return true;
+}
+
+bool TheoryInferenceManager::lemmaExp(Node conc,
+ PfRule id,
+ const std::vector<Node>& exp,
+ const std::vector<Node>& noExplain,
+ const std::vector<Node>& args,
+ LemmaProperty p,
+ bool doCache)
+{
+ if (d_pfee != nullptr)
+ {
+ // make the trust node from the proof equality engine
+ TrustNode trn = d_pfee->assertLemma(conc, id, exp, noExplain, args);
+ return trustedLemma(trn, p, doCache);
+ }
+ // otherwise, not using proofs, explain and send lemma
+ Node ant = mkExplainPartial(exp, noExplain);
+ Node lem = NodeManager::currentNM()->mkNode(kind::IMPLIES, ant, conc);
+ return lemma(lem, p, doCache);
+}
+
+bool TheoryInferenceManager::lemmaExp(Node conc,
+ const std::vector<Node>& exp,
+ const std::vector<Node>& noExplain,
+ ProofGenerator* pg,
+ LemmaProperty p,
+ bool doCache)
{
- return d_out.lemma(lem, p);
+ if (d_pfee != nullptr)
+ {
+ // make the trust node from the proof equality engine
+ TrustNode trn = d_pfee->assertLemma(conc, exp, noExplain, pg);
+ return trustedLemma(trn, p, doCache);
+ }
+ // otherwise, not using proofs, explain and send lemma
+ Node ant = mkExplainPartial(exp, noExplain);
+ Node lem = NodeManager::currentNM()->mkNode(kind::IMPLIES, ant, conc);
+ return lemma(lem, p, doCache);
+}
+
+bool TheoryInferenceManager::hasCachedLemma(TNode lem, LemmaProperty p)
+{
+ return d_lemmasSent.find(lem) != d_lemmasSent.end();
+}
+
+uint32_t TheoryInferenceManager::numSentLemmas() const
+{
+ return d_numCurrentLemmas;
}
-LemmaStatus TheoryInferenceManager::trustedLemma(const TrustNode& tlem,
- LemmaProperty p)
+bool TheoryInferenceManager::hasSentLemma() const
{
- return d_out.trustedLemma(tlem, p);
+ return d_numCurrentLemmas != 0;
}
-void TheoryInferenceManager::assertInternalFact(TNode atom, bool pol, TNode exp)
+bool TheoryInferenceManager::assertInternalFact(TNode atom, bool pol, TNode exp)
{
- processInternalFact(atom, pol, PfRule::UNKNOWN, {exp}, {}, nullptr);
+ return processInternalFact(atom, pol, PfRule::UNKNOWN, {exp}, {}, nullptr);
}
-void TheoryInferenceManager::assertInternalFact(TNode atom,
+bool TheoryInferenceManager::assertInternalFact(TNode atom,
bool pol,
PfRule id,
const std::vector<Node>& exp,
const std::vector<Node>& args)
{
Assert(id != PfRule::UNKNOWN);
- processInternalFact(atom, pol, id, exp, args, nullptr);
+ return processInternalFact(atom, pol, id, exp, args, nullptr);
}
-void TheoryInferenceManager::assertInternalFact(TNode atom,
+bool TheoryInferenceManager::assertInternalFact(TNode atom,
bool pol,
const std::vector<Node>& exp,
ProofGenerator* pg)
{
Assert(pg != nullptr);
- processInternalFact(atom, pol, PfRule::ASSUME, exp, {}, pg);
+ return processInternalFact(atom, pol, PfRule::ASSUME, exp, {}, pg);
}
-void TheoryInferenceManager::processInternalFact(TNode atom,
+bool TheoryInferenceManager::processInternalFact(TNode atom,
bool pol,
PfRule id,
const std::vector<Node>& exp,
@@ -172,23 +267,26 @@ void TheoryInferenceManager::processInternalFact(TNode atom,
// call the pre-notify fact method with preReg = false, isInternal = true
if (d_theory.preNotifyFact(atom, pol, expn, false, true))
{
- // handled in a theory-specific way that doesn't require equality engine
- return;
+ // Handled in a theory-specific way that doesn't require equality engine,
+ // notice we return true, indicating that the fact was processed.
+ return true;
}
Assert(d_ee != nullptr);
Trace("infer-manager") << "TheoryInferenceManager::assertInternalFact: "
<< expn << std::endl;
+ d_numCurrentFacts++;
// Now, assert the fact. How to do so depends on whether proofs are enabled.
// If no proof production, or no proof rule was given
+ bool ret = false;
if (d_pfee == nullptr || id == PfRule::UNKNOWN)
{
if (atom.getKind() == kind::EQUAL)
{
- d_ee->assertEquality(atom, pol, expn);
+ ret = d_ee->assertEquality(atom, pol, expn);
}
else
{
- d_ee->assertPredicate(atom, pol, expn);
+ ret = d_ee->assertPredicate(atom, pol, expn);
}
// Must reference count the equality and its explanation, which is not done
// by the equality engine. Notice that we do *not* need to do this for
@@ -208,18 +306,19 @@ void TheoryInferenceManager::processInternalFact(TNode atom,
if (pg != nullptr)
{
// use the proof generator interface
- d_pfee->assertFact(lit, expn, pg);
+ ret = d_pfee->assertFact(lit, expn, pg);
}
else
{
// use the explict proof step interface
- d_pfee->assertFact(lit, id, expn, args);
+ ret = d_pfee->assertFact(lit, id, expn, args);
}
}
// call the notify fact method with isInternal = true
d_theory.notifyFact(atom, pol, expn, true);
Trace("infer-manager")
<< "TheoryInferenceManager::finished assertInternalFact" << std::endl;
+ return ret;
}
void TheoryInferenceManager::explain(TNode n, std::vector<TNode>& assumptions)
@@ -244,5 +343,51 @@ Node TheoryInferenceManager::mkExplain(TNode n)
return NodeManager::currentNM()->mkAnd(assumptions);
}
+Node TheoryInferenceManager::mkExplainPartial(
+ const std::vector<Node>& exp, const std::vector<Node>& noExplain)
+{
+ std::vector<TNode> assumps;
+ for (const Node& e : exp)
+ {
+ if (std::find(noExplain.begin(), noExplain.end(), e) != noExplain.end())
+ {
+ if (std::find(assumps.begin(), assumps.end(), e) == assumps.end())
+ {
+ // a non-explained literal
+ assumps.push_back(e);
+ }
+ continue;
+ }
+ // otherwise, explain it
+ explain(e, assumps);
+ }
+ return NodeManager::currentNM()->mkAnd(assumps);
+}
+
+uint32_t TheoryInferenceManager::numSentFacts() const
+{
+ return d_numCurrentFacts;
+}
+
+bool TheoryInferenceManager::hasSentFact() const
+{
+ return d_numCurrentFacts != 0;
+}
+
+bool TheoryInferenceManager::cacheLemma(TNode lem, LemmaProperty p)
+{
+ if (d_lemmasSent.find(lem) != d_lemmasSent.end())
+ {
+ return false;
+ }
+ d_lemmasSent.insert(lem);
+ return true;
+}
+
+void TheoryInferenceManager::requirePhase(TNode n, bool pol)
+{
+ return d_out.requirePhase(n, pol);
+}
+
} // namespace theory
} // namespace CVC4
diff --git a/src/theory/theory_inference_manager.h b/src/theory/theory_inference_manager.h
index af8e817b4..7e5ef6dec 100644
--- a/src/theory/theory_inference_manager.h
+++ b/src/theory/theory_inference_manager.h
@@ -71,13 +71,23 @@ class TheoryInferenceManager
*/
TheoryInferenceManager(Theory& t, TheoryState& state, ProofNodeManager* pnm);
virtual ~TheoryInferenceManager() {}
- //--------------------------------------- initialization
/**
* Set equality engine, ee is a pointer to the official equality engine
* of theory.
*/
void setEqualityEngine(eq::EqualityEngine* ee);
- //--------------------------------------- end initialization
+ /**
+ * Reset, which resets counters regarding the number of added lemmas and
+ * internal facts. This method should be manually called by the theory at
+ * the appropriate time for the purpose of tracking the usage of this
+ * inference manager.
+ *
+ * For example, some theories implement an internal checking loop that
+ * repeats while new facts are added. The theory should call reset at the
+ * beginning of this loop and repeat its strategy while hasAddedFact is true.
+ */
+ void reset();
+ //--------------------------------------- propagations
/**
* T-propagate literal lit, possibly encountered by equality engine,
* returns false if we are in conflict.
@@ -94,6 +104,7 @@ class TheoryInferenceManager
* Theory, if it exists.
*/
virtual TrustNode explainLit(TNode lit);
+ //--------------------------------------- conflicts
/**
* Raise conflict, called when constants a and b merge. Sends the conflict
* on the output channel corresponding to the equality engine's explanation
@@ -114,11 +125,99 @@ class TheoryInferenceManager
* been provided in a custom way.
*/
void trustedConflict(TrustNode tconf);
- /** Send lemma lem with property p on the output channel. */
- LemmaStatus lemma(TNode lem, LemmaProperty p = LemmaProperty::NONE);
- /** Send (trusted) lemma lem with property p on the output channel. */
- LemmaStatus trustedLemma(const TrustNode& tlem,
- LemmaProperty p = LemmaProperty::NONE);
+ /**
+ * Explain and send conflict from contradictory facts. This method is called
+ * when the proof rule id with premises exp and arguments args concludes
+ * false. This method sends a trusted conflict corresponding to the official
+ * equality engine's explanation of literals in exp, with the proof equality
+ * engine as the proof generator (if it exists).
+ */
+ void conflictExp(PfRule id,
+ const std::vector<Node>& exp,
+ const std::vector<Node>& args);
+ //--------------------------------------- lemmas
+ /**
+ * Send (trusted) lemma lem with property p on the output channel.
+ *
+ * @param tlem The trust node containing the lemma and its proof generator.
+ * @param p The property of the lemma
+ * @param doCache If true, we send the lemma only if it has not already been
+ * cached (see cacheLemma), and add it to the cache during this call.
+ * @return true if the lemma was sent on the output channel.
+ */
+ bool trustedLemma(const TrustNode& tlem,
+ LemmaProperty p = LemmaProperty::NONE,
+ bool doCache = true);
+ /**
+ * Send lemma lem with property p on the output channel. Same as above, with
+ * a node instead of a trust node.
+ */
+ bool lemma(TNode lem,
+ LemmaProperty p = LemmaProperty::NONE,
+ bool doCache = true);
+ /**
+ * Explained lemma. This should be called when
+ * ( exp => conc )
+ * is a valid theory lemma. This method adds a lemma where part of exp
+ * is replaced by its explanation according to the official equality engine
+ * of the theory.
+ *
+ * In particular, this method adds a lemma on the output channel of the form
+ * ( ^_{e in exp \ noExplain} EXPLAIN(e) ^ noExplain ) => conc
+ * where EXPLAIN(e) returns the explanation of literal e according to the
+ * official equality engine of the theory. Note that noExplain is the *subset*
+ * of exp that should not be explained.
+ *
+ * @param conc The conclusion of the lemma
+ * @param id The proof rule concluding conc
+ * @param exp The set of (all) literals that imply conc
+ * @param noExplain The subset of exp that should not be explained by the
+ * equality engine
+ * @param args The arguments to the proof step concluding conc
+ * @param p The property of the lemma
+ * @param doCache Whether to check and add the lemma to the cache
+ * @return true if the lemma was sent on the output channel.
+ */
+ bool lemmaExp(Node conc,
+ PfRule id,
+ const std::vector<Node>& exp,
+ const std::vector<Node>& noExplain,
+ const std::vector<Node>& args,
+ LemmaProperty p = LemmaProperty::NONE,
+ bool doCache = true);
+ /**
+ * Same as above, but where pg can provide a proof of conc from free
+ * assumptions in exp. It is required to do so in the remainder of the user
+ * context when this method returns true.
+ *
+ * @param conc The conclusion of the lemma
+ * @param exp The set of (all) literals that imply conc
+ * @param noExplain The subset of exp that should not be explained by the
+ * equality engine
+ * @param pg If non-null, the proof generator who can provide a proof of conc.
+ * @param p The property of the lemma
+ * @param doCache Whether to check and add the lemma to the cache
+ * @return true if the lemma was sent on the output channel.
+ */
+ bool lemmaExp(Node conc,
+ const std::vector<Node>& exp,
+ const std::vector<Node>& noExplain,
+ ProofGenerator* pg = nullptr,
+ LemmaProperty p = LemmaProperty::NONE,
+ bool doCache = true);
+ /**
+ * Has this inference manager cached and sent the given lemma (in this user
+ * context)? This method can be overridden by the particular manager. If not,
+ * this returns true if lem is in the cache d_lemmasSent maintained by this
+ * class. Notice that the default cache in this base class is not dependent
+ * on the lemma property.
+ */
+ virtual bool hasCachedLemma(TNode lem, LemmaProperty p);
+ /** The number of lemmas we have sent since the last call to reset */
+ uint32_t numSentLemmas() const;
+ /** Have we added a lemma since the last call to reset? */
+ bool hasSentLemma() const;
+ //--------------------------------------- internal facts
/**
* Assert internal fact. This is recommended method for asserting "internal"
* facts into the equality engine of the theory. In particular, this method
@@ -130,8 +229,10 @@ class TheoryInferenceManager
* @param atom The atom of the fact to assert
* @param pol Its polarity
* @param exp Its explanation, i.e. ( exp => (~) atom ) is valid.
+ * @return true if the fact was processed, i.e. it was asserted to the
+ * equality engine or preNotifyFact returned true.
*/
- void assertInternalFact(TNode atom, bool pol, TNode exp);
+ bool assertInternalFact(TNode atom, bool pol, TNode exp);
/**
* Assert internal fact, with a proof step justification. Notice that if
* proofs are not enabled in this inference manager, then this asserts
@@ -142,8 +243,10 @@ class TheoryInferenceManager
* @param id The proof rule identifier of the proof step
* @param exp Its explanation, interpreted as a conjunction
* @param args The arguments of the proof step
+ * @return true if the fact was processed, i.e. it was asserted to the
+ * equality engine or preNotifyFact returned true.
*/
- void assertInternalFact(TNode atom,
+ bool assertInternalFact(TNode atom,
bool pol,
PfRule id,
const std::vector<Node>& exp,
@@ -155,21 +258,32 @@ class TheoryInferenceManager
* @param atom The atom of the fact to assert
* @param pol Its polarity
* @param exp Its explanation, interpreted as a conjunction
- * @param pg The proof generator for this step. It must be the case that pf
- * can provide a proof concluding (~) atom from free asumptions in exp in
+ * @param pg The proof generator for this step. If non-null, pg must be able
+ * to provide a proof concluding (~) atom from free asumptions in exp in
* the remainder of the current SAT context.
+ * @return true if the fact was processed, i.e. it was asserted to the
+ * equality engine or preNotifyFact returned true.
*/
- void assertInternalFact(TNode atom,
+ bool assertInternalFact(TNode atom,
bool pol,
const std::vector<Node>& exp,
ProofGenerator* pg);
-
+ /** The number of internal facts we have added since the last call to reset */
+ uint32_t numSentFacts() const;
+ /** Have we added a internal fact since the last call to reset? */
+ bool hasSentFact() const;
+ //--------------------------------------- phase requirements
+ /**
+ * Set that literal n has SAT phase requirement pol, that is, it should be
+ * decided with polarity pol, for details see OutputChannel::requirePhase.
+ */
+ void requirePhase(TNode n, bool pol);
protected:
/**
* Process internal fact. This is a common helper method for the
- * assertInternalFact variants above.
+ * assertInternalFact variants above. Returns true if the fact was processed.
*/
- void processInternalFact(TNode atom,
+ bool processInternalFact(TNode atom,
bool pol,
PfRule id,
const std::vector<Node>& exp,
@@ -192,6 +306,23 @@ class TheoryInferenceManager
* conjunctions), return the explanation as a conjunction.
*/
Node mkExplain(TNode n);
+ /**
+ * Explain the set of formulas in exp using the official equality engine of
+ * the theory. We ask the equality engine to explain literals in exp
+ * that do not occur in noExplain, and return unchanged those that occur in
+ * noExplain. Note the vector noExplain should be a subset of exp.
+ */
+ Node mkExplainPartial(const std::vector<Node>& exp,
+ const std::vector<Node>& noExplain);
+ /**
+ * Cache that lemma lem is being sent with property p. Return true if it
+ * did not already exist in the cache maintained by this class. If this
+ * method is not overridden, then we use the d_lemmasSent cache maintained
+ * by this class, which notice is not dependent on lemma property. If
+ * the lemma property should be taken into account, the manager should
+ * override this method to take the lemma property into account as needed.
+ */
+ virtual bool cacheLemma(TNode lem, LemmaProperty p);
/** The theory object */
Theory& d_theory;
/** Reference to the state of theory */
@@ -211,6 +342,15 @@ class TheoryInferenceManager
* SAT-context-dependent.
*/
NodeSet d_keep;
+ /**
+ * A cache of all lemmas sent, which is a user-context-dependent set of
+ * nodes. Notice that this cache does not depedent on lemma property.
+ */
+ NodeSet d_lemmasSent;
+ /** The number of lemmas sent since the last call to reset. */
+ uint32_t d_numCurrentLemmas;
+ /** The number of internal facts added since the last call to reset. */
+ uint32_t d_numCurrentFacts;
};
} // namespace theory
diff --git a/src/theory/theory_test_utils.h b/src/theory/theory_test_utils.h
index 2593b11a6..965e99338 100644
--- a/src/theory/theory_test_utils.h
+++ b/src/theory/theory_test_utils.h
@@ -27,7 +27,6 @@
#include "expr/node.h"
#include "theory/interrupted.h"
#include "theory/output_channel.h"
-#include "util/proof.h"
#include "util/resource_manager.h"
#include "util/unsafe_interrupt_exception.h"
@@ -69,17 +68,14 @@ public:
~TestOutputChannel() override {}
void safePoint(ResourceManager::Resource r) override {}
- void conflict(TNode n, std::unique_ptr<Proof> pf) override
- {
- push(CONFLICT, n);
- }
+ void conflict(TNode n) override { push(CONFLICT, n); }
bool propagate(TNode n) override {
push(PROPAGATE, n);
return true;
}
- LemmaStatus lemma(TNode n, ProofRule rule, LemmaProperty p) override
+ LemmaStatus lemma(TNode n, LemmaProperty p) override
{
push(LEMMA, n);
return LemmaStatus(Node::null(), 0);
diff --git a/src/theory/theory_traits_template.h b/src/theory/theory_traits_template.h
index 775f42a46..d591affba 100644
--- a/src/theory/theory_traits_template.h
+++ b/src/theory/theory_traits_template.h
@@ -34,8 +34,6 @@ struct TheoryTraits;
${theory_traits}
-#line 38 "${template}"
-
struct TheoryConstructor {
static void addTheory(TheoryEngine* engine, TheoryId id) {
switch(id) {
diff --git a/src/theory/type_enumerator_template.cpp b/src/theory/type_enumerator_template.cpp
index e9fdc6a86..47405f74e 100644
--- a/src/theory/type_enumerator_template.cpp
+++ b/src/theory/type_enumerator_template.cpp
@@ -22,7 +22,6 @@
${type_enumerator_includes}
-#line 26 "${template}"
using namespace std;
@@ -42,7 +41,6 @@ TypeEnumeratorInterface* TypeEnumerator::mkTypeEnumerator(
}
Unreachable();
${mk_type_enumerator_cases}
-#line 46 "${template}"
default: Unhandled() << "No type enumerator for type `" << type << "'";
}
Unreachable();
diff --git a/src/theory/uf/eq_proof.cpp b/src/theory/uf/eq_proof.cpp
index 513cf2f39..d7b615ffa 100644
--- a/src/theory/uf/eq_proof.cpp
+++ b/src/theory/uf/eq_proof.cpp
@@ -21,33 +21,20 @@ namespace CVC4 {
namespace theory {
namespace eq {
-void EqProof::debug_print(const char* c,
- unsigned tb,
- PrettyPrinter* prettyPrinter) const
+void EqProof::debug_print(const char* c, unsigned tb) const
{
std::stringstream ss;
- debug_print(ss, tb, prettyPrinter);
+ debug_print(ss, tb);
Debug(c) << ss.str();
}
-void EqProof::debug_print(std::ostream& os,
- unsigned tb,
- PrettyPrinter* prettyPrinter) const
+void EqProof::debug_print(std::ostream& os, unsigned tb) const
{
for (unsigned i = 0; i < tb; i++)
{
os << " ";
}
-
- if (prettyPrinter)
- {
- os << prettyPrinter->printTag(d_id);
- }
- else
- {
- os << static_cast<MergeReasonType>(d_id);
- }
- os << "(";
+ os << d_id << "(";
if (d_children.empty() && d_node.isNull())
{
os << ")";
@@ -66,7 +53,7 @@ void EqProof::debug_print(std::ostream& os,
for (unsigned i = 0; i < size; ++i)
{
os << std::endl;
- d_children[i]->debug_print(os, tb + 1, prettyPrinter);
+ d_children[i]->debug_print(os, tb + 1);
if (i < size - 1)
{
for (unsigned j = 0; j < tb + 1; ++j)
@@ -850,8 +837,7 @@ Node EqProof::addToProof(
<< ", returning " << it->second << "\n";
return it->second;
}
- Trace("eqproof-conv") << "EqProof::addToProof: adding step for "
- << static_cast<MergeReasonType>(d_id)
+ Trace("eqproof-conv") << "EqProof::addToProof: adding step for " << d_id
<< " with conclusion " << d_node << "\n";
// Assumption
if (d_id == MERGED_THROUGH_EQUALITY)
@@ -976,12 +962,10 @@ Node EqProof::addToProof(
{
Assert(!d_node.isNull() && d_node.getKind() == kind::EQUAL
&& d_node[1].isConst())
- << ". Conclusion " << d_node << " from "
- << static_cast<MergeReasonType>(d_id)
+ << ". Conclusion " << d_node << " from " << d_id
<< " was expected to be (= (f t1 ... tn) c)\n";
Assert(!assumptions.count(d_node))
- << "Conclusion " << d_node << " from "
- << static_cast<MergeReasonType>(d_id) << " is an assumption\n";
+ << "Conclusion " << d_node << " from " << d_id << " is an assumption\n";
// The step has the form
// [(= t1 c1)] ... [(= tn cn)]
// ------------------------
diff --git a/src/theory/uf/eq_proof.h b/src/theory/uf/eq_proof.h
index 492252baa..72368c8c9 100644
--- a/src/theory/uf/eq_proof.h
+++ b/src/theory/uf/eq_proof.h
@@ -35,36 +35,21 @@ namespace eq {
class EqProof
{
public:
- /** A custom pretty printer used for custom rules being those in
- * MergeReasonType. */
- class PrettyPrinter
- {
- public:
- virtual ~PrettyPrinter() {}
- virtual std::string printTag(unsigned tag) = 0;
- };
-
EqProof() : d_id(MERGED_THROUGH_REFLEXIVITY) {}
/** The proof rule for concluding d_node */
- unsigned d_id;
+ MergeReasonType d_id;
/** The conclusion of this EqProof */
Node d_node;
/** The proofs of the premises for deriving d_node with d_id */
std::vector<std::shared_ptr<EqProof>> d_children;
/**
- * Debug print this proof on debug trace c with tabulation tb and pretty
- * printer prettyPrinter.
+ * Debug print this proof on debug trace c with tabulation tb.
*/
- void debug_print(const char* c,
- unsigned tb = 0,
- PrettyPrinter* prettyPrinter = nullptr) const;
+ void debug_print(const char* c, unsigned tb = 0) const;
/**
- * Debug print this proof on output stream os with tabulation tb and pretty
- * printer prettyPrinter.
+ * Debug print this proof on output stream os with tabulation tb.
*/
- void debug_print(std::ostream& os,
- unsigned tb = 0,
- PrettyPrinter* prettyPrinter = nullptr) const;
+ void debug_print(std::ostream& os, unsigned tb = 0) const;
/** Add to proof
*
diff --git a/src/theory/uf/equality_engine.cpp b/src/theory/uf/equality_engine.cpp
index dd142edf4..c97c99776 100644
--- a/src/theory/uf/equality_engine.cpp
+++ b/src/theory/uf/equality_engine.cpp
@@ -103,8 +103,6 @@ void EqualityEngine::init() {
d_trueId = getNodeId(d_true);
d_falseId = getNodeId(d_false);
-
- d_freshMergeReasonType = eq::NUMBER_OF_MERGE_REASONS;
}
EqualityEngine::~EqualityEngine() {
@@ -1100,7 +1098,7 @@ void EqualityEngine::explainEquality(TNode t1, TNode t2, bool polarity,
getExplanation(t1Id, t2Id, equalities, cache, eqp);
} else {
if (eqp) {
- eqp->d_id = eq::MERGED_THROUGH_TRANS;
+ eqp->d_id = MERGED_THROUGH_TRANS;
eqp->d_node = d_nodes[t1Id].eqNode(d_nodes[t2Id]).notNode();
}
@@ -1137,12 +1135,13 @@ void EqualityEngine::explainEquality(TNode t1, TNode t2, bool polarity,
Debug("pf::ee") << "Child proof is:" << std::endl;
eqpc->debug_print("pf::ee", 1);
}
- if (eqpc->d_id == eq::MERGED_THROUGH_TRANS) {
+ if (eqpc->d_id == MERGED_THROUGH_TRANS)
+ {
std::vector<std::shared_ptr<EqProof>> orderedChildren;
bool nullCongruenceFound = false;
for (const auto& child : eqpc->d_children)
{
- if (child->d_id == eq::MERGED_THROUGH_CONGRUENCE
+ if (child->d_id == MERGED_THROUGH_CONGRUENCE
&& child->d_node.isNull())
{
nullCongruenceFound = true;
@@ -1382,35 +1381,24 @@ void EqualityEngine::getExplanation(
#endif
// If the nodes are the same, we're done
- if (t1Id == t2Id){
- if( eqp ) {
- if (options::proofNew())
- {
- // ignore equalities between function symbols, i.e. internal nullary
- // non-constant nodes.
- //
- // Note that this is robust for HOL because in that case function
- // symbols are not internal nodes
- if (d_isInternal[t1Id] && d_nodes[t1Id].getNumChildren() == 0
- && !d_isConstant[t1Id])
- {
- eqp->d_node = Node::null();
- }
- else
- {
- Assert(d_nodes[t1Id].getKind() != kind::BUILTIN);
- eqp->d_node = d_nodes[t1Id].eqNode(d_nodes[t1Id]);
- }
- }
- else if ((d_nodes[t1Id].getKind() == kind::BUILTIN)
- && (d_nodes[t1Id].getConst<Kind>() == kind::SELECT))
+ if (t1Id == t2Id)
+ {
+ if (eqp)
+ {
+ // ignore equalities between function symbols, i.e. internal nullary
+ // non-constant nodes.
+ //
+ // Note that this is robust for HOL because in that case function
+ // symbols are not internal nodes
+ if (d_isInternal[t1Id] && d_nodes[t1Id].getNumChildren() == 0
+ && !d_isConstant[t1Id])
{
- std::vector<Node> no_children;
- eqp->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_SELECT_0, no_children);
+ eqp->d_node = Node::null();
}
else
{
- eqp->d_node = ProofManager::currentPM()->mkOp(d_nodes[t1Id]);
+ Assert(d_nodes[t1Id].getKind() != kind::BUILTIN);
+ eqp->d_node = d_nodes[t1Id].eqNode(d_nodes[t1Id]);
}
}
return;
@@ -1466,7 +1454,8 @@ void EqualityEngine::getExplanation(
// The current node
currentNode = bfsQueue[currentIndex].d_nodeId;
EqualityNodeId edgeNode = d_equalityEdges[currentEdge].getNodeId();
- unsigned reasonType = d_equalityEdges[currentEdge].getReasonType();
+ MergeReasonType reasonType = static_cast<MergeReasonType>(
+ d_equalityEdges[currentEdge].getReasonType());
Node reason = d_equalityEdges[currentEdge].getReason();
Debug("equality")
@@ -1482,8 +1471,9 @@ void EqualityEngine::getExplanation(
<< edge.getNodeId() << "} " << d_nodes[edge.getNodeId()] << ")"
<< std::endl;
Debug("equality")
- << d_name << " reason type = "
- << static_cast<MergeReasonType>(reasonType) << std::endl;
+ << d_name
+ << " reason type = " << reasonType
+ << "\n";
std::shared_ptr<EqProof> eqpc;;
// Make child proof if a proof is being constructed
@@ -1518,63 +1508,21 @@ void EqualityEngine::getExplanation(
{
eqpc->d_children.push_back(eqpc1);
eqpc->d_children.push_back(eqpc2);
- if (options::proofNew())
+ // build conclusion if ids correspond to non-internal nodes or
+ // if non-internal nodes can be retrieved from them (in the
+ // case of n-ary applications), otherwise leave conclusion as
+ // null. This is only done for congruence kinds, since
+ // congruence is not used otherwise.
+ Kind k = d_nodes[currentNode].getKind();
+ if (d_congruenceKinds[k])
{
- // build conclusion if ids correspond to non-internal nodes or
- // if non-internal nodes can be retrieved from them (in the
- // case of n-ary applications), otherwise leave conclusion as
- // null. This is only done for congruence kinds, since
- // congruence is not used otherwise.
- Kind k = d_nodes[currentNode].getKind();
- if (d_congruenceKinds[k])
- {
- buildEqConclusion(currentNode, edgeNode, eqpc.get());
- }
- else
- {
- Assert(k == kind::EQUAL)
- << "not an internal node " << d_nodes[currentNode]
- << " with non-congruence with " << k << "\n";
- }
- }
- else if (d_nodes[currentNode].getKind() == kind::EQUAL)
- {
- //leave node null for now
- eqpc->d_node = Node::null();
+ buildEqConclusion(currentNode, edgeNode, eqpc.get());
}
else
{
- if (d_nodes[f1.d_a].getKind() == kind::APPLY_UF
- || d_nodes[f1.d_a].getKind() == kind::SELECT
- || d_nodes[f1.d_a].getKind() == kind::STORE)
- {
- eqpc->d_node = d_nodes[f1.d_a];
- }
- else
- {
- if (d_nodes[f1.d_a].getKind() == kind::BUILTIN
- && d_nodes[f1.d_a].getConst<Kind>() == kind::SELECT)
- {
- eqpc->d_node = NodeManager::currentNM()->mkNode(
- kind::PARTIAL_SELECT_1, d_nodes[f1.d_b]);
- // The first child is a PARTIAL_SELECT_0.
- // Give it a child so that we know what kind of (read) it is, when we dump to LFSC.
- Assert(eqpc->d_children[0]->d_node.getKind()
- == kind::PARTIAL_SELECT_0);
- Assert(eqpc->d_children[0]->d_children.size() == 0);
-
- eqpc->d_children[0]->d_node =
- NodeManager::currentNM()->mkNode(
- kind::PARTIAL_SELECT_0, d_nodes[f1.d_b]);
- }
- else
- {
- eqpc->d_node = NodeManager::currentNM()->mkNode(
- kind::PARTIAL_APPLY_UF,
- ProofManager::currentPM()->mkOp(d_nodes[f1.d_a]),
- d_nodes[f1.d_b]);
- }
- }
+ Assert(k == kind::EQUAL)
+ << "not an internal node " << d_nodes[currentNode]
+ << " with non-congruence with " << k << "\n";
}
}
Debug("equality") << pop;
@@ -1608,7 +1556,7 @@ void EqualityEngine::getExplanation(
// Get the node we interpreted
TNode interpreted;
- if (eqpc && options::proofNew())
+ if (eqpc)
{
// build the conclusion f(c1, ..., cn) = c
if (d_nodes[currentNode].isConst())
@@ -1661,24 +1609,19 @@ void EqualityEngine::getExplanation(
Debug("equality") << d_name << "::eq::getExplanation(): adding: "
<< reason << std::endl;
Debug("equality")
- << d_name << "::eq::getExplanation(): reason type = "
- << static_cast<MergeReasonType>(reasonType) << std::endl;
+ << d_name
+ << "::eq::getExplanation(): reason type = " << reasonType
+ << "\n";
Node a = d_nodes[currentNode];
Node b = d_nodes[d_equalityEdges[currentEdge].getNodeId()];
if (eqpc) {
- //apply proof reconstruction processing (when eqpc is non-null)
- if (d_pathReconstructionTriggers.find(reasonType) != d_pathReconstructionTriggers.end()) {
- d_pathReconstructionTriggers.find(reasonType)
- ->second->notify(reasonType, reason, a, b, equalities,
- eqpc.get());
- }
if (reasonType == MERGED_THROUGH_EQUALITY) {
// in the new proof infrastructure we can assume that "theory
// assumptions", which are a consequence of theory reasoning
// on other assumptions, are externally justified. In this
// case we can use (= a b) directly as the conclusion here.
- eqpc->d_node = !options::proofNew() ? reason : b.eqNode(a);
+ eqpc->d_node = b.eqNode(a);
} else {
// The LFSC translator prefers (not (= a b)) over (= (= a b) false)
@@ -1722,20 +1665,12 @@ void EqualityEngine::getExplanation(
} else {
eqp->d_id = MERGED_THROUGH_TRANS;
eqp->d_children.insert( eqp->d_children.end(), eqp_trans.begin(), eqp_trans.end() );
- if (options::proofNew())
- {
- // build conclusion in case of equality between non-internal
- // nodes or of n-ary congruence kinds, otherwise leave as
- // null. The latter is necessary for the overall handling of
- // congruence proofs involving n-ary kinds, see
- // EqProof::reduceNestedCongruence for more details.
- buildEqConclusion(t1Id, t2Id, eqp);
- }
- else
- {
- eqp->d_node = NodeManager::currentNM()->mkNode(
- kind::EQUAL, d_nodes[t1Id], d_nodes[t2Id]);
- }
+ // build conclusion in case of equality between non-internal
+ // nodes or of n-ary congruence kinds, otherwise leave as
+ // null. The latter is necessary for the overall handling of
+ // congruence proofs involving n-ary kinds, see
+ // EqProof::reduceNestedCongruence for more details.
+ buildEqConclusion(t1Id, t2Id, eqp);
}
if (Debug.isOn("pf::ee"))
{
@@ -2218,18 +2153,6 @@ size_t EqualityEngine::getSize(TNode t) {
return getEqualityNode(getEqualityNode(t).getFind()).getSize();
}
-
-void EqualityEngine::addPathReconstructionTrigger(unsigned trigger, const PathReconstructionNotify* notify) {
- // Currently we can only inform one callback per trigger
- Assert(d_pathReconstructionTriggers.find(trigger)
- == d_pathReconstructionTriggers.end());
- d_pathReconstructionTriggers[trigger] = notify;
-}
-
-unsigned EqualityEngine::getFreshMergeReasonType() {
- return d_freshMergeReasonType++;
-}
-
std::string EqualityEngine::identify() const { return d_name; }
void EqualityEngine::addTriggerTerm(TNode t, TheoryId tag)
diff --git a/src/theory/uf/equality_engine.h b/src/theory/uf/equality_engine.h
index 19a10eba8..f8444965f 100644
--- a/src/theory/uf/equality_engine.h
+++ b/src/theory/uf/equality_engine.h
@@ -43,26 +43,10 @@ namespace CVC4 {
namespace theory {
namespace eq {
-
-class EqProof;
class EqClassesIterator;
class EqClassIterator;
/**
- * An interface for equality engine notifications during equality path reconstruction.
- * Can be used to add theory-specific logic for, e.g., proof construction.
- */
-class PathReconstructionNotify {
-public:
-
- virtual ~PathReconstructionNotify() {}
-
- virtual void notify(unsigned reasonType, Node reason, Node a, Node b,
- std::vector<TNode>& equalities,
- EqProof* proof) const = 0;
-};
-
-/**
* Class for keeping an incremental congruence closure over a set of terms. It provides
* notifications via an EqualityEngineNotify object.
*/
@@ -152,9 +136,6 @@ private:
/** The map of kinds with operators to be considered external (for higher-order) */
KindMap d_congruenceKindsExtOperators;
- /** Objects that need to be notified during equality path reconstruction */
- std::map<unsigned, const PathReconstructionNotify*> d_pathReconstructionTriggers;
-
/** Map from nodes to their ids */
std::unordered_map<TNode, EqualityNodeId, TNodeHashFunction> d_nodeIds;
@@ -196,9 +177,6 @@ private:
/** Memory for the use-list nodes */
std::vector<UseListNode> d_useListNodes;
- /** A fresh merge reason type to return upon request */
- unsigned d_freshMergeReasonType;
-
/**
* We keep a list of asserted equalities. Not among original terms, but
* among the class representatives.
@@ -861,16 +839,6 @@ private:
*/
bool consistent() const { return !d_done; }
- /**
- * Marks an object for merge type based notification during equality path reconstruction.
- */
- void addPathReconstructionTrigger(unsigned trigger, const PathReconstructionNotify* notify);
-
- /**
- * Returns a fresh merge reason type tag for the client to use.
- */
- unsigned getFreshMergeReasonType();
-
/** Identify this equality engine (for debugging, etc..) */
std::string identify() const;
};
diff --git a/src/theory/uf/equality_engine_types.h b/src/theory/uf/equality_engine_types.h
index 14cd80436..cceffa51d 100644
--- a/src/theory/uf/equality_engine_types.h
+++ b/src/theory/uf/equality_engine_types.h
@@ -63,20 +63,26 @@ static const EqualityEdgeId null_edge = (EqualityEdgeId)(-1);
* or a merge of an equality to false due to both sides being
* (different) constants.
*/
-enum MergeReasonType {
- /** Terms were merged due to application of congruence closure */
+enum MergeReasonType
+{
+ /** Terms were merged due to congruence */
MERGED_THROUGH_CONGRUENCE,
- /** Terms were merged due to application of pure equality */
+ /** Terms were merged due to an assumption */
MERGED_THROUGH_EQUALITY,
- /** Equality was merged to true, due to both sides of equality being in the same class */
+ /** Terms were merged due to reflexivity */
MERGED_THROUGH_REFLEXIVITY,
- /** Equality was merged to false, due to both sides of equality being a constant */
+ /** Terms were merged due to theory reasoning */
MERGED_THROUGH_CONSTANTS,
- /** (for proofs only) Equality was merged due to transitivity */
+ /** Terms were merged due to transitivity */
MERGED_THROUGH_TRANS,
-
- /** Reason types beyond this constant are theory specific reasons */
- NUMBER_OF_MERGE_REASONS
+ // TEMPORARY RULES WHILE WE DON'T MIGRATE TO PROOF_NEW
+
+ /** Terms were merged due to arrays read-over-write */
+ MERGED_THROUGH_ROW,
+ /** Terms were merged due to arrays read-over-write (1) */
+ MERGED_THROUGH_ROW1,
+ /** Terms were merged due to extensionality */
+ MERGED_THROUGH_EXT,
};
inline std::ostream& operator << (std::ostream& out, MergeReasonType reason) {
@@ -90,13 +96,13 @@ inline std::ostream& operator << (std::ostream& out, MergeReasonType reason) {
case MERGED_THROUGH_REFLEXIVITY:
out << "reflexivity";
break;
- case MERGED_THROUGH_CONSTANTS:
- out << "constants disequal";
- break;
+ case MERGED_THROUGH_CONSTANTS: out << "theory constants"; break;
case MERGED_THROUGH_TRANS:
out << "transitivity";
break;
-
+ case MERGED_THROUGH_ROW: out << "read-over-write"; break;
+ case MERGED_THROUGH_ROW1: out << "read-over-write (1)"; break;
+ case MERGED_THROUGH_EXT: out << "extensionality"; break;
default:
out << "[theory]";
break;
diff --git a/src/theory/uf/ho_extension.cpp b/src/theory/uf/ho_extension.cpp
index 11b872e72..2a57cde5e 100644
--- a/src/theory/uf/ho_extension.cpp
+++ b/src/theory/uf/ho_extension.cpp
@@ -18,7 +18,6 @@
#include "expr/node_algorithm.h"
#include "options/uf_options.h"
#include "theory/theory_model.h"
-#include "theory/uf/theory_uf.h"
#include "theory/uf/theory_uf_rewriter.h"
using namespace std;
@@ -28,9 +27,9 @@ namespace CVC4 {
namespace theory {
namespace uf {
-HoExtension::HoExtension(TheoryUF& p, TheoryState& state)
- : d_parent(p),
- d_state(state),
+HoExtension::HoExtension(TheoryState& state, TheoryInferenceManager& im)
+ : d_state(state),
+ d_im(im),
d_extensionality(state.getUserContext()),
d_uf_std_skolem(state.getUserContext())
{
@@ -108,7 +107,7 @@ unsigned HoExtension::applyExtensionality(TNode deq)
Node lem = NodeManager::currentNM()->mkNode(OR, deq[0], conc);
Trace("uf-ho-lemma") << "uf-ho-lemma : extensionality : " << lem
<< std::endl;
- d_parent.getOutputChannel().lemma(lem);
+ d_im.lemma(lem);
return 1;
}
return 0;
@@ -168,7 +167,7 @@ Node HoExtension::getApplyUfForHoApply(Node node)
Trace("uf-ho-lemma")
<< "uf-ho-lemma : Skolem definition for apply-conversion : " << lem
<< std::endl;
- d_parent.getOutputChannel().lemma(lem);
+ d_im.lemma(lem);
d_uf_std_skolem[f] = new_f;
}
else
@@ -257,7 +256,7 @@ unsigned HoExtension::checkExtensionality(TheoryModel* m)
Node lem = nm->mkNode(OR, deq.negate(), eq);
Trace("uf-ho") << "HoExtension: cmi extensionality lemma " << lem
<< std::endl;
- d_parent.getOutputChannel().lemma(lem);
+ d_im.lemma(lem);
return 1;
}
}
@@ -282,10 +281,10 @@ unsigned HoExtension::applyAppCompletion(TNode n)
Node ret = TheoryUfRewriter::getHoApplyForApplyUf(n);
if (!ee->hasTerm(ret) || !ee->areEqual(ret, n))
{
- Node eq = ret.eqNode(n);
+ Node eq = n.eqNode(ret);
Trace("uf-ho-lemma") << "uf-ho-lemma : infer, by apply-expand : " << eq
<< std::endl;
- ee->assertEquality(eq, true, d_true);
+ d_im.assertInternalFact(eq, true, PfRule::HO_APP_ENCODE, {}, {n});
return 1;
}
Trace("uf-ho-debug") << " ...already have " << ret << " == " << n << "."
@@ -442,7 +441,7 @@ bool HoExtension::collectModelInfoHoTerm(Node n, TheoryModel* m)
Node eq = n.eqNode(hn);
Trace("uf-ho") << "HoExtension: cmi app completion lemma " << eq
<< std::endl;
- d_parent.getOutputChannel().lemma(eq);
+ d_im.lemma(eq);
return false;
}
}
diff --git a/src/theory/uf/ho_extension.h b/src/theory/uf/ho_extension.h
index 25cb3623b..ceb8e9c12 100644
--- a/src/theory/uf/ho_extension.h
+++ b/src/theory/uf/ho_extension.h
@@ -21,6 +21,7 @@
#include "context/cdhashset.h"
#include "context/cdo.h"
#include "expr/node.h"
+#include "theory/theory_inference_manager.h"
#include "theory/theory_model.h"
#include "theory/theory_state.h"
@@ -51,7 +52,7 @@ class HoExtension
typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap;
public:
- HoExtension(TheoryUF& p, TheoryState& state);
+ HoExtension(TheoryState& state, TheoryInferenceManager& im);
/** expand definition
*
@@ -181,10 +182,10 @@ class HoExtension
private:
/** common constants */
Node d_true;
- /** the parent of this extension */
- TheoryUF& d_parent;
/** Reference to the state object */
TheoryState& d_state;
+ /** Reference to the inference manager */
+ TheoryInferenceManager& d_im;
/** extensionality has been applied to these disequalities */
NodeSet d_extensionality;
diff --git a/src/theory/uf/proof_checker.cpp b/src/theory/uf/proof_checker.cpp
index b010b6d17..ea95c1f24 100644
--- a/src/theory/uf/proof_checker.cpp
+++ b/src/theory/uf/proof_checker.cpp
@@ -14,6 +14,8 @@
#include "theory/uf/proof_checker.h"
+#include "theory/uf/theory_uf_rewriter.h"
+
using namespace CVC4::kind;
namespace CVC4 {
@@ -31,6 +33,8 @@ void UfProofRuleChecker::registerTo(ProofChecker* pc)
pc->registerChecker(PfRule::TRUE_ELIM, this);
pc->registerChecker(PfRule::FALSE_INTRO, this);
pc->registerChecker(PfRule::FALSE_ELIM, this);
+ pc->registerChecker(PfRule::HO_CONG, this);
+ pc->registerChecker(PfRule::HO_APP_ENCODE, this);
}
Node UfProofRuleChecker::checkInternal(PfRule id,
@@ -171,6 +175,32 @@ Node UfProofRuleChecker::checkInternal(PfRule id,
}
return children[0][0].notNode();
}
+ if (id == PfRule::HO_CONG)
+ {
+ Assert(children.size() > 0);
+ std::vector<Node> lchildren;
+ std::vector<Node> rchildren;
+ for (size_t i = 0, nchild = children.size(); i < nchild; ++i)
+ {
+ Node eqp = children[i];
+ if (eqp.getKind() != EQUAL)
+ {
+ return Node::null();
+ }
+ lchildren.push_back(eqp[0]);
+ rchildren.push_back(eqp[1]);
+ }
+ NodeManager* nm = NodeManager::currentNM();
+ Node l = nm->mkNode(kind::APPLY_UF, lchildren);
+ Node r = nm->mkNode(kind::APPLY_UF, rchildren);
+ return l.eqNode(r);
+ }
+ else if (id == PfRule::HO_APP_ENCODE)
+ {
+ Assert(args.size() == 1);
+ Node ret = TheoryUfRewriter::getHoApplyForApplyUf(args[0]);
+ return args[0].eqNode(ret);
+ }
// no rule
return Node::null();
}
diff --git a/src/theory/uf/theory_uf.cpp b/src/theory/uf/theory_uf.cpp
index f94cc36af..a58834891 100644
--- a/src/theory/uf/theory_uf.cpp
+++ b/src/theory/uf/theory_uf.cpp
@@ -25,9 +25,6 @@
#include "options/smt_options.h"
#include "options/theory_options.h"
#include "options/uf_options.h"
-#include "proof/proof_manager.h"
-#include "proof/theory_proof.h"
-#include "proof/uf_proof.h"
#include "theory/theory_model.h"
#include "theory/type_enumerator.h"
#include "theory/uf/cardinality_extension.h"
@@ -56,7 +53,8 @@ TheoryUF::TheoryUF(context::Context* c,
d_ho(nullptr),
d_functionsTerms(c),
d_symb(u, instanceName),
- d_state(c, u, valuation)
+ d_state(c, u, valuation),
+ d_im(*this, d_state, pnm)
{
d_true = NodeManager::currentNM()->mkConst( true );
@@ -65,8 +63,9 @@ TheoryUF::TheoryUF(context::Context* c,
{
d_ufProofChecker.registerTo(pc);
}
- // indicate we are using the default theory state object
+ // indicate we are using the default theory state and inference managers
d_theoryState = &d_state;
+ d_inferManager = &d_im;
}
TheoryUF::~TheoryUF() {
@@ -99,7 +98,7 @@ void TheoryUF::finishInit() {
if (options::ufHo())
{
d_equalityEngine->addFunctionKind(kind::HO_APPLY);
- d_ho.reset(new HoExtension(*this, d_state));
+ d_ho.reset(new HoExtension(d_state, d_im));
}
}
@@ -288,40 +287,26 @@ bool TheoryUF::propagateLit(TNode literal)
return ok;
}/* TheoryUF::propagate(TNode) */
-void TheoryUF::explain(TNode literal, std::vector<TNode>& assumptions, eq::EqProof* pf) {
+void TheoryUF::explain(TNode literal, Node& exp)
+{
+ Debug("uf") << "TheoryUF::explain(" << literal << ")" << std::endl;
+ std::vector<TNode> assumptions;
// Do the work
bool polarity = literal.getKind() != kind::NOT;
TNode atom = polarity ? literal : literal[0];
- if (atom.getKind() == kind::EQUAL) {
+ if (atom.getKind() == kind::EQUAL)
+ {
d_equalityEngine->explainEquality(
- atom[0], atom[1], polarity, assumptions, pf);
- } else {
- d_equalityEngine->explainPredicate(atom, polarity, assumptions, pf);
+ atom[0], atom[1], polarity, assumptions, nullptr);
}
- if( pf ){
- Debug("pf::uf") << std::endl;
- pf->debug_print("pf::uf");
- }
-
- Debug("pf::uf") << "UF: explain( " << literal << " ):" << std::endl << "\t";
- for (unsigned i = 0; i < assumptions.size(); ++i) {
- Debug("pf::uf") << assumptions[i] << " ";
+ else
+ {
+ d_equalityEngine->explainPredicate(atom, polarity, assumptions, nullptr);
}
- Debug("pf::uf") << std::endl;
+ exp = mkAnd(assumptions);
}
-TrustNode TheoryUF::explain(TNode literal)
-{
- Node exp = explain(literal, NULL);
- return TrustNode::mkTrustPropExp(literal, exp, nullptr);
-}
-
-Node TheoryUF::explain(TNode literal, eq::EqProof* pf) {
- Debug("uf") << "TheoryUF::explain(" << literal << ")" << std::endl;
- std::vector<TNode> assumptions;
- explain(literal, assumptions, pf);
- return mkAnd(assumptions);
-}
+TrustNode TheoryUF::explain(TNode literal) { return d_im.explainLit(literal); }
bool TheoryUF::collectModelValues(TheoryModel* m, const std::set<Node>& termSet)
{
@@ -350,7 +335,8 @@ void TheoryUF::presolve() {
i != newClauses.end();
++i) {
Debug("uf") << "uf: generating a lemma: " << *i << std::endl;
- d_out->lemma(*i);
+ // no proof generator provided
+ d_im.lemma(*i);
}
}
if( d_thss ){
@@ -662,13 +648,12 @@ void TheoryUF::computeCareGraph() {
<< std::endl;
}/* TheoryUF::computeCareGraph() */
-void TheoryUF::conflict(TNode a, TNode b) {
- std::shared_ptr<eq::EqProof> pf =
- d_proofsEnabled ? std::make_shared<eq::EqProof>() : nullptr;
- Node conf = explain(a.eqNode(b), pf.get());
- std::unique_ptr<ProofUF> puf(d_proofsEnabled ? new ProofUF(pf) : nullptr);
- d_out->conflict(conf, std::move(puf));
- d_state.notifyInConflict();
+void TheoryUF::conflict(TNode a, TNode b)
+{
+ // call the inference manager, which will construct the conflict (possibly
+ // with proofs from the underlying proof equality engine), and notify the
+ // state object.
+ d_im.conflictEqConstantMerge(a, b);
}
void TheoryUF::eqNotifyNewClass(TNode t) {
diff --git a/src/theory/uf/theory_uf.h b/src/theory/uf/theory_uf.h
index 2bfd7e16c..4a8369483 100644
--- a/src/theory/uf/theory_uf.h
+++ b/src/theory/uf/theory_uf.h
@@ -26,6 +26,7 @@
#include "theory/theory.h"
#include "theory/uf/equality_engine.h"
#include "theory/uf/proof_checker.h"
+#include "theory/uf/proof_equality_engine.h"
#include "theory/uf/symmetry_breaker.h"
#include "theory/uf/theory_uf_rewriter.h"
@@ -112,17 +113,6 @@ private:
*/
bool propagateLit(TNode literal);
- /**
- * Explain why this literal is true by adding assumptions
- * with proof (if "pf" is non-NULL).
- */
- void explain(TNode literal, std::vector<TNode>& assumptions, eq::EqProof* pf);
-
- /**
- * Explain a literal, with proof (if "pf" is non-NULL).
- */
- Node explain(TNode literal, eq::EqProof* pf);
-
/** All the function terms that the theory has seen */
context::CDList<TNode> d_functionsTerms;
@@ -202,6 +192,9 @@ private:
CardinalityExtension* getCardinalityExtension() const { return d_thss.get(); }
private:
+ /** Explain why this literal is true by building an explanation */
+ void explain(TNode literal, Node& exp);
+
bool areCareDisequal(TNode x, TNode y);
void addCarePairs(const TNodeTrie* t1,
const TNodeTrie* t2,
@@ -213,6 +206,8 @@ private:
UfProofRuleChecker d_ufProofChecker;
/** A (default) theory state object */
TheoryState d_state;
+ /** A (default) inference manager */
+ TheoryInferenceManager d_im;
};/* class TheoryUF */
}/* CVC4::theory::uf namespace */
diff --git a/src/theory/uf/theory_uf_rewriter.h b/src/theory/uf/theory_uf_rewriter.h
index e651edb51..5d301cf9e 100644
--- a/src/theory/uf/theory_uf_rewriter.h
+++ b/src/theory/uf/theory_uf_rewriter.h
@@ -22,6 +22,7 @@
#include "expr/node_algorithm.h"
#include "options/uf_options.h"
+#include "theory/rewriter.h"
#include "theory/substitutions.h"
#include "theory/theory_rewriter.h"
diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt
index 09bbfc518..0977714c2 100644
--- a/src/util/CMakeLists.txt
+++ b/src/util/CMakeLists.txt
@@ -26,7 +26,6 @@ libcvc4_add_sources(
ostream_util.h
poly_util.cpp
poly_util.h
- proof.h
random.cpp
random.h
resource_manager.cpp
diff --git a/src/util/proof.h b/src/util/proof.h
deleted file mode 100644
index c89a3b0a6..000000000
--- a/src/util/proof.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/********************* */
-/*! \file proof.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Tim King, Morgan Deters, Mathias Preiner
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief [[ Add one-line brief description here ]]
- **
- ** [[ Add lengthier description here ]]
- ** \todo document this file
- **/
-
-#include "cvc4_public.h"
-
-#ifndef CVC4__PROOF_H
-#define CVC4__PROOF_H
-
-#include <iosfwd>
-#include <unordered_map>
-
-namespace CVC4 {
-
-class Expr;
-class ProofLetCount;
-struct ExprHashFunction;
-
-typedef std::unordered_map<Expr, ProofLetCount, ExprHashFunction> ProofLetMap;
-
-class CVC4_PUBLIC Proof
-{
- public:
- virtual ~Proof() {}
- virtual void toStream(std::ostream& out) const = 0;
- virtual void toStream(std::ostream& out, const ProofLetMap& map) const = 0;
-};/* class Proof */
-
-}/* CVC4 namespace */
-
-#endif /* CVC4__PROOF_H */
diff --git a/src/util/string.cpp b/src/util/string.cpp
index 44c4d3e4b..a1a40df8a 100644
--- a/src/util/string.cpp
+++ b/src/util/string.cpp
@@ -131,7 +131,7 @@ std::vector<unsigned> String::toInternal(const std::string& s,
++i;
// are we an escape sequence?
bool isEscapeSequence = true;
- // the string corresponding to the hexidecimal code point
+ // the string corresponding to the hexadecimal code point
std::stringstream hexString;
// is the slash followed by a 'u'? Could be last character.
if (i >= s.size() || s[i] != 'u')
@@ -195,7 +195,7 @@ std::vector<unsigned> String::toInternal(const std::string& s,
}
if (!isEnd)
{
- // if we were interupted before ending, then this is not a valid
+ // if we were interrupted before ending, then this is not a valid
// escape sequence
isEscapeSequence = false;
}
@@ -210,7 +210,7 @@ std::vector<unsigned> String::toInternal(const std::string& s,
if (val > num_codes())
{
// Failed due to being out of range. This can happen for strings of
- // the form \ u { d_4 d_3 d_2 d_1 d_0 } where d_4 is a hexidecimal not
+ // the form \ u { d_4 d_3 d_2 d_1 d_0 } where d_4 is a hexadecimal not
// in the range [0-2].
isEscapeSequence = false;
}
diff --git a/src/util/string.h b/src/util/string.h
index ca458232f..fb4a1208c 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -58,7 +58,7 @@ class CVC4_PUBLIC String {
* \u{d_2 d_1 d_0}
* \u{d_3 d_2 d_1 d_0}
* \u{d_4 d_3 d_2 d_1 d_0}
- * where d_0 ... d_4 are hexidecimal digits, to the appropriate character.
+ * where d_0 ... d_4 are hexadecimal digits, to the appropriate character.
*
* If useEscSequences is false, then the characters of the constructed
* CVC4::String correspond one-to-one with the input string.
@@ -213,7 +213,7 @@ class CVC4_PUBLIC String {
* This is true for code points between 48 ('0') and 57 ('9').
*/
static bool isDigit(unsigned character);
- /** is the unsigned a hexidecimal digit?
+ /** is the unsigned a hexadecimal digit?
*
* This is true for code points between 48 ('0') and 57 ('9'), code points
* between 65 ('A') and 70 ('F) and code points between 97 ('a') and 102 ('f).
diff --git a/test/regress/CMakeLists.txt b/test/regress/CMakeLists.txt
index 0caeafb36..1a33ee3a5 100644
--- a/test/regress/CMakeLists.txt
+++ b/test/regress/CMakeLists.txt
@@ -59,6 +59,7 @@ set(regress_0_tests
regress0/arrays/bug272.minimized.smtv1.smt2
regress0/arrays/bug272.smtv1.smt2
regress0/arrays/bug3020.smt2
+ regress0/arrays/bug4957.smt2
regress0/arrays/bug637.delta.smt2
regress0/arrays/constarr.cvc
regress0/arrays/constarr.smt2
@@ -621,7 +622,6 @@ set(regress_0_tests
regress0/nl/very-easy-sat.smt2
regress0/nl/very-simple-unsat.smt2
regress0/options/invalid_dump.smt2
- regress0/options/invalid_option_inc_proofs.smt2
regress0/opt-abd-no-use.smt2
regress0/parallel-let.smt2
regress0/parser/as.smt2
@@ -871,7 +871,7 @@ set(regress_0_tests
regress0/seq/seq-nth.smt2
regress0/seq/seq-nth-uf.smt2
regress0/seq/seq-nth-uf-z.smt2
- regress0/seq/seq-nth-undef.smt2
+ regress0/seq/seq-nth-undef.smt2
regress0/seq/seq-rewrites.smt2
regress0/sets/abt-min.smt2
regress0/sets/abt-te-exh.smt2
diff --git a/test/regress/regress0/arrays/bug4957.smt2 b/test/regress/regress0/arrays/bug4957.smt2
new file mode 100644
index 000000000..f82ae1932
--- /dev/null
+++ b/test/regress/regress0/arrays/bug4957.smt2
@@ -0,0 +1,6 @@
+; COMMAND-LINE: --ackermann --no-check-unsat-cores
+; EXPECT: unsat
+(set-logic QF_ALIA)
+(declare-fun a () (Array Int Int))
+(assert (distinct (select a 0) (select (ite false a a) 0)))
+(check-sat)
diff --git a/test/regress/regress0/bug217.smt2 b/test/regress/regress0/bug217.smt2
index 30c87333e..4d2e828b5 100644
--- a/test/regress/regress0/bug217.smt2
+++ b/test/regress/regress0/bug217.smt2
@@ -1,4 +1,3 @@
-; COMMAND-LINE: --fewer-preprocessing-holes
; EXPECT: unsat
(set-logic QF_UF)
(set-info :status unsat)
diff --git a/test/regress/regress0/options/invalid_option_inc_proofs.smt2 b/test/regress/regress0/options/invalid_option_inc_proofs.smt2
deleted file mode 100644
index f63dbd27f..000000000
--- a/test/regress/regress0/options/invalid_option_inc_proofs.smt2
+++ /dev/null
@@ -1,6 +0,0 @@
-; REQUIRES: proof
-; COMMAND-LINE: --incremental --proof
-; EXPECT: (error "Error in option parsing: --incremental is not supported with proofs")
-; EXIT: 1
-(set-logic QF_BV)
-(check-sat)
diff --git a/test/regress/regress1/bv/bench_38.delta.smt2 b/test/regress/regress1/bv/bench_38.delta.smt2
index 760614348..3f809716a 100644
--- a/test/regress/regress1/bv/bench_38.delta.smt2
+++ b/test/regress/regress1/bv/bench_38.delta.smt2
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --fewer-preprocessing-holes --check-proof --quiet
+; COMMAND-LINE: --quiet
; EXPECT: unsat
(set-logic QF_BV)
(declare-fun x () (_ BitVec 4))
diff --git a/test/regress/regress1/non-fatal-errors.smt2 b/test/regress/regress1/non-fatal-errors.smt2
index 1e1865883..ec3d02927 100644
--- a/test/regress/regress1/non-fatal-errors.smt2
+++ b/test/regress/regress1/non-fatal-errors.smt2
@@ -2,11 +2,10 @@
; EXPECT: success
; EXPECT: success
; EXPECT: success
+; EXPECT: unsupported
; EXPECT: success
; EXPECT: success
; EXPECT: success
-; EXPECT: success
-; EXPECT: (error "")
; EXPECT: (error "")
; EXPECT: (error "")
; EXPECT: (error "")
@@ -22,7 +21,6 @@
(declare-fun p () Bool)
(get-unsat-core)
(get-value (p))
-(get-proof)
(get-model)
(get-assignment)
(assert true)
diff --git a/test/regress/regress1/quantifiers/dump-inst-proof.smt2 b/test/regress/regress1/quantifiers/dump-inst-proof.smt2
index 9edc4df2b..f900e78a9 100644
--- a/test/regress/regress1/quantifiers/dump-inst-proof.smt2
+++ b/test/regress/regress1/quantifiers/dump-inst-proof.smt2
@@ -1,5 +1,5 @@
; REQUIRES: proof
-; COMMAND-LINE: --dump-instantiations --proof --print-inst-full
+; COMMAND-LINE: --dump-instantiations --produce-unsat-cores --print-inst-full
; EXPECT: unsat
; EXPECT: (instantiations (forall ((x Int)) (or (P x) (Q x)) )
; EXPECT: ( 2 )
@@ -21,7 +21,7 @@
(assert (forall ((x Int)) (or (not (S x)) (not (Q x)))))
(assert (and (not (R 0)) (not (R 10)) (not (S 1)) (not (P 2))))
(assert (S 2))
-; This tests that --proof minimizes the instantiations printed out.
-; This regression should require only the 2 instantiations above, but
-; may try more.
+; This tests that --produce-unsat-cores minimizes the instantiations
+; printed out. This regression should require only the 2
+; instantiations above, but may try more.
(check-sat)
diff --git a/test/regress/regress1/quantifiers/issue3481-unsat1.smt2 b/test/regress/regress1/quantifiers/issue3481-unsat1.smt2
index fb7ff5485..9cf535dc7 100644
--- a/test/regress/regress1/quantifiers/issue3481-unsat1.smt2
+++ b/test/regress/regress1/quantifiers/issue3481-unsat1.smt2
@@ -2,7 +2,7 @@
; EXPECT: unsat
;; produced by cvc4_16.drv ;;
-(set-logic AUFBVFPDTNIRA)
+(set-logic AUFBVDTNIRA)
(set-info :smt-lib-version 2.6)
;;; generated by SMT-LIB2 driver
;;; SMT-LIB2 driver: bit-vectors, common part
diff --git a/test/regress/regress1/quantifiers/issue3481.smt2 b/test/regress/regress1/quantifiers/issue3481.smt2
index fe8c84d62..3d9bfe981 100644
--- a/test/regress/regress1/quantifiers/issue3481.smt2
+++ b/test/regress/regress1/quantifiers/issue3481.smt2
@@ -3,7 +3,7 @@
;; produced by cvc4_16.drv ;;
(set-info :smt-lib-version 2.6)
-(set-logic AUFBVFPDTNIRA)
+(set-logic AUFBVDTNIRA)
;;; generated by SMT-LIB2 driver
;;; SMT-LIB2 driver: bit-vectors, common part
;;; SMT-LIB2: integer arithmetic
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index bd7c1ea22..bd7029c54 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -107,7 +107,6 @@ add_subdirectory(expr)
add_subdirectory(main)
add_subdirectory(parser)
add_subdirectory(prop)
-add_subdirectory(proof)
add_subdirectory(theory)
add_subdirectory(preprocessing)
add_subdirectory(util)
diff --git a/test/unit/api/python/test_datatype_api.py b/test/unit/api/python/test_datatype_api.py
new file mode 100644
index 000000000..a5499ffd6
--- /dev/null
+++ b/test/unit/api/python/test_datatype_api.py
@@ -0,0 +1,171 @@
+import pytest
+
+import pycvc4
+from pycvc4 import kinds
+
+
+def test_datatype_simply_rec():
+ solver = pycvc4.Solver()
+
+ # Create mutual datatypes corresponding to this definition block:
+ #
+ # DATATYPE
+ # wlist = leaf(data: list),
+ # list = cons(car: wlist, cdr: list) | nil,
+ # ns = elem(ndata: set(wlist)) | elemArray(ndata2: array(list, list))
+ # END;
+
+ # Make unresolved types as placeholders
+ unres_wlist = solver.mkUninterpretedSort('wlist')
+ unres_list = solver.mkUninterpretedSort('list')
+ unres_ns = solver.mkUninterpretedSort('ns')
+ unres_types = set([unres_wlist, unres_list, unres_ns])
+
+ wlist = solver.mkDatatypeDecl('wlist')
+ leaf = solver.mkDatatypeConstructorDecl('leaf')
+ leaf.addSelector('data', unres_list)
+ wlist.addConstructor(leaf)
+
+ dlist = solver.mkDatatypeDecl('list')
+ cons = solver.mkDatatypeConstructorDecl('cons')
+ cons.addSelector('car', unres_wlist)
+ cons.addSelector('cdr', unres_list)
+ dlist.addConstructor(cons)
+ nil = solver.mkDatatypeConstructorDecl("nil")
+ dlist.addConstructor(nil)
+
+ ns = solver.mkDatatypeDecl('ns')
+ elem = solver.mkDatatypeConstructorDecl('elem')
+ elem.addSelector('ndata', solver.mkSetSort(unres_wlist))
+ ns.addConstructor(elem)
+ elem_array = solver.mkDatatypeConstructorDecl('elemArray')
+ elem_array.addSelector('ndata', solver.mkArraySort(unres_list, unres_list))
+ ns.addConstructor(elem_array)
+
+ # this is well-founded and has no nested recursion
+ dtdecls = [wlist, dlist, ns]
+ dtsorts = solver.mkDatatypeSorts(dtdecls, unres_types)
+ assert len(dtsorts) == 3
+ assert dtsorts[0].getDatatype().isWellFounded()
+ assert dtsorts[1].getDatatype().isWellFounded()
+ assert dtsorts[2].getDatatype().isWellFounded()
+ assert not dtsorts[0].getDatatype().hasNestedRecursion()
+ assert not dtsorts[1].getDatatype().hasNestedRecursion()
+ assert not dtsorts[2].getDatatype().hasNestedRecursion()
+
+ # Create mutual datatypes corresponding to this definition block:
+ # DATATYPE
+ # ns2 = elem2(ndata: array(int,ns2)) | nil2
+ # END;
+ unres_ns2 = solver.mkUninterpretedSort('ns2')
+ unres_types = set([unres_ns2])
+
+ ns2 = solver.mkDatatypeDecl('ns2')
+ elem2 = solver.mkDatatypeConstructorDecl('elem2')
+ elem2.addSelector('ndata',
+ solver.mkArraySort(solver.getIntegerSort(), unres_ns2))
+ ns2.addConstructor(elem2)
+ nil2 = solver.mkDatatypeConstructorDecl('nil2')
+ ns2.addConstructor(nil2)
+
+ # this is not well-founded due to non-simple recursion
+ dtdecls = [ns2]
+ dtsorts = solver.mkDatatypeSorts(dtdecls, unres_types)
+ assert len(dtsorts) == 1
+ assert dtsorts[0].getDatatype()[0][0].getRangeSort().isArray()
+ elem_sort = dtsorts[0].getDatatype()[0][0].getRangeSort().getArrayElementSort()
+ assert elem_sort == dtsorts[0]
+ assert dtsorts[0].getDatatype().isWellFounded()
+ assert dtsorts[0].getDatatype().hasNestedRecursion()
+
+ # Create mutual datatypes corresponding to this definition block:
+ # DATATYPE
+ # list3 = cons3(car: ns3, cdr: list3) | nil3,
+ # ns3 = elem3(ndata: set(list3))
+ # END
+ unres_ns3 = solver.mkUninterpretedSort('ns3')
+ unres_list3 = solver.mkUninterpretedSort('list3')
+ unres_types = set([unres_ns3, unres_list3])
+
+ list3 = solver.mkDatatypeDecl('list3')
+ cons3 = solver.mkDatatypeConstructorDecl('cons3')
+ cons3.addSelector('car', unres_ns3)
+ cons3.addSelector('cdr', unres_list3)
+ list3.addConstructor(cons3)
+ nil3 = solver.mkDatatypeConstructorDecl('nil3')
+ list3.addConstructor(nil3)
+
+ ns3 = solver.mkDatatypeDecl('ns3')
+ elem3 = solver.mkDatatypeConstructorDecl('elem3')
+ elem3.addSelector('ndata', solver.mkSetSort(unres_list3))
+ ns3.addConstructor(elem3)
+
+ # both are well-founded and have nested recursion
+ dtdecls = [list3, ns3]
+ dtsorts = solver.mkDatatypeSorts(dtdecls, unres_types)
+ assert len(dtsorts) == 2
+ assert dtsorts[0].getDatatype().isWellFounded()
+ assert dtsorts[1].getDatatype().isWellFounded()
+ assert dtsorts[0].getDatatype().hasNestedRecursion()
+ assert dtsorts[1].getDatatype().hasNestedRecursion()
+
+ # Create mutual datatypes corresponding to this definition block:
+ # DATATYPE
+ # list4 = cons(car: set(ns4), cdr: list4) | nil,
+ # ns4 = elem(ndata: list4)
+ # END
+ unres_ns4 = solver.mkUninterpretedSort('ns4')
+ unres_list4 = solver.mkUninterpretedSort('list4')
+ unres_types = set([unres_ns4, unres_list4])
+
+ list4 = solver.mkDatatypeDecl('list4')
+ cons4 = solver.mkDatatypeConstructorDecl('cons4')
+ cons4.addSelector('car', solver.mkSetSort(unres_ns4))
+ cons4.addSelector('cdr', unres_list4)
+ list4.addConstructor(cons4)
+ nil4 = solver.mkDatatypeConstructorDecl('nil4')
+ list4.addConstructor(nil4)
+
+ ns4 = solver.mkDatatypeDecl('ns4')
+ elem4 = solver.mkDatatypeConstructorDecl('elem3')
+ elem4.addSelector('ndata', unres_list4)
+ ns4.addConstructor(elem4)
+
+ # both are well-founded and have nested recursion
+ dtdecls = [list4, ns4]
+ dtsorts = solver.mkDatatypeSorts(dtdecls, unres_types)
+ assert len(dtsorts) == 2
+ assert dtsorts[0].getDatatype().isWellFounded()
+ assert dtsorts[1].getDatatype().isWellFounded()
+ assert dtsorts[0].getDatatype().hasNestedRecursion()
+ assert dtsorts[1].getDatatype().hasNestedRecursion()
+
+ # Create mutual datatypes corresponding to this definition block:
+ # DATATYPE
+ # list5[X] = cons(car: X, cdr: list5[list5[X]]) | nil
+ # END
+ unres_list5 = solver.mkSortConstructorSort('list5', 1)
+ unres_types = set([unres_list5])
+
+ x = solver.mkParamSort('X')
+ v = [x]
+ list5 = solver.mkDatatypeDecl('list5', v)
+
+ args = [x]
+ ur_list_x = unres_list5.instantiate(args)
+ args = [ur_list_x]
+ ur_list_list_x = unres_list5.instantiate(args)
+
+ cons5 = solver.mkDatatypeConstructorDecl('cons5')
+ cons5.addSelector('car', x)
+ cons5.addSelector('cdr', ur_list_list_x)
+ list5.addConstructor(cons5)
+ nil5 = solver.mkDatatypeConstructorDecl('nil5')
+ list5.addConstructor(nil5)
+
+ # well-founded and has nested recursion
+ dtdecls = [list5]
+ dtsorts = solver.mkDatatypeSorts(dtdecls, unres_types)
+ assert len(dtsorts) == 1
+ assert dtsorts[0].getDatatype().isWellFounded()
+ assert dtsorts[0].getDatatype().hasNestedRecursion()
diff --git a/test/unit/api/python/test_sort.py b/test/unit/api/python/test_sort.py
index cd40fc807..5fdb49f48 100644
--- a/test/unit/api/python/test_sort.py
+++ b/test/unit/api/python/test_sort.py
@@ -223,21 +223,31 @@ def testGetBVSize():
def testGetFPExponentSize():
solver = pycvc4.Solver()
- fpSort = solver.mkFloatingPointSort(4, 8)
- fpSort.getFPExponentSize()
- setSort = solver.mkSetSort(solver.getIntegerSort())
- with pytest.raises(Exception):
- setSort.getFPExponentSize()
+ if solver.supportsFloatingPoint():
+ fpSort = solver.mkFloatingPointSort(4, 8)
+ fpSort.getFPExponentSize()
+ setSort = solver.mkSetSort(solver.getIntegerSort())
+
+ with pytest.raises(Exception):
+ setSort.getFPExponentSize()
+ else:
+ with pytest.raises(Exception):
+ solver.mkFloatingPointSort(4, 8)
def testGetFPSignificandSize():
solver = pycvc4.Solver()
- fpSort = solver.mkFloatingPointSort(4, 8)
- fpSort.getFPSignificandSize()
- setSort = solver.mkSetSort(solver.getIntegerSort())
- with pytest.raises(Exception):
- setSort.getFPSignificandSize()
+ if solver.supportsFloatingPoint():
+ fpSort = solver.mkFloatingPointSort(4, 8)
+ fpSort.getFPSignificandSize()
+ setSort = solver.mkSetSort(solver.getIntegerSort())
+
+ with pytest.raises(Exception):
+ setSort.getFPSignificandSize()
+ else:
+ with pytest.raises(Exception):
+ solver.mkFloatingPointSort(4, 8)
def testGetDatatypeParamSorts():
solver = pycvc4.Solver()
diff --git a/test/unit/api/python/test_term.py b/test/unit/api/python/test_term.py
index b135e4510..ca8d4c741 100644
--- a/test/unit/api/python/test_term.py
+++ b/test/unit/api/python/test_term.py
@@ -4,6 +4,17 @@ import pycvc4
from pycvc4 import kinds
+def test_getitem():
+ solver = pycvc4.Solver()
+ intsort = solver.getIntegerSort()
+ x = solver.mkConst(intsort, 'x')
+ y = solver.mkConst(intsort, 'y')
+ xpy = solver.mkTerm(kinds.Plus, x, y)
+
+ assert xpy[0] == x
+ assert xpy[1] == y
+
+
def test_get_kind():
solver = pycvc4.Solver()
intsort = solver.getIntegerSort()
diff --git a/test/unit/api/solver_black.h b/test/unit/api/solver_black.h
index 9837d6b00..11dbbb7ae 100644
--- a/test/unit/api/solver_black.h
+++ b/test/unit/api/solver_black.h
@@ -27,12 +27,14 @@ class SolverBlack : public CxxTest::TestSuite
void setUp() override;
void tearDown() override;
+ void testSupportsFloatingPoint();
+
void testGetBooleanSort();
void testGetIntegerSort();
void testGetNullSort();
void testGetRealSort();
void testGetRegExpSort();
- void testGetRoundingmodeSort();
+ void testGetRoundingModeSort();
void testGetStringSort();
void testMkArraySort();
@@ -169,6 +171,20 @@ void SolverBlack::setUp() { d_solver.reset(new Solver()); }
void SolverBlack::tearDown() { d_solver.reset(nullptr); }
+void SolverBlack::testSupportsFloatingPoint()
+{
+ if (d_solver->supportsFloatingPoint())
+ {
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver->mkRoundingMode(ROUND_NEAREST_TIES_TO_EVEN));
+ }
+ else
+ {
+ TS_ASSERT_THROWS(d_solver->mkRoundingMode(ROUND_NEAREST_TIES_TO_EVEN),
+ CVC4ApiException&);
+ }
+}
+
void SolverBlack::testGetBooleanSort()
{
TS_ASSERT_THROWS_NOTHING(d_solver->getBooleanSort());
@@ -199,9 +215,16 @@ void SolverBlack::testGetStringSort()
TS_ASSERT_THROWS_NOTHING(d_solver->getStringSort());
}
-void SolverBlack::testGetRoundingmodeSort()
+void SolverBlack::testGetRoundingModeSort()
{
- TS_ASSERT_THROWS_NOTHING(d_solver->getRoundingmodeSort());
+ if (d_solver->supportsFloatingPoint())
+ {
+ TS_ASSERT_THROWS_NOTHING(d_solver->getRoundingModeSort());
+ }
+ else
+ {
+ TS_ASSERT_THROWS(d_solver->getRoundingModeSort(), CVC4ApiException&);
+ }
}
void SolverBlack::testMkArraySort()
@@ -210,15 +233,20 @@ void SolverBlack::testMkArraySort()
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));
+
+ if (d_solver->supportsFloatingPoint())
+ {
+ Sort fpSort = d_solver->mkFloatingPointSort(3, 5);
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkArraySort(fpSort, fpSort));
+ TS_ASSERT_THROWS_NOTHING(d_solver->mkArraySort(bvSort, fpSort));
+ }
+
Solver slv;
TS_ASSERT_THROWS(slv.mkArraySort(boolSort, boolSort), CVC4ApiException&);
}
@@ -231,9 +259,16 @@ void SolverBlack::testMkBitVectorSort()
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&);
+ if (d_solver->supportsFloatingPoint())
+ {
+ 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&);
+ }
+ else
+ {
+ TS_ASSERT_THROWS(d_solver->mkFloatingPointSort(4, 8), CVC4ApiException&);
+ }
}
void SolverBlack::testMkDatatypeSort()
@@ -480,8 +515,16 @@ void SolverBlack::testMkBoolean()
void SolverBlack::testMkRoundingMode()
{
- TS_ASSERT_THROWS_NOTHING(
- d_solver->mkRoundingMode(RoundingMode::ROUND_TOWARD_ZERO));
+ if (CVC4::Configuration::isBuiltWithSymFPU())
+ {
+ TS_ASSERT_THROWS_NOTHING(
+ d_solver->mkRoundingMode(RoundingMode::ROUND_TOWARD_ZERO));
+ }
+ else
+ {
+ TS_ASSERT_THROWS(d_solver->mkRoundingMode(RoundingMode::ROUND_TOWARD_ZERO),
+ CVC4ApiException&);
+ }
}
void SolverBlack::testMkUninterpretedConst()
diff --git a/test/unit/proof/CMakeLists.txt b/test/unit/proof/CMakeLists.txt
deleted file mode 100644
index 315c78d6f..000000000
--- a/test/unit/proof/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-#-----------------------------------------------------------------------------#
-# Add unit tests
-
-cvc4_add_unit_test_black(drat_proof_black proof)
-cvc4_add_unit_test_black(er_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
deleted file mode 100644
index 4b593a588..000000000
--- a/test/unit/proof/drat_proof_black.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/********************* */
-/*! \file drat_proof_black.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Andres Noetzli
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** 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 bb.v62) (clc (neg bb.v8192) cln))"
- "(DRATProofa (clc (pos bb.v128) (clc (neg bb.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/er_proof_black.h b/test/unit/proof/er_proof_black.h
deleted file mode 100644
index d9178e34e..000000000
--- a/test/unit/proof/er_proof_black.h
+++ /dev/null
@@ -1,464 +0,0 @@
-/********************* */
-/*! \file er_proof_black.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Black box testing of the ER proof class
- **
- ** In particular, tests TRACECHECK parsing and ER LFSC output.
- **/
-
-#include <cxxtest/TestSuite.h>
-
-#include <algorithm>
-#include <cctype>
-#include <iostream>
-#include <iterator>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include "base/configuration_private.h"
-#include "proof/clause_id.h"
-#include "proof/er/er_proof.h"
-#include "prop/sat_solver_types.h"
-#include "utils.h"
-
-#if IS_LFSC_BUILD
-#include "lfscc.h"
-
-namespace CVC4 {
-namespace proof {
-extern const char* const plf_signatures;
-} // namespace proof
-} // namespace CVC4
-#endif
-
-
-using namespace CVC4;
-using namespace CVC4::proof::er;
-using namespace CVC4::prop;
-
-class ErProofBlack : public CxxTest::TestSuite
-{
- public:
- void setUp() override {}
- void tearDown() override {}
-
- void testTraceCheckParse1Line();
- void testTraceCheckParse5Lines();
- void testErTraceCheckParse();
- void testErTraceCheckOutput();
- void testErTraceCheckOutputMedium();
-};
-
-/**
- * @brief Add a new clause to the clause store and list of used clauses
- *
- * @param clauses the clause store
- * @param usedIds the used clauses
- * @param id the id of the new clause
- * @param clause the clause itself
- */
-void addClause(std::unordered_map<ClauseId, SatClause>& clauses,
- std::vector<ClauseId>& usedIds,
- ClauseId id,
- SatClause&& clause)
-{
- clauses.emplace(id, std::move(clause));
- usedIds.push_back(id);
-}
-
-void ErProofBlack::testTraceCheckParse1Line()
-{
- std::string tracecheckText = "1 -2 3 0 4 2 0\n";
- std::istringstream stream(tracecheckText);
- TraceCheckProof pf = TraceCheckProof::fromText(stream);
- TS_ASSERT_EQUALS(pf.d_lines.size(), 1);
-
- TS_ASSERT_EQUALS(pf.d_lines[0].d_idx, 1);
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause.size(), 2);
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause[0], SatLiteral(1, true));
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause[1], SatLiteral(2, false));
- TS_ASSERT_EQUALS(pf.d_lines[0].d_chain.size(), 2);
- TS_ASSERT_EQUALS(pf.d_lines[0].d_chain[0], 4);
- TS_ASSERT_EQUALS(pf.d_lines[0].d_chain[1], 2);
-}
-
-void ErProofBlack::testTraceCheckParse5Lines()
-{
- std::string tracecheckText =
- "1 1 -2 3 0 0\n"
- "2 -1 0 0\n"
- "3 2 0 0\n"
- "4 -3 0 0\n"
- "5 0 1 2 4 3 0\n";
- std::istringstream stream(tracecheckText);
- TraceCheckProof pf = TraceCheckProof::fromText(stream);
- TS_ASSERT_EQUALS(pf.d_lines.size(), 5);
-
- TS_ASSERT_EQUALS(pf.d_lines[0].d_idx, 1);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_idx, 5);
-
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause.size(), 3);
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause[0], SatLiteral(0, false));
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause[1], SatLiteral(1, true));
- TS_ASSERT_EQUALS(pf.d_lines[0].d_clause[2], SatLiteral(2, false));
- TS_ASSERT_EQUALS(pf.d_lines[0].d_chain.size(), 0);
-
- TS_ASSERT_EQUALS(pf.d_lines[4].d_chain.size(), 4);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_chain[0], 1);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_chain[1], 2);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_chain[2], 4);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_chain[3], 3);
- TS_ASSERT_EQUALS(pf.d_lines[4].d_clause.size(), 0);
-}
-
-void ErProofBlack::testErTraceCheckParse()
-{
- std::string tracecheckText =
- "1 1 2 -3 0 0\n"
- "2 -1 -2 3 0 0\n"
- "3 2 3 -4 0 0\n"
- "4 -2 -3 4 0 0\n"
- "5 -1 -3 -4 0 0\n"
- "6 1 3 4 0 0\n"
- "7 -1 2 4 0 0\n"
- "8 1 -2 -4 0 0\n"
- "9 5 0 0\n"
- "10 5 1 0 0\n"
- "11 4 5 2 0 10 7 0\n"
- "12 -4 5 -3 0 10 5 0\n"
- "13 3 5 -2 0 10 2 0\n"
- "14 -2 -4 0 2 5 8 0\n"
- "15 4 3 0 7 2 6 0\n"
- "16 2 -3 0 7 5 1 0\n"
- "17 2 0 3 15 16 0\n"
- "18 0 4 15 14 17 0\n";
- std::istringstream stream(tracecheckText);
- TraceCheckProof tc = TraceCheckProof::fromText(stream);
-
- std::unordered_map<ClauseId, SatClause> clauses;
- std::vector<ClauseId> usedIds;
- addClause(
- clauses,
- usedIds,
- 1,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, false), SatLiteral(2, true)});
- addClause(
- clauses,
- usedIds,
- 2,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, true), SatLiteral(2, false)});
- addClause(
- clauses,
- usedIds,
- 3,
- std::vector<SatLiteral>{
- SatLiteral(1, false), SatLiteral(2, false), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 4,
- std::vector<SatLiteral>{
- SatLiteral(1, true), SatLiteral(2, true), SatLiteral(3, false)});
- addClause(clauses,
- usedIds,
- 5,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(2, true), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 6,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(2, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 7,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 8,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, true), SatLiteral(3, true)});
- ErProof pf(clauses, usedIds, std::move(tc));
-
- TS_ASSERT_EQUALS(pf.getInputClauseIds()[0], 1);
- TS_ASSERT_EQUALS(pf.getInputClauseIds()[7], 8);
-
- TS_ASSERT_EQUALS(pf.getDefinitions().size(), 1)
- TS_ASSERT_EQUALS(pf.getDefinitions()[0].d_newVariable, SatVariable(4));
- TS_ASSERT_EQUALS(pf.getDefinitions()[0].d_oldLiteral, SatLiteral(0, true));
- TS_ASSERT_EQUALS(pf.getDefinitions()[0].d_otherLiterals.size(), 0);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines.size(), 18);
-
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_idx, 1);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_idx, 17);
-
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_clause.size(), 3);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_clause[0],
- SatLiteral(0, false));
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_clause[1],
- SatLiteral(1, false));
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_clause[2],
- SatLiteral(2, true));
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[0].d_chain.size(), 0);
-
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_clause.size(), 1);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_clause[0],
- SatLiteral(1, false));
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_chain.size(), 3);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_chain[0], 3);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_chain[1], 15);
- TS_ASSERT_EQUALS(pf.getTraceCheckProof().d_lines[16].d_chain[2], 16);
-}
-
-void ErProofBlack::testErTraceCheckOutput()
-{
- std::string tracecheckText =
- "1 1 2 -3 0 0\n"
- "2 -1 -2 3 0 0\n"
- "3 2 3 -4 0 0\n"
- "4 -2 -3 4 0 0\n"
- "5 -1 -3 -4 0 0\n"
- "6 1 3 4 0 0\n"
- "7 -1 2 4 0 0\n"
- "8 1 -2 -4 0 0\n"
- "9 5 0 0\n"
- "10 5 1 0 0\n"
- "11 4 5 2 0 10 7 0\n"
- "12 -4 5 -3 0 10 5 0\n"
- "13 3 5 -2 0 10 2 0\n"
- "14 -2 -4 0 2 5 8 0\n"
- "15 4 3 0 7 2 6 0\n"
- "16 2 -3 0 7 5 1 0\n"
- "17 2 0 3 15 16 0\n"
- "18 0 4 15 14 17 0\n";
- std::istringstream stream(tracecheckText);
- TraceCheckProof tc = TraceCheckProof::fromText(stream);
-
- std::unordered_map<ClauseId, SatClause> clauses;
- std::vector<ClauseId> usedIds;
- addClause(
- clauses,
- usedIds,
- 1,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, false), SatLiteral(2, true)});
- addClause(
- clauses,
- usedIds,
- 2,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, true), SatLiteral(2, false)});
- addClause(
- clauses,
- usedIds,
- 3,
- std::vector<SatLiteral>{
- SatLiteral(1, false), SatLiteral(2, false), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 4,
- std::vector<SatLiteral>{
- SatLiteral(1, true), SatLiteral(2, true), SatLiteral(3, false)});
- addClause(clauses,
- usedIds,
- 5,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(2, true), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 6,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(2, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 7,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 8,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, true), SatLiteral(3, true)});
- ErProof pf(clauses, usedIds, std::move(tc));
-
- std::ostringstream lfsc;
- pf.outputAsLfsc(lfsc);
-
- std::string out = R"EOF(
- (decl_definition
- (neg bb.v0)
- cln
- (\ er.v4
- (\ er.def4
- (clausify_definition _ _ _ er.def4 _
- (\ er.c9
- (\ er.c10
- (\ er.cnf4
- (satlem_simplify _ _ _
- (R _ _ er.c10 bb.pb7 bb.v0) (\ er.c11
- (satlem_simplify _ _ _
- (R _ _ er.c10 bb.pb5 bb.v0) (\ er.c12
- (satlem_simplify _ _ _
- (R _ _ er.c10 bb.pb2 bb.v0) (\ er.c13
- (satlem_simplify _ _ _
- (Q _ _ (R _ _ bb.pb2 bb.pb5 bb.v2) bb.pb8 bb.v0) (\ er.c14
- (satlem_simplify _ _ _
- (Q _ _ (R _ _ bb.pb7 bb.pb2 bb.v1) bb.pb6 bb.v0) (\ er.c15
- (satlem_simplify _ _ _
- (Q _ _ (R _ _ bb.pb7 bb.pb5 bb.v3) bb.pb1 bb.v0) (\ er.c16
- (satlem_simplify _ _ _
- (R _ _ (Q _ _ bb.pb3 er.c15 bb.v3) er.c16 bb.v2) (\ er.c17
- (satlem_simplify _ _ _
- (Q _ _ (R _ _ (Q _ _ bb.pb4 er.c15 bb.v2) er.c14 bb.v3)
- er.c17 bb.v1) (\ er.c18
- er.c18 ; (holds cln)
- ))))))))))))))))
- )))
- )
- ))
- )
- )EOF";
-
- TS_ASSERT_EQUALS(filterWhitespace(lfsc.str()), filterWhitespace(out));
-}
-
-/**
- * This proof has been specially constructed to stress-test the proof
- * machinery, while still being short. It's a bit meandering...
- */
-void ErProofBlack::testErTraceCheckOutputMedium()
-{
- std::string tracecheckText =
- "1 1 2 -3 0 0\n"
- "2 -1 -2 3 0 0\n"
- "3 2 3 -4 0 0\n"
- "4 -2 -3 4 0 0\n"
- "5 -1 -3 -4 0 0\n"
- "6 1 3 4 0 0\n"
- "7 -1 2 4 0 0\n"
- "8 1 -2 -4 0 0\n"
-
- "9 5 2 4 0 0\n" // Definition with 2 other variables
- "10 5 1 0 0\n"
- "11 2 -5 -1 0 0\n"
- "12 4 -5 -1 0 0\n"
-
- "13 6 0 0\n" // Definition with no other variables
- "14 6 -3 0 0\n"
-
- "15 -3 4 0 11 1 10 7 4 0\n" // Chain w/ both def. and input clauses
-
- "16 -2 -4 0 2 5 8 0\n" // The useful bit of the proof
- "17 4 3 0 7 2 6 0\n"
- "18 2 -3 0 7 5 1 0\n"
- "19 2 0 3 17 18 0\n"
- "20 0 4 17 16 19 0\n";
-
- std::istringstream stream(tracecheckText);
- TraceCheckProof tc = TraceCheckProof::fromText(stream);
-
- std::unordered_map<ClauseId, SatClause> clauses;
- std::vector<ClauseId> usedIds;
- addClause(
- clauses,
- usedIds,
- 1,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, false), SatLiteral(2, true)});
- addClause(
- clauses,
- usedIds,
- 2,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, true), SatLiteral(2, false)});
- addClause(
- clauses,
- usedIds,
- 3,
- std::vector<SatLiteral>{
- SatLiteral(1, false), SatLiteral(2, false), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 4,
- std::vector<SatLiteral>{
- SatLiteral(1, true), SatLiteral(2, true), SatLiteral(3, false)});
- addClause(clauses,
- usedIds,
- 5,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(2, true), SatLiteral(3, true)});
- addClause(
- clauses,
- usedIds,
- 6,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(2, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 7,
- std::vector<SatLiteral>{
- SatLiteral(0, true), SatLiteral(1, false), SatLiteral(3, false)});
- addClause(
- clauses,
- usedIds,
- 8,
- std::vector<SatLiteral>{
- SatLiteral(0, false), SatLiteral(1, true), SatLiteral(3, true)});
- ErProof pf(clauses, usedIds, std::move(tc));
-
- std::ostringstream actual_pf_body;
- pf.outputAsLfsc(actual_pf_body);
-
-#if IS_LFSC_BUILD
- std::string pf_header = R"EOF(
- (check
- (% bb.v0 var
- (% bb.v1 var
- (% bb.v2 var
- (% bb.v3 var
- (% bb.pb1 (holds (clc (pos bb.v0) (clc (pos bb.v1) (clc (neg bb.v2) cln))))
- (% bb.pb2 (holds (clc (neg bb.v0) (clc (neg bb.v1) (clc (pos bb.v2) cln))))
- (% bb.pb3 (holds (clc (pos bb.v1) (clc (pos bb.v2) (clc (neg bb.v3) cln))))
- (% bb.pb4 (holds (clc (neg bb.v1) (clc (neg bb.v2) (clc (pos bb.v3) cln))))
- (% bb.pb5 (holds (clc (neg bb.v0) (clc (neg bb.v2) (clc (neg bb.v3) cln))))
- (% bb.pb6 (holds (clc (pos bb.v0) (clc (pos bb.v2) (clc (pos bb.v3) cln))))
- (% bb.pb7 (holds (clc (neg bb.v0) (clc (pos bb.v1) (clc (pos bb.v3) cln))))
- (% bb.pb8 (holds (clc (pos bb.v0) (clc (neg bb.v1) (clc (neg bb.v3) cln))))
- (: (holds cln)
- )EOF";
-
- std::string pf_footer = R"EOF(
- )
- ))))))))
- ))))
- )
- )EOF";
-
- std::stringstream actual_pf;
- actual_pf << proof::plf_signatures << pf_header << actual_pf_body.str() << pf_footer;
-
- lfscc_init();
- lfscc_check_file(actual_pf, false, false, false, false, false, false, false);
-#endif
-}
diff --git a/test/unit/proof/lfsc_proof_printer_black.h b/test/unit/proof/lfsc_proof_printer_black.h
deleted file mode 100644
index 74fda4996..000000000
--- a/test/unit/proof/lfsc_proof_printer_black.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/********************* */
-/*! \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-2020 by the authors listed in the file AUTHORS
- ** in the top-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
deleted file mode 100644
index 8d91fee33..000000000
--- a/test/unit/proof/lrat_proof_black.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/********************* */
-/*! \file lrat_proof_black.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir, Andres Noetzli
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** 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 <iostream>
-
-#include "proof/lrat/lrat_proof.h"
-#include "prop/sat_solver_types.h"
-#include "utils.h"
-
-using namespace CVC4;
-using namespace CVC4::proof::lrat;
-using namespace CVC4::prop;
-
-class LratProofBlack : public CxxTest::TestSuite
-{
- public:
- void setUp() override {}
- void tearDown() override {}
-
- void testOutputAsLfsc();
-};
-
-void LratProofBlack::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));
-}
diff --git a/test/unit/proof/utils.h b/test/unit/proof/utils.h
deleted file mode 100644
index 3db6e2171..000000000
--- a/test/unit/proof/utils.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/********************* */
-/*! \file utils.h
- ** \verbatim
- ** Top contributors (to current version):
- ** Alex Ozdemir
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
- ** in the top-level source directory) and their institutional affiliations.
- ** All rights reserved. See the file COPYING in the top-level source
- ** directory for licensing information.\endverbatim
- **
- ** \brief Utilities for proof testing
- **/
-
-#include <algorithm>
-#include <string>
-#include <cctype>
-#include <iterator>
-
-/**
- * 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;
-}
diff --git a/test/unit/prop/cnf_stream_white.h b/test/unit/prop/cnf_stream_white.h
index f0253fdbf..33fc15674 100644
--- a/test/unit/prop/cnf_stream_white.h
+++ b/test/unit/prop/cnf_stream_white.h
@@ -174,8 +174,8 @@ class CnfStreamWhite : public CxxTest::TestSuite {
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node c = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::AND, a, b, c),
- false, false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::AND, a, b, c), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
@@ -189,26 +189,27 @@ class CnfStreamWhite : public CxxTest::TestSuite {
Node f = d_nodeManager->mkVar(d_nodeManager->booleanType());
d_cnfStream->convertAndAssert(
d_nodeManager->mkNode(
- kind::IMPLIES, d_nodeManager->mkNode(kind::AND, a, b),
+ kind::IMPLIES,
+ d_nodeManager->mkNode(kind::AND, a, b),
d_nodeManager->mkNode(
- kind::EQUAL, d_nodeManager->mkNode(kind::OR, c, d),
+ kind::EQUAL,
+ d_nodeManager->mkNode(kind::OR, c, d),
d_nodeManager->mkNode(kind::NOT,
d_nodeManager->mkNode(kind::XOR, e, f)))),
- false, false, RULE_INVALID, Node::null());
+ false,
+ false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
void testTrue() {
NodeManagerScope nms(d_nodeManager);
- d_cnfStream->convertAndAssert(d_nodeManager->mkConst(true), false, false,
- RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(d_nodeManager->mkConst(true), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
void testFalse() {
NodeManagerScope nms(d_nodeManager);
- d_cnfStream->convertAndAssert(d_nodeManager->mkConst(false), false, false,
- RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(d_nodeManager->mkConst(false), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
@@ -216,8 +217,8 @@ class CnfStreamWhite : public CxxTest::TestSuite {
NodeManagerScope nms(d_nodeManager);
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::EQUAL, a, b), false,
- false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::EQUAL, a, b), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
@@ -225,33 +226,16 @@ class CnfStreamWhite : public CxxTest::TestSuite {
NodeManagerScope nms(d_nodeManager);
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::IMPLIES, a, b),
- false, false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::IMPLIES, a, b), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
- // ITEs should be removed before going to CNF
- // void testIte() {
- // NodeManagerScope nms(d_nodeManager);
- // d_cnfStream->convertAndAssert(
- // d_nodeManager->mkNode(
- // kind::EQUAL,
- // d_nodeManager->mkNode(
- // kind::ITE,
- // d_nodeManager->mkVar(d_nodeManager->booleanType()),
- // d_nodeManager->mkVar(d_nodeManager->integerType()),
- // d_nodeManager->mkVar(d_nodeManager->integerType())
- // ),
- // d_nodeManager->mkVar(d_nodeManager->integerType())
- // ), false, false, RULE_INVALID, Node::null());
- //
- //}
-
void testNot() {
NodeManagerScope nms(d_nodeManager);
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::NOT, a), false,
- false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::NOT, a), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
@@ -260,8 +244,8 @@ class CnfStreamWhite : public CxxTest::TestSuite {
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node c = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::OR, a, b, c),
- false, false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::OR, a, b, c), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
@@ -269,10 +253,10 @@ class CnfStreamWhite : public CxxTest::TestSuite {
NodeManagerScope nms(d_nodeManager);
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(a, false, false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(a, false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
d_satSolver->reset();
- d_cnfStream->convertAndAssert(b, false, false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(b, false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
@@ -280,8 +264,8 @@ class CnfStreamWhite : public CxxTest::TestSuite {
NodeManagerScope nms(d_nodeManager);
Node a = d_nodeManager->mkVar(d_nodeManager->booleanType());
Node b = d_nodeManager->mkVar(d_nodeManager->booleanType());
- d_cnfStream->convertAndAssert(d_nodeManager->mkNode(kind::XOR, a, b), false,
- false, RULE_INVALID, Node::null());
+ d_cnfStream->convertAndAssert(
+ d_nodeManager->mkNode(kind::XOR, a, b), false, false);
TS_ASSERT(d_satSolver->addClauseCalled());
}
diff --git a/test/unit/theory/theory_engine_white.h b/test/unit/theory/theory_engine_white.h
index a67d0aeb2..ae4264aa2 100644
--- a/test/unit/theory/theory_engine_white.h
+++ b/test/unit/theory/theory_engine_white.h
@@ -41,7 +41,6 @@
#include "theory/theory_rewriter.h"
#include "theory/valuation.h"
#include "util/integer.h"
-#include "util/proof.h"
#include "util/rational.h"
using namespace CVC4;
@@ -55,13 +54,9 @@ using namespace CVC4::theory::bv;
using namespace std;
class FakeOutputChannel : public OutputChannel {
- void conflict(TNode n, std::unique_ptr<Proof> pf) override
- {
- Unimplemented();
- }
+ void conflict(TNode n) override { Unimplemented(); }
bool propagate(TNode n) override { Unimplemented(); }
LemmaStatus lemma(TNode n,
- ProofRule rule,
LemmaProperty p = LemmaProperty::NONE) override
{
Unimplemented();
diff --git a/test/unit/theory/theory_white.h b/test/unit/theory/theory_white.h
index 9693000a3..e90bd56a2 100644
--- a/test/unit/theory/theory_white.h
+++ b/test/unit/theory/theory_white.h
@@ -26,7 +26,6 @@
#include "smt/smt_engine_scope.h"
#include "theory/theory.h"
#include "theory/theory_engine.h"
-#include "util/proof.h"
#include "util/resource_manager.h"
using namespace CVC4;
@@ -48,10 +47,7 @@ class TestOutputChannel : public OutputChannel {
~TestOutputChannel() override {}
void safePoint(ResourceManager::Resource r) override {}
- void conflict(TNode n, std::unique_ptr<Proof> pf) override
- {
- push(CONFLICT, n);
- }
+ void conflict(TNode n) override { push(CONFLICT, n); }
bool propagate(TNode n) override {
push(PROPAGATE, n);
@@ -59,7 +55,6 @@ class TestOutputChannel : public OutputChannel {
}
LemmaStatus lemma(TNode n,
- ProofRule rule,
LemmaProperty p = LemmaProperty::NONE) override
{
push(LEMMA, n);
@@ -298,7 +293,7 @@ class TheoryBlack : public CxxTest::TestSuite {
void testOutputChannel() {
Node n = atom0.orNode(atom1);
- d_outputChannel.lemma(n, RULE_INVALID);
+ d_outputChannel.lemma(n);
d_outputChannel.split(atom0);
Node s = atom0.orNode(atom0.notNode());
TS_ASSERT_EQUALS(d_outputChannel.d_callHistory.size(), 2u);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback