diff options
202 files changed, 3735 insertions, 2155 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95c6c035c..2a41efb59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,6 +82,7 @@ jobs: # # https://github.com/actions/runner/blob/master/docs/adrs/0278-env-context.md#dont-populate-the-env-context-with-environment-variables-from-runner-machine echo "image_version=$ImageVersion" >> $GITHUB_ENV + echo "num_proc=$(nproc)" >> $GITHUB_ENV echo "/usr/lib/ccache" >> $GITHUB_PATH # Note: macOS comes with a libedit; it does not need to brew-installed @@ -103,6 +104,7 @@ jobs: # # https://github.com/actions/runner/blob/master/docs/adrs/0278-env-context.md#dont-populate-the-env-context-with-environment-variables-from-runner-machine echo "image_version=$ImageVersion" >> $GITHUB_ENV + echo "num_proc=$(sysctl -n hw.logicalcpu)" >> $GITHUB_ENV echo "/usr/local/opt/ccache/libexec" >> $GITHUB_PATH - name: Install Python Dependencies @@ -191,14 +193,14 @@ jobs: --werror - name: Build - run: make -j2 + run: make -j${{ env.num_proc }} working-directory: build - name: ccache Statistics run: ccache -s - name: Run CTest - run: make -j2 check + run: make -j${{ env.num_proc }} check env: ARGS: --output-on-failure -LE regress[${{ matrix.exclude_regress }}] CVC5_REGRESSION_ARGS: --no-early-exit @@ -207,7 +209,7 @@ jobs: - name: Install Check run: | - make -j2 install + make -j${{ env.num_proc }} install echo -e "#include <cvc5/cvc5.h>\nint main() { cvc5::api::Solver s; return 0; }" > /tmp/test.cpp g++ -std=c++11 /tmp/test.cpp -I install/include -L install/lib -lcvc5 working-directory: build @@ -225,14 +227,14 @@ jobs: mkdir build cd build cmake .. -DCMAKE_PREFIX_PATH=$(pwd)/../../build/install/lib/cmake - make -j2 - ctest -j2 --output-on-failure + make -j${{ env.num_proc }} + ctest -j${{ env.num_proc }} --output-on-failure working-directory: examples - name: Build Documentation if: matrix.build-documentation run: | - make -j2 docs-gh + make -j${{ env.num_proc }} docs-gh if [ "${{ github.event_name }}" == "pull_request" ] ; then echo "${{ github.event.number }}" > docs/sphinx-gh/prnum fi diff --git a/CMakeLists.txt b/CMakeLists.txt index d7512e874..3780b0b5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,7 +118,6 @@ option(ENABLE_PROFILING "Enable support for gprof profiling") # > allows to detect if set by user (default: IGNORE) # > only necessary for options set for ENABLE_BEST cvc5_option(USE_ABC "Use ABC for AIG bit-blasting") -cvc5_option(USE_CADICAL "Use CaDiCaL SAT solver") cvc5_option(USE_CLN "Use CLN instead of GMP") cvc5_option(USE_CRYPTOMINISAT "Use CryptoMiniSat SAT solver") cvc5_option(USE_GLPK "Use GLPK simplex solver") @@ -127,7 +126,7 @@ cvc5_option(USE_EDITLINE "Use Editline for better interactive support") # >> 2-valued: ON OFF # > for options where we don't need to detect if set by user (default: OFF) option(USE_POLY "Use LibPoly for polynomial arithmetic") -option(USE_SYMFPU "Use SymFPU for floating point support") +option(USE_COCOA "Use CoCoALib for further polynomial operations") option(USE_PYTHON2 "Force Python 2 (deprecated)") # Custom install directories for dependencies @@ -417,10 +416,7 @@ if(USE_ABC) add_definitions(-DCVC5_USE_ABC ${ABC_ARCH_FLAGS}) endif() -if(USE_CADICAL) - find_package(CaDiCaL REQUIRED) - add_definitions(-DCVC5_USE_CADICAL) -endif() +find_package(CaDiCaL REQUIRED) if(USE_CLN) set(GPL_LIBS "${GPL_LIBS} cln") @@ -462,6 +458,11 @@ else() set(CVC5_USE_POLY_IMP 0) endif() +if(USE_COCOA) + find_package(CoCoA REQUIRED 0.99711) + add_definitions(-DCVC5_USE_COCOA) +endif() + if(USE_EDITLINE) find_package(Editline REQUIRED) set(HAVE_LIBEDITLINE 1) @@ -470,13 +471,7 @@ if(USE_EDITLINE) endif() endif() -if(USE_SYMFPU) - find_package(SymFPU REQUIRED) - add_definitions(-DCVC5_USE_SYMFPU) - set(CVC5_USE_SYMFPU 1) -else() - set(CVC5_USE_SYMFPU 0) -endif() +find_package(SymFPU REQUIRED) if(GPL_LIBS) if(NOT ENABLE_GPL) @@ -652,11 +647,11 @@ print_config("Java bindings " ${BUILD_BINDINGS_JAVA}) print_config("Python2 " ${USE_PYTHON2}) message("") print_config("ABC " ${USE_ABC}) -print_config("CaDiCaL " ${USE_CADICAL}) print_config("CryptoMiniSat " ${USE_CRYPTOMINISAT}) print_config("GLPK " ${USE_GLPK}) print_config("Kissat " ${USE_KISSAT}) print_config("LibPoly " ${USE_POLY}) +print_config("CoCoALib " ${USE_COCOA}) message("") print_config("Build libcvc5 only " ${BUILD_LIB_ONLY}) @@ -666,7 +661,6 @@ else() print_config("MP library " "gmp") endif() print_config("Editline " ${USE_EDITLINE}) -print_config("SymFPU " ${USE_SYMFPU}) message("") print_config("Api docs " ${BUILD_DOCS}) message("") diff --git a/INSTALL.md b/INSTALL.md index 41f770288..1a9c03476 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -57,6 +57,7 @@ minimum versions; more recent versions should be compatible. - [GMP v6.1 (GNU Multi-Precision arithmetic library)](https://gmplib.org) - [ANTLR 3.4](http://www.antlr3.org/) - [Java >= 1.6](https://www.java.com) +- [SymFPU](https://github.com/martin-cs/symfpu/tree/CVC4) ### ANTLR 3.4 parser generator @@ -74,8 +75,6 @@ cross-compile, or you want to build cvc5 statically but the distribution does not ship static libraries, cvc5 builds GMP automatically when `--auto-download` is given. -## Optional Dependencies - ### SymFPU (Support for the Theory of Floating Point Numbers) [SymFPU](https://github.com/martin-cs/symfpu/tree/CVC4) @@ -83,7 +82,8 @@ is an implementation of SMT-LIB/IEEE-754 floating-point operations in terms of bit-vector operations. It is required for supporting the theory of floating-point numbers and can be downloaded and built automatically. -Configure cvc5 with `configure.sh --symfpu` to build with this dependency. + +## Optional Dependencies ### CaDiCaL (Optional SAT solver) @@ -4,6 +4,8 @@ Changes since CVC4 1.8 ====================== New Features: +* CaDiCaL is now a required dependency. +* SymFPU is now a required dependency. * New unsat-core production modes based on the new proof infrastructure (`--unsat-cores-mode=sat-proof`) and on the solving-under-assumption feature of Minisat (`--unsat-cores-mode=assumptions`). The mode based on SAT diff --git a/cmake/FindCaDiCaL.cmake b/cmake/FindCaDiCaL.cmake index 80fa2e4ec..ce70c5292 100644 --- a/cmake/FindCaDiCaL.cmake +++ b/cmake/FindCaDiCaL.cmake @@ -47,9 +47,7 @@ if(NOT CaDiCaL_FOUND_SYSTEM) include(CheckSymbolExists) include(ExternalProject) - fail_if_include_missing("sys/resource.h" "CaDiCaL") - - set(CaDiCaL_VERSION "88623ef0866370448c34f6e320c148fc18e6f4cc") + set(CaDiCaL_VERSION "rel-1.4.1") # avoid configure script and instantiate the makefile manually the configure # scripts unnecessarily fails for cross compilation thus we do the bare @@ -74,7 +72,7 @@ if(NOT CaDiCaL_FOUND_SYSTEM) ${COMMON_EP_CONFIG} BUILD_IN_SOURCE ON URL https://github.com/arminbiere/cadical/archive/${CaDiCaL_VERSION}.tar.gz - URL_HASH SHA1=16ea51f0274d699f3d3c9e3be7083179eed83abf + URL_HASH SHA1=ad3be225f20e5c5b3883290478282698624c14a5 CONFIGURE_COMMAND mkdir -p <SOURCE_DIR>/build # avoid configure script, prepare the makefile manually COMMAND ${CMAKE_COMMAND} -E copy <SOURCE_DIR>/makefile.in @@ -83,11 +81,6 @@ if(NOT CaDiCaL_FOUND_SYSTEM) sed -i.orig -e "s,@CXX@,${CMAKE_CXX_COMPILER}," -e "s,@CXXFLAGS@,${CXXFLAGS}," -e "s,@MAKEFLAGS@,," <SOURCE_DIR>/build/makefile - # This is a temporary patch until fixed upstream - PATCH_COMMAND - sed -i.orig - "s,#include <vector>,#include <vector>\\\\n#include <cstddef>," - <SOURCE_DIR>/src/reap.hpp BUILD_COMMAND ${make_cmd} -C <SOURCE_DIR>/build libcadical.a INSTALL_COMMAND ${CMAKE_COMMAND} -E copy <SOURCE_DIR>/build/libcadical.a <INSTALL_DIR>/lib/libcadical.a @@ -110,6 +103,16 @@ set_target_properties( CaDiCaL PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CaDiCaL_INCLUDE_DIR}" ) +if (WIN32) + # The Windows version of CaDiCaL calls GetProcessMemoryInfo(), which is + # defined in the Process Status API (psapi), so we declare it as a dependency + # of the CaDiCaL library (without this, linking a static cvc5 executable + # fails). + set_target_properties( + CaDiCaL PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES psapi + ) +endif () + mark_as_advanced(CaDiCaL_FOUND) mark_as_advanced(CaDiCaL_FOUND_SYSTEM) mark_as_advanced(CaDiCaL_INCLUDE_DIR) diff --git a/cmake/FindCoCoA.cmake b/cmake/FindCoCoA.cmake new file mode 100644 index 000000000..1a4f82e9f --- /dev/null +++ b/cmake/FindCoCoA.cmake @@ -0,0 +1,96 @@ +############################################################################### +# Top contributors (to current version): +# Gereon Kremer +# +# This file is part of the cvc5 project. +# +# Copyright (c) 2009-2021 by the authors listed in the file AUTHORS +# in the top-level source directory and their institutional affiliations. +# All rights reserved. See the file COPYING in the top-level source +# directory for licensing information. +# ############################################################################# +# +# Find CoCoA +# CoCoA_FOUND - system has CoCoA lib +# CoCoA_INCLUDE_DIR - the CoCoA include directory +# CoCoA_LIBRARIES - Libraries needed to use CoCoA +## + +include(deps-helper) + +find_path(CoCoA_INCLUDE_DIR NAMES CoCoA/CoCoA.h) +find_library(CoCoA_LIBRARIES NAMES CoCoA) + +set(CoCoA_FOUND_SYSTEM FALSE) +if(CoCoA_INCLUDE_DIR AND CoCoA_LIBRARIES) + set(CoCoA_FOUND_SYSTEM TRUE) + + file(STRINGS ${CoCoA_INCLUDE_DIR}/CoCoA/library.H CoCoA_VERSION + REGEX "^COCOALIB_VERSION=.*" + ) + string(REGEX MATCH "[0-9]+\\.[0-9]+" CoCoA_VERSION "${CoCoA_VERSION}") + + check_system_version("CoCoA") +endif() + +if(NOT CoCoA_FOUND_SYSTEM) + check_ep_downloaded("CoCoA-EP") + if(NOT CoCoA-EP_DOWNLOADED) + check_auto_download("CoCoA" "--no-cocoa") + endif() + + include(ExternalProject) + + set(CoCoA_VERSION "0.99712") + + if("${CMAKE_GENERATOR}" STREQUAL "Unix Makefiles") + # use $(MAKE) instead of "make" to allow for parallel builds + set(make_cmd "$(MAKE)") + else() + # $(MAKE) does not work with ninja + set(make_cmd "make") + endif() + + ExternalProject_Add( + CoCoA-EP + ${COMMON_EP_CONFIG} + URL "http://cocoa.dima.unige.it/cocoalib/tgz/CoCoALib-${CoCoA_VERSION}.tgz" + URL_HASH SHA1=873d0b60800cd3852939816ce0aa2e7f72dac4ce + BUILD_IN_SOURCE YES + CONFIGURE_COMMAND ./configure --prefix=<INSTALL_DIR> + BUILD_COMMAND ${make_cmd} library + ) + # Remove install directory before make install. CoCoA will complain otherwise + ExternalProject_Add_Step( + CoCoA-EP clear-install + COMMAND ${CMAKE_COMMAND} -E remove_directory <INSTALL_DIR>/include/CoCoA-${CoCoA_VERSION} + DEPENDEES build + DEPENDERS install + ) + + add_dependencies(CoCoA-EP GMP) + + set(CoCoA_INCLUDE_DIR "${DEPS_BASE}/include/") + set(CoCoA_LIBRARIES "${DEPS_BASE}/lib/libcocoa.a") +endif() + +set(CoCoA_FOUND TRUE) + +add_library(CoCoA STATIC IMPORTED GLOBAL) +set_target_properties(CoCoA PROPERTIES IMPORTED_LOCATION "${CoCoA_LIBRARIES}") +set_target_properties( + CoCoA PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CoCoA_INCLUDE_DIR}" +) +set_target_properties(CoCoA PROPERTIES INTERFACE_LINK_LIBRARIES GMP) + +mark_as_advanced(CoCoA_FOUND) +mark_as_advanced(CoCoA_FOUND_SYSTEM) +mark_as_advanced(CoCoA_INCLUDE_DIR) +mark_as_advanced(CoCoA_LIBRARIES) + +if(CoCoA_FOUND_SYSTEM) + message(STATUS "Found CoCoA ${CoCoA_VERSION}: ${CoCoA_LIBRARIES}") +else() + message(STATUS "Building CoCoA ${CoCoA_VERSION}: ${CoCoA_LIBRARIES}") + add_dependencies(CoCoA CoCoA-EP) +endif() diff --git a/cmake/FindPoly.cmake b/cmake/FindPoly.cmake index 3fa35b951..e11d85c3f 100644 --- a/cmake/FindPoly.cmake +++ b/cmake/FindPoly.cmake @@ -45,16 +45,12 @@ if(NOT Poly_FOUND_SYSTEM) include(ExternalProject) - set(Poly_VERSION "6309f7a94e97753ef3ecb7dbfcbd435d558c4bd6") + set(Poly_VERSION "f543721215ec17a724dc86820a0430233931a637") check_if_cross_compiling(CCWIN "Windows" "") if(CCWIN) # Roughly following https://stackoverflow.com/a/44383330/2375725 set(patchcmd - COMMAND - patch - <SOURCE_DIR>/src/CMakeLists.txt - ${CMAKE_CURRENT_LIST_DIR}/deps-utils/Poly-patch-cmake.patch # Avoid %z and %llu format specifiers COMMAND find <SOURCE_DIR>/ -type f -exec sed -i.orig "s/%z[diu]/%\" PRIu64 \"/g" {} + @@ -78,7 +74,7 @@ if(NOT Poly_FOUND_SYSTEM) Poly-EP ${COMMON_EP_CONFIG} URL https://github.com/SRI-CSL/libpoly/archive/${Poly_VERSION}.tar.gz - URL_HASH SHA1=7bac7aa4aab8201f5b14494fc486fa2b0ffb7b31 + URL_HASH SHA1=3fad3b310727fa0fb2fdff5a8857709d12f72e04 PATCH_COMMAND sed -i.orig "s,add_subdirectory(test/polyxx),add_subdirectory(test/polyxx EXCLUDE_FROM_ALL),g" diff --git a/cmake/deps-utils/Poly-patch-cmake.patch b/cmake/deps-utils/Poly-patch-cmake.patch deleted file mode 100644 index fe8528f70..000000000 --- a/cmake/deps-utils/Poly-patch-cmake.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index f91e3e8..6205689 100755 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -38,7 +38,7 @@ set(poly_SOURCES - ) - - if (NOT HAVE_OPEN_MEMSTREAM) -- set(poly_SOURCES "utils/open_memstream.c ${poly_SOURCES}") -+ set(poly_SOURCES utils/open_memstream.c ${poly_SOURCES}) - endif() - - set(polyxx_SOURCES diff --git a/configure.sh b/configure.sh index 3e59cadc9..4ba153a75 100755 --- a/configure.sh +++ b/configure.sh @@ -59,11 +59,10 @@ The following flags enable optional packages (disable with --no-<option name>). --cln use CLN instead of GMP --glpk use GLPK simplex solver --abc use the ABC AIG library - --cadical use the CaDiCaL SAT solver [default=yes] --cryptominisat use the CryptoMiniSat SAT solver --kissat use the Kissat SAT solver --poly use the LibPoly library [default=yes] - --symfpu use SymFPU for floating point solver [default=yes] + --cocoa use the CoCoA library --editline support the editline library Optional Path to Optional Packages: @@ -108,7 +107,6 @@ abc=default asan=default assertions=default auto_download=default -cadical=ON cln=default comp_inc=default coverage=default @@ -121,6 +119,7 @@ glpk=default gpl=default kissat=default poly=ON +cocoa=default muzzle=default ninja=default profiling=default @@ -131,7 +130,6 @@ editline=default shared=default static_binary=default statistics=default -symfpu=ON tracing=default tsan=default ubsan=default @@ -174,7 +172,6 @@ do # Best configuration --best) abc=ON - cadical=ON cln=ON cryptominisat=ON glpk=ON @@ -198,9 +195,6 @@ do --name) die "missing argument to $1 (try -h)" ;; --name=*) build_dir=${1##*=} ;; - --cadical) cadical=ON;; - --no-cadical) cadical=OFF;; - --cln) cln=ON;; --no-cln) cln=OFF;; @@ -240,6 +234,9 @@ do --poly) poly=ON;; --no-poly) poly=OFF;; + --cocoa) cocoa=ON;; + --no-cocoa) cocoa=OFF;; + --muzzle) muzzle=ON;; --no-muzzle) muzzle=OFF;; @@ -255,9 +252,6 @@ do --statistics) statistics=ON;; --no-statistics) statistics=OFF;; - --symfpu) symfpu=ON;; - --no-symfpu) symfpu=OFF;; - --tracing) tracing=ON;; --no-tracing) tracing=OFF;; @@ -379,8 +373,6 @@ cmake_opts="" && cmake_opts="$cmake_opts -DUSE_EDITLINE=$editline" [ $abc != default ] \ && cmake_opts="$cmake_opts -DUSE_ABC=$abc" -[ $cadical != default ] \ - && cmake_opts="$cmake_opts -DUSE_CADICAL=$cadical" [ $cln != default ] \ && cmake_opts="$cmake_opts -DUSE_CLN=$cln" [ $cryptominisat != default ] \ @@ -391,8 +383,8 @@ cmake_opts="" && cmake_opts="$cmake_opts -DUSE_KISSAT=$kissat" [ $poly != default ] \ && cmake_opts="$cmake_opts -DUSE_POLY=$poly" -[ $symfpu != default ] \ - && cmake_opts="$cmake_opts -DUSE_SYMFPU=$symfpu" +[ $cocoa != default ] \ + && cmake_opts="$cmake_opts -DUSE_COCOA=$cocoa" [ "$abc_dir" != default ] \ && cmake_opts="$cmake_opts -DABC_DIR=$abc_dir" [ "$glpk_dir" != default ] \ diff --git a/contrib/competitions/smt-comp/run-script-smtcomp-current b/contrib/competitions/smt-comp/run-script-smtcomp-current index ecc6ce5fe..9b4f534b0 100755 --- a/contrib/competitions/smt-comp/run-script-smtcomp-current +++ b/contrib/competitions/smt-comp/run-script-smtcomp-current @@ -1,6 +1,6 @@ #!/bin/bash -cvc5=./cvc5 +cvc5=$(dirname "$(readlink -f "$0")")/cvc5 bench="$1" # Output other than "sat"/"unsat" is either written to stderr or to "err.log" @@ -75,7 +75,7 @@ QF_NRA) finishwith --decision=internal --nl-ext=none ;; # all logics with UF + quantifiers should either fall under this or special cases below -ALIA|AUFLIA|AUFLIRA|AUFNIRA|UF|UFIDL|UFLIA|UFLRA|UFNIA|UFDT|UFDTLIA|AUFDTLIA|AUFBVDTLIA|AUFNIA|UFFPDTLIRA|UFFPDTNIRA) +ALIA|AUFLIA|AUFLIRA|AUFNIRA|UF|UFBVLIA|UFIDL|UFLIA|UFLRA|UFNIA|UFDT|UFDTLIA|AUFDTLIA|AUFBV|AUFBVDTLIA|AUFBVFP|AUFNIA|UFFPDTLIRA|UFFPDTNIRA) # initial runs 1 min trywith 30 --simplification=none --full-saturate-quant trywith 30 --no-e-matching --full-saturate-quant @@ -112,7 +112,7 @@ UFBV) trywith 30 --full-saturate-quant --no-cegqi-innermost --global-negate finishwith --finite-model-find ;; -BV) +ABV|BV) trywith 120 --full-saturate-quant trywith 120 --sygus-inst trywith 300 --full-saturate-quant --cegqi-nested-qe --decision=internal @@ -121,7 +121,7 @@ BV) # finish 10min finishwith --full-saturate-quant --no-cegqi-innermost --global-negate ;; -ABVFP|BVFP|FP|NIA|NRA) +ABVFP|ABVFPLRA|BVFP|FP|NIA|NRA) trywith 300 --full-saturate-quant --nl-ext-tplanes --fp-exp finishwith --sygus-inst --fp-exp ;; @@ -131,8 +131,8 @@ LIA|LRA) finishwith --full-saturate-quant --cegqi-nested-qe --decision=internal ;; QF_AUFBV) - trywith 600 --ite-simp - finishwith --decision=justification-stoponly --ite-simp + trywith 600 + finishwith --decision=justification-stoponly ;; QF_ABV) trywith 50 --ite-simp --simp-with-care --repeat-simp --arrays-weak-equiv diff --git a/contrib/competitions/smt-comp/run-script-smtcomp-current-incremental b/contrib/competitions/smt-comp/run-script-smtcomp-current-incremental index 21bb2f6e0..79df91d69 100755 --- a/contrib/competitions/smt-comp/run-script-smtcomp-current-incremental +++ b/contrib/competitions/smt-comp/run-script-smtcomp-current-incremental @@ -1,6 +1,6 @@ #!/bin/bash -cvc5=./cvc5 +cvc5=$(dirname "$(readlink -f "$0")")/cvc5 line="" while [[ -z "$line" ]]; do @@ -26,50 +26,20 @@ function runcvc5 { # we run in this way for line-buffered input, otherwise memory's a # concern (plus it mimics what we'll end up getting from an # application-track trace runner?) - $cvc5 --force-logic="$logic" -L smt2.6 --print-success --no-type-checking --no-interactive "$@" <&0- + $cvc5 --incremental --force-logic="$logic" -L smt2.6 --print-success --no-type-checking --no-interactive "$@" <&0- } case "$logic" in -ALIA|ANIA|AUFNIRA|LIA|LRA|QF_ALIA|QF_ANIA|QF_AUFBVLIA|QF_AUFBVNIA|QF_LIA|QF_LRA|QF_NIA|QF_UFBVLIA|QF_UFLIA|QF_UFLRA|QF_UFNIA|UFLRA) - runcvc5 --tear-down-incremental=1 - ;; QF_AUFLIA) - runcvc5 --tear-down-incremental=1 --no-arrays-eager-index --arrays-eager-lemmas + runcvc5 --no-arrays-eager-index --arrays-eager-lemmas ;; QF_BV) - runcvc5 --incremental --bitblast=eager --bv-assert-input - ;; -QF_UFBV) - runcvc5 --incremental --bv-assert-input - ;; -QF_UF) - runcvc5 --incremental - ;; -QF_AUFBV) - runcvc5 --incremental --bv-assert-input - ;; -QF_ABV) - runcvc5 --incremental --bv-assert-input - ;; -ABVFP) - runcvc5 --incremental - ;; -BVFP) - runcvc5 --incremental - ;; -QF_ABVFP) - runcvc5 --incremental - ;; -QF_BVFP) - runcvc5 --incremental - ;; -QF_FP) - runcvc5 --incremental + runcvc5 --bitblast=eager ;; *) # just run the default - runcvc5 --incremental + runcvc5 ;; esac diff --git a/contrib/competitions/smt-comp/run-script-smtcomp-current-model-validation b/contrib/competitions/smt-comp/run-script-smtcomp-current-model-validation index fe8d4ae44..0998e9949 100755 --- a/contrib/competitions/smt-comp/run-script-smtcomp-current-model-validation +++ b/contrib/competitions/smt-comp/run-script-smtcomp-current-model-validation @@ -1,6 +1,6 @@ #!/bin/bash -cvc5=./cvc5 +cvc5=$(dirname "$(readlink -f "$0")")/cvc5 bench="$1" logic=$(expr "$(grep -m1 '^[^;]*set-logic' "$bench")" : ' *(set-logic *\([A-Z_]*\) *) *$') @@ -20,7 +20,7 @@ QF_LIA) finishwith --miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --use-soi --pb-rewrites --ite-simp --simp-ite-compress ;; QF_BV) - finishwith --bitblast=eager --bv-assert-input + finishwith --bv-assert-input ;; *) # just run the default diff --git a/contrib/competitions/smt-comp/run-script-smtcomp-current-unsat-cores b/contrib/competitions/smt-comp/run-script-smtcomp-current-unsat-cores index e9753781d..75e3bfc82 100755 --- a/contrib/competitions/smt-comp/run-script-smtcomp-current-unsat-cores +++ b/contrib/competitions/smt-comp/run-script-smtcomp-current-unsat-cores @@ -1,6 +1,6 @@ #!/bin/bash -cvc5=./cvc5 +cvc5=$(dirname "$(readlink -f "$0")")/cvc5 bench="$1" logic=$(expr "$(grep -m1 '^[^;]*set-logic' "$bench")" : ' *(set-logic *\([A-Z_]*\) *) *$') @@ -20,10 +20,7 @@ QF_LIA) finishwith --miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --use-soi ;; QF_NIA) - finishwith --nl-ext --nl-ext-tplanes - ;; -QF_NRA) - finishwith --nl-ext --nl-ext-tplanes + finishwith --nl-ext-tplanes ;; # all logics with UF + quantifiers should either fall under this or special cases below ALIA|AUFLIA|AUFLIRA|AUFNIRA|UF|UFIDL|UFLIA|UFLRA|UFNIA|UFDT|UFDTLIA|AUFDTLIA|AUFBVDTLIA|AUFNIA|ABVFP|BVFP|FP) diff --git a/contrib/competitions/smt-comp/run-script-smtcomp2021 b/contrib/competitions/smt-comp/run-script-smtcomp2021 new file mode 100755 index 000000000..9b4f534b0 --- /dev/null +++ b/contrib/competitions/smt-comp/run-script-smtcomp2021 @@ -0,0 +1,177 @@ +#!/bin/bash + +cvc5=$(dirname "$(readlink -f "$0")")/cvc5 +bench="$1" + +# Output other than "sat"/"unsat" is either written to stderr or to "err.log" +# in the directory specified by $2 if it has been set (e.g. when running on +# StarExec). +out_file=/dev/stderr + +if [ -n "$STAREXEC_WALLCLOCK_LIMIT" ]; then + # If we are running on StarExec, don't print to `/dev/stderr/` even when $2 + # is not provided. + out_file="/dev/null" +fi + +if [ -n "$2" ]; then + out_file="$2/err.log" +fi + +logic=$(expr "$(grep -m1 '^[^;]*set-logic' "$bench")" : ' *(set-logic *\([A-Z_]*\) *) *$') + +# use: trywith [params..] +# to attempt a run. Only thing printed on stdout is "sat" or "unsat", in which +# case this run script terminates immediately. Otherwise, this function +# returns normally and prints the output of the solver to $out_file. +function trywith { + limit=$1; shift; + result="$({ ulimit -S -t "$limit"; $cvc5 -L smt2.6 --no-incremental --no-type-checking --no-interactive "$@" $bench; } 2>&1)" + case "$result" in + sat|unsat) echo "$result"; exit 0;; + *) echo "$result" &> "$out_file";; + esac +} + +# use: finishwith [params..] +# to run cvc5. Only "sat" or "unsat" are output. Other outputs are written to +# $out_file. +function finishwith { + result="$({ $cvc5 -L smt2.6 --no-incremental --no-type-checking --no-interactive "$@" $bench; } 2>&1)" + case "$result" in + sat|unsat) echo "$result"; exit 0;; + *) echo "$result" &> "$out_file";; + esac +} + +# the following is designed for a run time of 20 min. +case "$logic" in + +QF_LRA) + trywith 200 --miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --unconstrained-simp --use-soi + finishwith --no-restrict-pivots --use-soi --new-prop --unconstrained-simp + ;; +QF_LIA) + # same as QF_LRA but add --pb-rewrites + finishwith --miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --unconstrained-simp --use-soi --pb-rewrites --ite-simp --simp-ite-compress + ;; +QF_NIA) + trywith 420 --nl-ext-tplanes --decision=justification + trywith 60 --nl-ext-tplanes --decision=internal + trywith 60 --nl-ext-tplanes --decision=justification-old + trywith 60 --no-nl-ext-tplanes --decision=internal + trywith 60 --no-arith-brab --nl-ext-tplanes --decision=internal + # this totals up to more than 20 minutes, although notice that smaller bit-widths may quickly fail + trywith 300 --solve-int-as-bv=2 --bitblast=eager + trywith 300 --solve-int-as-bv=4 --bitblast=eager + trywith 300 --solve-int-as-bv=8 --bitblast=eager + trywith 300 --solve-int-as-bv=16 --bitblast=eager + trywith 600 --solve-int-as-bv=32 --bitblast=eager + finishwith --nl-ext-tplanes --decision=internal + ;; +QF_NRA) + trywith 600 --decision=justification + trywith 300 --decision=internal --no-nl-cad --nl-ext=full --nl-ext-tplanes + finishwith --decision=internal --nl-ext=none + ;; +# all logics with UF + quantifiers should either fall under this or special cases below +ALIA|AUFLIA|AUFLIRA|AUFNIRA|UF|UFBVLIA|UFIDL|UFLIA|UFLRA|UFNIA|UFDT|UFDTLIA|AUFDTLIA|AUFBV|AUFBVDTLIA|AUFBVFP|AUFNIA|UFFPDTLIRA|UFFPDTNIRA) + # initial runs 1 min + trywith 30 --simplification=none --full-saturate-quant + trywith 30 --no-e-matching --full-saturate-quant + trywith 30 --no-e-matching --full-saturate-quant --fs-sum + # trigger selections 3 min + trywith 30 --relevant-triggers --full-saturate-quant + trywith 30 --trigger-sel=max --full-saturate-quant + trywith 30 --multi-trigger-when-single --full-saturate-quant + trywith 30 --multi-trigger-when-single --multi-trigger-priority --full-saturate-quant + trywith 30 --multi-trigger-cache --full-saturate-quant + trywith 30 --no-multi-trigger-linear --full-saturate-quant + # other 4 min + trywith 30 --pre-skolem-quant --full-saturate-quant + trywith 30 --inst-when=full --full-saturate-quant + trywith 30 --no-e-matching --no-quant-cf --full-saturate-quant + trywith 30 --full-saturate-quant --quant-ind + trywith 30 --decision=internal --simplification=none --no-inst-no-entail --no-quant-cf --full-saturate-quant + trywith 30 --decision=internal --full-saturate-quant --fs-sum + trywith 30 --term-db-mode=relevant --full-saturate-quant + trywith 30 --fs-interleave --full-saturate-quant + # finite model find 3 min + trywith 30 --finite-model-find --mbqi=none + trywith 30 --finite-model-find --decision=internal + trywith 30 --finite-model-find --macros-quant --macros-quant-mode=all + trywith 60 --finite-model-find --fmf-inst-engine + # long runs 4 min + trywith 240 --finite-model-find --decision=internal + finishwith --full-saturate-quant + ;; +UFBV) + # most problems in UFBV are essentially BV + trywith 300 --sygus-inst + trywith 300 --full-saturate-quant --cegqi-nested-qe --decision=internal + trywith 30 --full-saturate-quant --no-cegqi-innermost --global-negate + finishwith --finite-model-find + ;; +ABV|BV) + trywith 120 --full-saturate-quant + trywith 120 --sygus-inst + trywith 300 --full-saturate-quant --cegqi-nested-qe --decision=internal + trywith 30 --full-saturate-quant --no-cegqi-bv + trywith 30 --full-saturate-quant --cegqi-bv-ineq=eq-slack + # finish 10min + finishwith --full-saturate-quant --no-cegqi-innermost --global-negate + ;; +ABVFP|ABVFPLRA|BVFP|FP|NIA|NRA) + trywith 300 --full-saturate-quant --nl-ext-tplanes --fp-exp + finishwith --sygus-inst --fp-exp + ;; +LIA|LRA) + trywith 30 --full-saturate-quant + trywith 300 --full-saturate-quant --cegqi-nested-qe + finishwith --full-saturate-quant --cegqi-nested-qe --decision=internal + ;; +QF_AUFBV) + trywith 600 + finishwith --decision=justification-stoponly + ;; +QF_ABV) + trywith 50 --ite-simp --simp-with-care --repeat-simp --arrays-weak-equiv + trywith 500 --arrays-weak-equiv + finishwith --ite-simp --simp-with-care --repeat-simp --arrays-weak-equiv + ;; +QF_BV|QF_UFBV) + finishwith --bitblast=eager --bv-assert-input + ;; +QF_AUFLIA) + finishwith --no-arrays-eager-index --arrays-eager-lemmas --decision=justification + ;; +QF_AX) + finishwith --no-arrays-eager-index --arrays-eager-lemmas --decision=internal + ;; +QF_AUFNIA) + finishwith --decision=justification --no-arrays-eager-index --arrays-eager-lemmas + ;; +QF_ALIA) + trywith 140 --decision=justification --arrays-weak-equiv + finishwith --decision=justification-stoponly --no-arrays-eager-index --arrays-eager-lemmas + ;; +QF_S|QF_SLIA) + trywith 300 --strings-exp --strings-fmf --no-jh-rlv-order + finishwith --strings-exp --no-jh-rlv-order + ;; +QF_ABVFP|QF_ABVFPLRA) + finishwith --fp-exp + ;; +QF_BVFP|QF_BVFPLRA) + finishwith --fp-exp + ;; +QF_FP|QF_FPLRA) + finishwith --fp-exp + ;; +*) + # just run the default + finishwith + ;; + +esac + diff --git a/contrib/competitions/smt-comp/run-script-smtcomp2021-incremental b/contrib/competitions/smt-comp/run-script-smtcomp2021-incremental new file mode 100755 index 000000000..79df91d69 --- /dev/null +++ b/contrib/competitions/smt-comp/run-script-smtcomp2021-incremental @@ -0,0 +1,45 @@ +#!/bin/bash + +cvc5=$(dirname "$(readlink -f "$0")")/cvc5 + +line="" +while [[ -z "$line" ]]; do + read line +done +if [ "$line" != '(set-option :print-success true)' ]; then + echo 'ERROR: first line supposed to be set-option :print-success, but got: "'"$line"'"' >&2 + exit 1 +fi +echo success +line="" +while [[ -z "$line" ]]; do + read line +done +logic=$(expr "$line" : ' *(set-logic *\([A-Z_]*\) *) *$') +if [ -z "$logic" ]; then + echo 'ERROR: second line supposed to be set-logic, but got: "'"$line"'"' >&2 + exit 1 +fi +echo success + +function runcvc5 { + # we run in this way for line-buffered input, otherwise memory's a + # concern (plus it mimics what we'll end up getting from an + # application-track trace runner?) + $cvc5 --incremental --force-logic="$logic" -L smt2.6 --print-success --no-type-checking --no-interactive "$@" <&0- +} + +case "$logic" in + +QF_AUFLIA) + runcvc5 --no-arrays-eager-index --arrays-eager-lemmas + ;; +QF_BV) + runcvc5 --bitblast=eager + ;; +*) + # just run the default + runcvc5 + ;; + +esac diff --git a/contrib/competitions/smt-comp/run-script-smtcomp2021-model-validation b/contrib/competitions/smt-comp/run-script-smtcomp2021-model-validation new file mode 100755 index 000000000..0998e9949 --- /dev/null +++ b/contrib/competitions/smt-comp/run-script-smtcomp2021-model-validation @@ -0,0 +1,30 @@ +#!/bin/bash + +cvc5=$(dirname "$(readlink -f "$0")")/cvc5 +bench="$1" + +logic=$(expr "$(grep -m1 '^[^;]*set-logic' "$bench")" : ' *(set-logic *\([A-Z_]*\) *) *$') + +# use: finishwith [params..] +# to run cvc5 and let it output whatever it will to stdout. +function finishwith { + $cvc5 -L smt2.6 --no-incremental --no-type-checking --no-interactive "$@" $bench +} + +case "$logic" in + +QF_LRA) + finishwith --no-restrict-pivots --use-soi --new-prop + ;; +QF_LIA) + finishwith --miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --use-soi --pb-rewrites --ite-simp --simp-ite-compress + ;; +QF_BV) + finishwith --bv-assert-input + ;; +*) + # just run the default + finishwith + ;; + +esac diff --git a/contrib/competitions/smt-comp/run-script-smtcomp2021-unsat-cores b/contrib/competitions/smt-comp/run-script-smtcomp2021-unsat-cores new file mode 100755 index 000000000..75e3bfc82 --- /dev/null +++ b/contrib/competitions/smt-comp/run-script-smtcomp2021-unsat-cores @@ -0,0 +1,83 @@ +#!/bin/bash + +cvc5=$(dirname "$(readlink -f "$0")")/cvc5 +bench="$1" + +logic=$(expr "$(grep -m1 '^[^;]*set-logic' "$bench")" : ' *(set-logic *\([A-Z_]*\) *) *$') + +# use: finishwith [params..] +# to run cvc5 and let it output whatever it will to stdout. +function finishwith { + $cvc5 -L smt2.6 --no-incremental --no-type-checking --no-interactive "$@" $bench +} + +case "$logic" in + +QF_LRA) + finishwith --no-restrict-pivots --use-soi --new-prop + ;; +QF_LIA) + finishwith --miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --use-soi + ;; +QF_NIA) + finishwith --nl-ext-tplanes + ;; +# all logics with UF + quantifiers should either fall under this or special cases below +ALIA|AUFLIA|AUFLIRA|AUFNIRA|UF|UFIDL|UFLIA|UFLRA|UFNIA|UFDT|UFDTLIA|AUFDTLIA|AUFBVDTLIA|AUFNIA|ABVFP|BVFP|FP) + finishwith --full-saturate-quant --fp-exp + ;; +UFBV) + finishwith --finite-model-find + ;; +BV) + finishwith --full-saturate-quant --decision=internal + ;; +LIA|LRA) + finishwith --full-saturate-quant --cegqi-nested-qe --decision=internal + ;; +NIA|NRA) + finishwith --full-saturate-quant --cegqi-nested-qe --decision=internal + ;; +QF_AUFBV) + finishwith --decision=justification-stoponly + ;; +QF_ABV) + finishwith --arrays-weak-equiv + ;; +QF_UFBV) + finishwith + ;; +QF_BV) + finishwith + ;; +QF_AUFLIA) + finishwith --no-arrays-eager-index --arrays-eager-lemmas --decision=justification + ;; +QF_AX) + finishwith --no-arrays-eager-index --arrays-eager-lemmas --decision=internal + ;; +QF_AUFNIA) + finishwith --decision=justification --no-arrays-eager-index --arrays-eager-lemmas + ;; +QF_ALIA) + finishwith --decision=justification-stoponly --no-arrays-eager-index --arrays-eager-lemmas + ;; +QF_S|QF_SLIA) + finishwith --strings-exp + ;; +QF_ABVFP|QF_ABVFPLRA) + finishwith --fp-exp + ;; +QF_BVFP|QF_BVFPLRA) + finishwith --fp-exp + ;; +QF_FP|QF_FPLRA) + finishwith --fp-exp + ;; +*) + # just run the default + finishwith + ;; + +esac + diff --git a/docs/_static/custom.css b/docs/_static/custom.css index a5403c295..9d07edeaf 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -87,3 +87,13 @@ a:hover, a:focus { .highlight .m { color: #ba2121; } + +#c-api-class-hierarchy code { + font-size: 100%; + font-weight: normal; + font-family: "Lato","proxima-nova","Helvetica Neue","Arial","sans-serif"; +} + +.hide-toctree { + display: none; +} diff --git a/docs/api/cpp/class_hierarchy.rst b/docs/api/cpp/class_hierarchy.rst new file mode 100644 index 000000000..3fda2f348 --- /dev/null +++ b/docs/api/cpp/class_hierarchy.rst @@ -0,0 +1,45 @@ +C++ API Class Hierarchy +======================= + +``namespace cvc5::api {`` + + * class :cpp:class:`CVC5ApiException <cvc5::api::CVC5ApiException>` + * class :cpp:class:`CVC5ApiRecoverableException <cvc5::api::CVC5ApiRecoverableException>` + + * class :ref:`api/cpp/datatype:datatype` + + * class :cpp:class:`const_iterator <cvc5::api::Datatype::const_iterator>` + + * class :ref:`api/cpp/datatypeconstructor:datatypeconstructor` + + * class :cpp:class:`const_iterator <cvc5::api::DatatypeConstructor::const_iterator>` + + * class :ref:`api/cpp/datatypeconstructordecl:datatypeconstructordecl` + * class :ref:`api/cpp/datatypedecl:datatypedecl` + * class :ref:`api/cpp/datatypeselector:datatypeselector` + + * class :ref:`api/cpp/grammar:grammar` + + * class :ref:`api/cpp/kind:kind` + + * class :ref:`api/cpp/op:op` + + * class :ref:`api/cpp/result:result` + + * enum :cpp:enum:`UnknownExplanation <cvc5::api::Result::UnknownExplanation>` + + * class :ref:`api/cpp/roundingmode:roundingmode` + + * class :ref:`api/cpp/solver:solver` + + * class :ref:`api/cpp/sort:sort` + + * class :cpp:class:`Stat <cvc5::api::Stat>` + + * class :cpp:class:`Statistics <cvc5::api::Statistics>` + + * class :ref:`api/cpp/term:term` + + * class :cpp:class:`const_iterator <cvc5::api::Term::const_iterator>` + +``}`` diff --git a/docs/api/cpp/cpp.rst b/docs/api/cpp/cpp.rst index 8d302d60c..17e121a2c 100644 --- a/docs/api/cpp/cpp.rst +++ b/docs/api/cpp/cpp.rst @@ -6,63 +6,27 @@ C++ API Documentation .. toctree:: :maxdepth: 2 - datatype - datatypeconstructor - datatypeconstructordecl - datatypedecl - datatypeselector - exceptions - grammar - kind - op - result - roundingmode - solver - sort - statistics - term + class_hierarchy + +.. container:: hide-toctree + + .. toctree:: + :maxdepth: 0 + + datatype + datatypeconstructor + datatypeconstructordecl + datatypedecl + datatypeselector + exceptions + grammar + kind + op + result + roundingmode + solver + sort + statistics + term -Class Hierarchy ---------------- - -* namespace ``cvc5::api`` - - * class :cpp:class:`CVC5ApiException <cvc5::api::CVC5ApiException>` - * class :cpp:class:`CVC5ApiRecoverableException <cvc5::api::CVC5ApiRecoverableException>` - - * class :cpp:class:`Datatype <cvc5::api::Datatype>` - - * class :cpp:class:`const_iterator <cvc5::api::Datatype::const_iterator>` - - * class :cpp:class:`DatatypeConstructor <cvc5::api::DatatypeConstructor>` - - * class :cpp:class:`const_iterator <cvc5::api::DatatypeConstructor::const_iterator>` - - * class :cpp:class:`DatatypeConstructorDecl <cvc5::api::DatatypeConstructorDecl>` - * class :cpp:class:`DatatypeDecl <cvc5::api::DatatypeDecl>` - * class :cpp:class:`DatatypeSelector <cvc5::api::DatatypeSelector>` - - * class :cpp:class:`Grammar <cvc5::api::Grammar>` - - * enum :cpp:enum:`Kind <cvc5::api::Kind>` - - * class :cpp:class:`Op <cvc5::api::Op>` - - * class :cpp:class:`Result <cvc5::api::Result>` - - * enum :cpp:enum:`UnknownExplanation <cvc5::api::Result::UnknownExplanation>` - - * enum :cpp:enum:`RoundingMode <cvc5::api::RoundingMode>` - - * class :cpp:class:`Solver <cvc5::api::Solver>` - - * class :cpp:class:`Sort <cvc5::api::Sort>` - - * class :cpp:class:`Stat <cvc5::api::Stat>` - - * class :cpp:class:`Statistics <cvc5::api::Statistics>` - - * class :cpp:class:`Term <cvc5::api::Term>` - - * class :cpp:class:`const_iterator <cvc5::api::Term::const_iterator>` diff --git a/docs/conf.py.in b/docs/conf.py.in index 65e880bc9..4447d1441 100644 --- a/docs/conf.py.in +++ b/docs/conf.py.in @@ -49,6 +49,9 @@ extensions = [ bibtex_bibfiles = ['references.bib'] +# Make sure the target is unique +autosectionlabel_prefix_document = True + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -67,6 +70,7 @@ html_theme = 'sphinx_rtd_theme' html_theme_options = {} html_static_path = ['${CMAKE_CURRENT_SOURCE_DIR}/_static/'] html_css_files = ['custom.css'] +html_show_sourcelink = False # -- Breathe configuration --------------------------------------------------- breathe_default_project = "cvc5" diff --git a/docs/examples/examples.rst b/docs/examples/examples.rst index 5e17d524b..4132d1545 100644 --- a/docs/examples/examples.rst +++ b/docs/examples/examples.rst @@ -1,13 +1,15 @@ Examples =========== -The following examples show how the APIs (:ref:`cpp-api`, :ref:`python-api`) and input languages can be used. -For every example, the same problem is constructed and solved using different input mechanisms. +The following examples show how the APIs (:ref:`cpp-api`, :ref:`python-api`) +and input languages can be used. +For every example, the same problem is constructed and solved using different +input mechanisms. .. toctree:: :maxdepth: 2 - + helloworld exceptions bitvectors diff --git a/docs/references.bib b/docs/references.bib index 50e410e7b..8e3fd5e69 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -6,3 +6,96 @@ pages={1-84}, doi={10.1109/IEEESTD.2019.8766229} } + +@article{BansalBRT17, + author = {Kshitij Bansal and + Clark W. Barrett and + Andrew Reynolds and + Cesare Tinelli}, + title = {A New Decision Procedure for Finite Sets and Cardinality Constraints + in {SMT}}, + journal = {CoRR}, + volume = {abs/1702.06259}, + year = {2017}, + archivePrefix = {arXiv}, + eprint = {1702.06259}, + timestamp = {Mon, 13 Aug 2018 16:47:11 +0200}, + biburl = {https://dblp.org/rec/journals/corr/BansalBRT17.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@inproceedings{MengRTB17, + author = {Baoluo Meng and + Andrew Reynolds and + Cesare Tinelli and + Clark W. Barrett}, + editor = {Leonardo de Moura}, + title = {Relational Constraint Solving in {SMT}}, + booktitle = {Automated Deduction - {CADE} 26 - 26th International Conference on + Automated Deduction, Gothenburg, Sweden, August 6-11, 2017, Proceedings}, + series = {Lecture Notes in Computer Science}, + volume = {10395}, + pages = {148--165}, + publisher = {Springer}, + year = {2017}, + doi = {10.1007/978-3-319-63046-5_10}, + timestamp = {Wed, 25 Sep 2019 18:19:14 +0200}, + biburl = {https://dblp.org/rec/conf/cade/MengRTB17.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@inproceedings{ReynoldsISK16, + author = {Andrew Reynolds and + Radu Iosif and + Cristina Serban and + Tim King}, + editor = {Cyrille Artho and + Axel Legay and + Doron Peled}, + title = {A Decision Procedure for Separation Logic in {SMT}}, + booktitle = {Automated Technology for Verification and Analysis - 14th International + Symposium, {ATVA} 2016, Chiba, Japan, October 17-20, 2016, Proceedings}, + series = {Lecture Notes in Computer Science}, + volume = {9938}, + pages = {244--261}, + year = {2016}, + doi = {10.1007/978-3-319-46520-3_16}, + timestamp = {Tue, 14 May 2019 10:00:49 +0200}, + biburl = {https://dblp.org/rec/conf/atva/ReynoldsIS016.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@inproceedings{ReynoldsB15, + author = {Andrew Reynolds and + Jasmin Christian Blanchette}, + editor = {Amy P. Felty and + Aart Middeldorp}, + title = {A Decision Procedure for (Co)datatypes in {SMT} Solvers}, + booktitle = {Automated Deduction - {CADE-25} - 25th International Conference on + Automated Deduction, Berlin, Germany, August 1-7, 2015, Proceedings}, + series = {Lecture Notes in Computer Science}, + volume = {9195}, + pages = {197--213}, + publisher = {Springer}, + year = {2015}, + doi = {10.1007/978-3-319-21401-6_13}, + timestamp = {Tue, 14 May 2019 10:00:39 +0200}, + biburl = {https://dblp.org/rec/conf/cade/ReynoldsB15.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@article{BarrettST07, + author = {Clark W. Barrett and + Igor Shikanian and + Cesare Tinelli}, + title = {An Abstract Decision Procedure for a Theory of Inductive Data Types}, + journal = {J. Satisf. Boolean Model. Comput.}, + volume = {3}, + number = {1-2}, + pages = {21--46}, + year = {2007}, + doi = {10.3233/sat190028}, + timestamp = {Mon, 17 Aug 2020 18:32:39 +0200}, + biburl = {https://dblp.org/rec/journals/jsat/BarrettST07.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} diff --git a/docs/theories/datatypes.rst b/docs/theories/datatypes.rst index 5f02a8bf8..1211a43ee 100644 --- a/docs/theories/datatypes.rst +++ b/docs/theories/datatypes.rst @@ -45,8 +45,8 @@ evaluate to true iff their argument has top-symbol ``C``. Semantics --------- -The decision procedure for inductive datatypes can be found -`here <http://homepage.cs.uiowa.edu/~tinelli/papers/BarST-JSAT-07.pdf>`__. +The decision procedure for inductive datatypes is described in +:cite:`BarrettST07`. Example Declarations -------------------- @@ -150,8 +150,8 @@ For example: Codatatypes ----------- -cvc5 also supports co-inductive datatypes, as described -`here <http://homepage.cs.uiowa.edu/~ajreynol/cade15.pdf>`__. +cvc5 also supports co-inductive datatypes, as described in +:cite:`ReynoldsB15`. The syntax for declaring mutually recursive coinductive datatype blocks is identical to inductive datatypes, except that ``declare-datatypes`` is replaced diff --git a/docs/theories/separation-logic.rst b/docs/theories/separation-logic.rst index c2dcda78e..86f802ef8 100644 --- a/docs/theories/separation-logic.rst +++ b/docs/theories/separation-logic.rst @@ -7,10 +7,9 @@ language. Signature --------- -Given a (decidable) base theory :math:`T`, cvc5 has a -`decision procedure <https://cvc4.github.io/publications/2016/RIS+16.pdf>`__ -for quantifier-free :math:`SL(T)_{Loc,Data}` formulas, where :math:`Loc` and -:math:`Data` are any sort belonging to :math:`T`. +Given a (decidable) base theory :math:`T`, cvc5 implements a decision procedure +for quantifier-free :math:`SL(T)_{Loc,Data}` formulas :cite:`ReynoldsISK16`, +where :math:`Loc` and :math:`Data` are any sort belonging to :math:`T`. A :math:`SL(T)_{Loc,Data}` formula is one from the following grammar: diff --git a/docs/theories/sets-and-relations.rst b/docs/theories/sets-and-relations.rst index 79838334f..88671a837 100644 --- a/docs/theories/sets-and-relations.rst +++ b/docs/theories/sets-and-relations.rst @@ -20,8 +20,7 @@ The source code of these examples is available at: Below is a short summary of the sorts, constants, functions and -predicates. For more details, see -`this paper at IJCAR 2016 <https://cvc4.github.io/publications/2016/BRBT16.pdf>`__. +predicates. More details can be found in :cite:`BansalBRT17`. For the C++ API examples in the table below, we assume that we have created a `cvc5::api::Solver solver` object. @@ -151,8 +150,7 @@ Example: For reference, below is a short summary of the sorts, constants, functions and predicates. -For more details, see -`this paper at CADE 2017 <https://cvc4.github.io/publications/2017/MRT+17.pdf>`__. +More details can be found in :cite:`MengRTB17`. +----------------------+----------------------------------------------+------------------------------------------------------------------------------------+ | | SMTLIB language | C++ API | diff --git a/examples/api/cpp/CMakeLists.txt b/examples/api/cpp/CMakeLists.txt index bff7caa4d..6f66fdc5f 100644 --- a/examples/api/cpp/CMakeLists.txt +++ b/examples/api/cpp/CMakeLists.txt @@ -24,6 +24,7 @@ set(CVC5_EXAMPLES_API sets sequences strings + quickstart ) foreach(example ${CVC5_EXAMPLES_API}) diff --git a/examples/api/cpp/bitvectors.cpp b/examples/api/cpp/bitvectors.cpp index 8768bd996..51f438a2d 100644 --- a/examples/api/cpp/bitvectors.cpp +++ b/examples/api/cpp/bitvectors.cpp @@ -10,7 +10,7 @@ * directory for licensing information. * **************************************************************************** * - * A simple demonstration of the solving capabilities of the CVC4 + * A simple demonstration of the solving capabilities of the cvc5 * bit-vector solver. * */ @@ -43,7 +43,7 @@ int main() // //(2) x = a + b - x; // - // We will use CVC4 to prove that the three pieces of code above are all + // We will use cvc5 to prove that the three pieces of code above are all // equivalent by encoding the problem in the bit-vector theory. // Creating a bit-vector type of width 32 @@ -73,7 +73,7 @@ int main() Term assignment0 = slv.mkTerm(EQUAL, new_x, ite); // Assert the encoding of code (0) - cout << "Asserting " << assignment0 << " to CVC4 " << endl; + cout << "Asserting " << assignment0 << " to cvc5 " << endl; slv.assertFormula(assignment0); cout << "Pushing a new context." << endl; slv.push(); @@ -83,14 +83,14 @@ int main() Term a_xor_b_xor_x = slv.mkTerm(BITVECTOR_XOR, a, b, x); Term assignment1 = slv.mkTerm(EQUAL, new_x_, a_xor_b_xor_x); - // Assert encoding to CVC4 in current context; - cout << "Asserting " << assignment1 << " to CVC4 " << endl; + // Assert encoding to cvc5 in current context; + cout << "Asserting " << assignment1 << " to cvc5 " << endl; slv.assertFormula(assignment1); Term new_x_eq_new_x_ = slv.mkTerm(EQUAL, new_x, new_x_); cout << " Check entailment assuming: " << new_x_eq_new_x_ << endl; cout << " Expect ENTAILED. " << endl; - cout << " CVC4: " << slv.checkEntailed(new_x_eq_new_x_) << endl; + cout << " cvc5: " << slv.checkEntailed(new_x_eq_new_x_) << endl; cout << " Popping context. " << endl; slv.pop(); @@ -100,19 +100,19 @@ int main() Term a_plus_b_minus_x = slv.mkTerm(BITVECTOR_SUB, a_plus_b, x); Term assignment2 = slv.mkTerm(EQUAL, new_x_, a_plus_b_minus_x); - // Assert encoding to CVC4 in current context; - cout << "Asserting " << assignment2 << " to CVC4 " << endl; + // Assert encoding to cvc5 in current context; + cout << "Asserting " << assignment2 << " to cvc5 " << endl; slv.assertFormula(assignment2); cout << " Check entailment assuming: " << new_x_eq_new_x_ << endl; cout << " Expect ENTAILED. " << endl; - cout << " CVC4: " << slv.checkEntailed(new_x_eq_new_x_) << endl; + cout << " cvc5: " << slv.checkEntailed(new_x_eq_new_x_) << endl; Term x_neq_x = slv.mkTerm(EQUAL, x, x).notTerm(); std::vector<Term> v{new_x_eq_new_x_, x_neq_x}; cout << " Check entailment assuming: " << v << endl; cout << " Expect NOT_ENTAILED. " << endl; - cout << " CVC4: " << slv.checkEntailed(v) << endl; + cout << " cvc5: " << slv.checkEntailed(v) << endl; // Assert that a is odd Op extract_op = slv.mkOp(BITVECTOR_EXTRACT, 0, 0); @@ -123,6 +123,6 @@ int main() cout << "Check satisfiability." << endl; slv.assertFormula(a_odd); cout << " Expect sat. " << endl; - cout << " CVC4: " << slv.checkSat() << endl; + cout << " cvc5: " << slv.checkSat() << endl; return 0; } diff --git a/examples/api/cpp/bitvectors_and_arrays.cpp b/examples/api/cpp/bitvectors_and_arrays.cpp index 547b294a0..6b58daf1b 100644 --- a/examples/api/cpp/bitvectors_and_arrays.cpp +++ b/examples/api/cpp/bitvectors_and_arrays.cpp @@ -10,7 +10,7 @@ * directory for licensing information. * **************************************************************************** * - * A simple demonstration of the solving capabilities of the CVC4 + * A simple demonstration of the solving capabilities of the cvc5 * bit-vector and array solvers. * */ @@ -84,10 +84,10 @@ int main() Term query = slv.mkTerm(NOT, slv.mkTerm(AND, assertions)); - cout << "Asserting " << query << " to CVC4 " << endl; + cout << "Asserting " << query << " to cvc5 " << endl; slv.assertFormula(query); cout << "Expect sat. " << endl; - cout << "CVC4: " << slv.checkSatAssuming(slv.mkTrue()) << endl; + cout << "cvc5: " << slv.checkSatAssuming(slv.mkTrue()) << endl; // Getting the model cout << "The satisfying model is: " << endl; diff --git a/examples/api/cpp/datatypes.cpp b/examples/api/cpp/datatypes.cpp index 76c6da0f0..1ba9beaf1 100644 --- a/examples/api/cpp/datatypes.cpp +++ b/examples/api/cpp/datatypes.cpp @@ -10,7 +10,7 @@ * directory for licensing information. * **************************************************************************** * - * An example of using inductive datatypes in CVC4. + * An example of using inductive datatypes in cvc5. */ #include <cvc5/cvc5.h> @@ -127,7 +127,7 @@ void test(Solver& slv, Sort& consListSort) std::cout << "Assert " << assertion << std::endl; slv.assertFormula(assertion); std::cout << "Expect sat." << std::endl; - std::cout << "CVC4: " << slv.checkSat() << std::endl; + std::cout << "cvc5: " << slv.checkSat() << std::endl; } int main() @@ -153,7 +153,7 @@ int main() std::cout << "spec is:" << std::endl << consListSpec << std::endl; // Keep in mind that "DatatypeDecl" is the specification class for - // datatypes---"DatatypeDecl" is not itself a CVC4 Sort. + // datatypes---"DatatypeDecl" is not itself a cvc5 Sort. // Now that our Datatype is fully specified, we can get a Sort for it. // This step resolves the "SelfSort" reference and creates // symbols for all the constructors, etc. diff --git a/examples/api/cpp/extract.cpp b/examples/api/cpp/extract.cpp index d21c59d59..b5de58d26 100644 --- a/examples/api/cpp/extract.cpp +++ b/examples/api/cpp/extract.cpp @@ -10,7 +10,7 @@ * directory for licensing information. * **************************************************************************** * - * A simple demonstration of the solving capabilities of the CVC4 + * A simple demonstration of the solving capabilities of the cvc5 * bit-vector solver. * */ @@ -50,7 +50,7 @@ int main() Term eq2 = slv.mkTerm(EQUAL, x_31_31, x_0_0); cout << " Check entailment assuming: " << eq2 << endl; cout << " Expect ENTAILED. " << endl; - cout << " CVC4: " << slv.checkEntailed(eq2) << endl; + cout << " cvc5: " << slv.checkEntailed(eq2) << endl; return 0; } diff --git a/examples/api/cpp/helloworld.cpp b/examples/api/cpp/helloworld.cpp index 21eb8e8fc..3d11d1bd0 100644 --- a/examples/api/cpp/helloworld.cpp +++ b/examples/api/cpp/helloworld.cpp @@ -10,7 +10,7 @@ * directory for licensing information. * **************************************************************************** * - * A very simple CVC4 example. + * A very simple cvc5 example. */ #include <cvc5/cvc5.h> diff --git a/examples/api/cpp/linear_arith.cpp b/examples/api/cpp/linear_arith.cpp index 02ddd956c..979959d21 100644 --- a/examples/api/cpp/linear_arith.cpp +++ b/examples/api/cpp/linear_arith.cpp @@ -11,7 +11,7 @@ * **************************************************************************** * * A simple demonstration of the linear arithmetic solving capabilities and - * the push pop of CVC4. This also gives an example option. + * the push pop of cvc5. This also gives an example option. */ #include <iostream> @@ -60,9 +60,9 @@ int main() slv.push(); Term diff_leq_two_thirds = slv.mkTerm(LEQ, diff, two_thirds); - cout << "Prove that " << diff_leq_two_thirds << " with CVC4." << endl; - cout << "CVC4 should report ENTAILED." << endl; - cout << "Result from CVC4 is: " << slv.checkEntailed(diff_leq_two_thirds) + cout << "Prove that " << diff_leq_two_thirds << " with cvc5." << endl; + cout << "cvc5 should report ENTAILED." << endl; + cout << "Result from cvc5 is: " << slv.checkEntailed(diff_leq_two_thirds) << endl; slv.pop(); @@ -72,9 +72,9 @@ int main() Term diff_is_two_thirds = slv.mkTerm(EQUAL, diff, two_thirds); slv.assertFormula(diff_is_two_thirds); cout << "Show that the assertions are consistent with " << endl; - cout << diff_is_two_thirds << " with CVC4." << endl; - cout << "CVC4 should report SAT." << endl; - cout << "Result from CVC4 is: " << slv.checkSat() << endl; + cout << diff_is_two_thirds << " with cvc5." << endl; + cout << "cvc5 should report SAT." << endl; + cout << "Result from cvc5 is: " << slv.checkSat() << endl; slv.pop(); cout << "Thus the maximum value of (y - x) is 2/3."<< endl; diff --git a/examples/api/cpp/quickstart.cpp b/examples/api/cpp/quickstart.cpp new file mode 100644 index 000000000..5d4849bc0 --- /dev/null +++ b/examples/api/cpp/quickstart.cpp @@ -0,0 +1,170 @@ +/****************************************************************************** + * Top contributors (to current version): + * Yoni Zohar + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * A simple demonstration of the api capabilities of cvc5. + * + */ + +#include <cvc5/cvc5.h> + +#include <iostream> + +using namespace std; +using namespace cvc5::api; + +int main() +{ + // Create a solver + Solver solver; + + // We will ask the solver to produce models and unsat cores, + // hence these options should be turned on. + solver.setOption("produce-models", "true"); + solver.setOption("produce-unsat-cores", "true"); + + // The simplest way to set a logic for the solver is to choose "ALL". + // This enables all logics in the solver. + // Alternatively, "QF_ALL" enables all logics without quantifiers. + // To optimize the solver's behavior for a more specific logic, + // use the logic name, e.g. "QF_BV" or "QF_AUFBV". + + // Set the logic + solver.setLogic("ALL"); + + // In this example, we will define constraints over reals and integers. + // Hence, we first obtain the corresponding sorts. + Sort realSort = solver.getRealSort(); + Sort intSort = solver.getIntegerSort(); + + // x and y will be real variables, while a and b will be integer variables. + // Formally, their cpp type is Term, + // and they are called "constants" in SMT jargon: + Term x = solver.mkConst(realSort, "x"); + Term y = solver.mkConst(realSort, "y"); + Term a = solver.mkConst(intSort, "a"); + Term b = solver.mkConst(intSort, "b"); + + // Our constraints regarding x and y will be: + // + // (1) 0 < x + // (2) 0 < y + // (3) x + y < 1 + // (4) x <= y + // + + // Formally, constraints are also terms. Their sort is Boolean. + // We will construct these constraints gradually, + // by defining each of their components. + // We start with the constant numerals 0 and 1: + Term zero = solver.mkReal(0); + Term one = solver.mkReal(1); + + // Next, we construct the term x + y + Term xPlusY = solver.mkTerm(PLUS, x, y); + + // Now we can define the constraints. + // They use the operators +, <=, and <. + // In the API, these are denoted by PLUS, LEQ, and LT. + // A list of available operators is available in: + // src/api/cpp/cvc5_kind.h + Term constraint1 = solver.mkTerm(LT, zero, x); + Term constraint2 = solver.mkTerm(LT, zero, y); + Term constraint3 = solver.mkTerm(LT, xPlusY, one); + Term constraint4 = solver.mkTerm(LEQ, x, y); + + // Now we assert the constraints to the solver. + solver.assertFormula(constraint1); + solver.assertFormula(constraint2); + solver.assertFormula(constraint3); + solver.assertFormula(constraint4); + + // Check if the formula is satisfiable, that is, + // are there real values for x,y,z that satisfy all the constraints? + Result r1 = solver.checkSat(); + + // The result is either SAT, UNSAT, or UNKNOWN. + // In this case, it is SAT. + std::cout << "expected: sat" << std::endl; + std::cout << "result:" << r1 << std::endl; + + // We can get the values for x and y that satisfy the constraints. + Term xVal = solver.getValue(x); + Term yVal = solver.getValue(y); + + // It is also possible to get values for compound terms, + // even if those did not appear in the original formula. + Term xMinusY = solver.mkTerm(MINUS, x, y); + Term xMinusYVal = solver.getValue(xMinusY); + + // We can now obtain thestring representations of the values. + std::string xStr = xVal.getRealValue(); + std::string yStr = yVal.getRealValue(); + std::string xMinusYStr = xMinusYVal.getRealValue(); + + std::cout << "value for x: " << xStr << std::endl; + std::cout << "value for y: " << yStr << std::endl; + std::cout << "value for x - y: " << xMinusYStr << std::endl; + + // Further, we can convert the values to cpp types, + // using standard cpp conversion functions. + double xDouble = std::stod(xStr); + double yDouble = std::stod(yStr); + double xMinusYDouble = std::stod(xMinusYStr); + + // Another way to independently compute the value of x and y would be using + // the ordinary cpp minus operator instead of asking the solver. + // However, for more complex terms, + // it is easier to let the solver do the evaluation. + double xMinusYComputed = xDouble - yDouble; + if (xMinusYComputed == xMinusYDouble) + { + std::cout << "computed correctly" << std::endl; + } + else + { + std::cout << "computed incorrectly" << std::endl; + } + + // Next, we will check satisfiability of the same formula, + // only this time over integer variables a and b. + + // We start by resetting assertions added to the solver. + solver.resetAssertions(); + + // Next, we assert the same assertions above with integers. + // This time, we inline the construction of terms + // to the assertion command. + solver.assertFormula(solver.mkTerm(LT, solver.mkInteger(0), a)); + solver.assertFormula(solver.mkTerm(LT, solver.mkInteger(0), b)); + solver.assertFormula( + solver.mkTerm(LT, solver.mkTerm(PLUS, a, b), solver.mkInteger(1))); + solver.assertFormula(solver.mkTerm(LEQ, a, b)); + + // We check whether the revised assertion is satisfiable. + Result r2 = solver.checkSat(); + + // This time the formula is unsatisfiable + std::cout << "expected: unsat" << std::endl; + std::cout << "result: " << r2 << std::endl; + + // We can query the solver for an unsatisfiable core, i.e., a subset + // of the assertions that is already unsatisfiable. + std::vector<Term> unsatCore = solver.getUnsatCore(); + std::cout << "unsat core size: " << unsatCore.size() << std::endl; + std::cout << "unsat core: " << std::endl; + for (const Term& t : unsatCore) + { + std::cout << t << std::endl; + } + + return 0; +} diff --git a/examples/api/cpp/sequences.cpp b/examples/api/cpp/sequences.cpp index 5ee66048f..40cacf5c7 100644 --- a/examples/api/cpp/sequences.cpp +++ b/examples/api/cpp/sequences.cpp @@ -10,7 +10,7 @@ * directory for licensing information. * **************************************************************************** * - * A simple demonstration of reasoning about sequences with CVC4 via C++ API. + * A simple demonstration of reasoning about sequences with cvc5 via C++ API. */ #include <cvc5/cvc5.h> @@ -57,7 +57,7 @@ int main() // check sat Result result = slv.checkSatAssuming(q); - std::cout << "CVC4 reports: " << q << " is " << result << "." << std::endl; + std::cout << "cvc5 reports: " << q << " is " << result << "." << std::endl; if (result.isSat()) { diff --git a/examples/api/cpp/sets.cpp b/examples/api/cpp/sets.cpp index c1eded4a4..1f3a1683c 100644 --- a/examples/api/cpp/sets.cpp +++ b/examples/api/cpp/sets.cpp @@ -51,7 +51,7 @@ int main() Term theorem = slv.mkTerm(EQUAL, lhs, rhs); - cout << "CVC4 reports: " << theorem << " is " << slv.checkEntailed(theorem) + cout << "cvc5 reports: " << theorem << " is " << slv.checkEntailed(theorem) << "." << endl; } @@ -62,7 +62,7 @@ int main() Term theorem = slv.mkTerm(SUBSET, emptyset, A); - cout << "CVC4 reports: " << theorem << " is " << slv.checkEntailed(theorem) + cout << "cvc5 reports: " << theorem << " is " << slv.checkEntailed(theorem) << "." << endl; } @@ -84,7 +84,7 @@ int main() Term e = slv.mkTerm(MEMBER, x, intersection); Result result = slv.checkSatAssuming(e); - cout << "CVC4 reports: " << e << " is " << result << "." << endl; + cout << "cvc5 reports: " << e << " is " << result << "." << endl; if (result.isSat()) { diff --git a/examples/api/cpp/strings.cpp b/examples/api/cpp/strings.cpp index a952b31d1..01e384ee7 100644 --- a/examples/api/cpp/strings.cpp +++ b/examples/api/cpp/strings.cpp @@ -10,7 +10,7 @@ * directory for licensing information. * **************************************************************************** * - * A simple demonstration of reasoning about strings with CVC4 via C++ API. + * A simple demonstration of reasoning about strings with cvc5 via C++ API. */ #include <cvc5/cvc5.h> @@ -84,7 +84,7 @@ int main() // check sat Result result = slv.checkSatAssuming(q); - std::cout << "CVC4 reports: " << q << " is " << result << "." << std::endl; + std::cout << "cvc5 reports: " << q << " is " << result << "." << std::endl; if(result.isSat()) { diff --git a/examples/api/java/FloatingPointArith.java b/examples/api/java/FloatingPointArith.java index 61ab18148..46f8b8330 100644 --- a/examples/api/java/FloatingPointArith.java +++ b/examples/api/java/FloatingPointArith.java @@ -27,13 +27,6 @@ public class FloatingPointArith { System.loadLibrary("cvc4jni"); // Test whether CVC4 was built with floating-point support - if (!Configuration.isBuiltWithSymFPU()) { - System.out.println("CVC4 was built without floating-point support."); - System.out.println("Configure with --symfpu and rebuild CVC4 to run"); - System.out.println("this example."); - System.exit(77); - } - ExprManager em = new ExprManager(); SmtEngine smt = new SmtEngine(em); diff --git a/examples/api/python/floating_point.py b/examples/api/python/floating_point.py index 66b18642d..0001f726b 100644 --- a/examples/api/python/floating_point.py +++ b/examples/api/python/floating_point.py @@ -22,12 +22,6 @@ from pycvc5 import kinds if __name__ == "__main__": slv = pycvc5.Solver() - if not slv.supportsFloatingPoint(): - # cvc5 must be built with SymFPU to support the theory of - # floating-point numbers - print("cvc5 was not built with floating-point support.") - exit() - slv.setOption("produce-models", "true") slv.setLogic("QF_FP") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bec3a8345..74db7c941 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -441,6 +441,7 @@ libcvc5_add_sources( theory/arith/nl/nonlinear_extension.h theory/arith/nl/poly_conversion.cpp theory/arith/nl/poly_conversion.h + theory/arith/nl/pow2_solver.cpp theory/arith/nl/pow2_solver.h theory/arith/nl/stats.cpp theory/arith/nl/stats.h @@ -595,6 +596,7 @@ libcvc5_add_sources( theory/bv/bv_subtheory_core.h theory/bv/bv_subtheory_inequality.cpp theory/bv/bv_subtheory_inequality.h + theory/bv/int_blaster.cpp theory/bv/int_blaster.h theory/bv/proof_checker.cpp theory/bv/proof_checker.h @@ -1184,9 +1186,9 @@ if(USE_ABC) target_link_libraries(cvc5 PRIVATE ${ABC_LIBRARIES}) target_include_directories(cvc5 PRIVATE ${ABC_INCLUDE_DIR}) endif() -if(USE_CADICAL) - target_link_libraries(cvc5 PRIVATE CaDiCaL) -endif() + +target_link_libraries(cvc5 PRIVATE CaDiCaL) + if(USE_CLN) target_link_libraries(cvc5 PRIVATE CLN) endif() @@ -1203,9 +1205,8 @@ endif() if(USE_POLY) target_link_libraries(cvc5 PRIVATE Polyxx) endif() -if(USE_SYMFPU) - target_link_libraries(cvc5 PRIVATE SymFPU) -endif() + +target_link_libraries(cvc5 PRIVATE SymFPU) # Note: When linked statically GMP needs to be linked after CLN since CLN # depends on GMP. diff --git a/src/api/cpp/cvc5.cpp b/src/api/cpp/cvc5.cpp index 668fc9382..43bb3d2dc 100644 --- a/src/api/cpp/cvc5.cpp +++ b/src/api/cpp/cvc5.cpp @@ -55,6 +55,7 @@ #include "expr/sequence.h" #include "expr/type_node.h" #include "expr/uninterpreted_constant.h" +#include "options/base_options.h" #include "options/main_options.h" #include "options/option_exception.h" #include "options/options.h" @@ -5196,18 +5197,6 @@ void Solver::checkMkTerm(Kind kind, uint32_t nchildren) const << " children (the one under construction has " << nchildren << ")"; } -/* Solver Configuration */ -/* -------------------------------------------------------------------------- */ - -bool Solver::supportsFloatingPoint() const -{ - CVC5_API_TRY_CATCH_BEGIN; - //////// all checks before this line - return Configuration::isBuiltWithSymFPU(); - //////// - CVC5_API_TRY_CATCH_END; -} - /* Sorts Handling */ /* -------------------------------------------------------------------------- */ @@ -5275,8 +5264,6 @@ Sort Solver::getRoundingModeSort(void) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(Configuration::isBuiltWithSymFPU()) - << "Expected cvc5 to be compiled with SymFPU support"; //////// all checks before this line return Sort(this, getNodeManager()->roundingModeType()); //////// @@ -5313,8 +5300,6 @@ Sort Solver::mkFloatingPointSort(uint32_t exp, uint32_t sig) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(Configuration::isBuiltWithSymFPU()) - << "Expected cvc5 to be compiled with SymFPU support"; CVC5_API_ARG_CHECK_EXPECTED(exp > 0, exp) << "exponent size > 0"; CVC5_API_ARG_CHECK_EXPECTED(sig > 0, sig) << "significand size > 0"; //////// all checks before this line @@ -5793,8 +5778,6 @@ Term Solver::mkPosInf(uint32_t exp, uint32_t sig) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(Configuration::isBuiltWithSymFPU()) - << "Expected cvc5 to be compiled with SymFPU support"; //////// all checks before this line return mkValHelper<cvc5::FloatingPoint>( FloatingPoint::makeInf(FloatingPointSize(exp, sig), false)); @@ -5806,8 +5789,6 @@ Term Solver::mkNegInf(uint32_t exp, uint32_t sig) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(Configuration::isBuiltWithSymFPU()) - << "Expected cvc5 to be compiled with SymFPU support"; //////// all checks before this line return mkValHelper<cvc5::FloatingPoint>( FloatingPoint::makeInf(FloatingPointSize(exp, sig), true)); @@ -5819,8 +5800,6 @@ Term Solver::mkNaN(uint32_t exp, uint32_t sig) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(Configuration::isBuiltWithSymFPU()) - << "Expected cvc5 to be compiled with SymFPU support"; //////// all checks before this line return mkValHelper<cvc5::FloatingPoint>( FloatingPoint::makeNaN(FloatingPointSize(exp, sig))); @@ -5832,8 +5811,6 @@ Term Solver::mkPosZero(uint32_t exp, uint32_t sig) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(Configuration::isBuiltWithSymFPU()) - << "Expected cvc5 to be compiled with SymFPU support"; //////// all checks before this line return mkValHelper<cvc5::FloatingPoint>( FloatingPoint::makeZero(FloatingPointSize(exp, sig), false)); @@ -5845,8 +5822,6 @@ Term Solver::mkNegZero(uint32_t exp, uint32_t sig) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(Configuration::isBuiltWithSymFPU()) - << "Expected cvc5 to be compiled with SymFPU support"; //////// all checks before this line return mkValHelper<cvc5::FloatingPoint>( FloatingPoint::makeZero(FloatingPointSize(exp, sig), true)); @@ -5858,8 +5833,6 @@ Term Solver::mkRoundingMode(RoundingMode rm) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(Configuration::isBuiltWithSymFPU()) - << "Expected cvc5 to be compiled with SymFPU support"; //////// all checks before this line return mkValHelper<cvc5::RoundingMode>(s_rmodes.at(rm)); //////// @@ -5913,8 +5886,6 @@ Term Solver::mkFloatingPoint(uint32_t exp, uint32_t sig, Term val) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(Configuration::isBuiltWithSymFPU()) - << "Expected cvc5 to be compiled with SymFPU support"; CVC5_API_SOLVER_CHECK_TERM(val); CVC5_API_ARG_CHECK_EXPECTED(exp > 0, exp) << "a value > 0"; CVC5_API_ARG_CHECK_EXPECTED(sig > 0, sig) << "a value > 0"; @@ -6452,7 +6423,7 @@ Result Solver::checkEntailed(const Term& term) const NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; CVC5_API_CHECK(!d_smtEngine->isQueryMade() - || d_smtEngine->getOptions().smt.incrementalSolving) + || d_smtEngine->getOptions().base.incrementalSolving) << "Cannot make multiple queries unless incremental solving is enabled " "(try --incremental)"; CVC5_API_SOLVER_CHECK_TERM(term); @@ -6468,7 +6439,7 @@ Result Solver::checkEntailed(const std::vector<Term>& terms) const CVC5_API_TRY_CATCH_BEGIN; NodeManagerScope scope(getNodeManager()); CVC5_API_CHECK(!d_smtEngine->isQueryMade() - || d_smtEngine->getOptions().smt.incrementalSolving) + || d_smtEngine->getOptions().base.incrementalSolving) << "Cannot make multiple queries unless incremental solving is enabled " "(try --incremental)"; CVC5_API_SOLVER_CHECK_TERMS(terms); @@ -6497,7 +6468,7 @@ Result Solver::checkSat(void) const CVC5_API_TRY_CATCH_BEGIN; NodeManagerScope scope(getNodeManager()); CVC5_API_CHECK(!d_smtEngine->isQueryMade() - || d_smtEngine->getOptions().smt.incrementalSolving) + || d_smtEngine->getOptions().base.incrementalSolving) << "Cannot make multiple queries unless incremental solving is enabled " "(try --incremental)"; //////// all checks before this line @@ -6512,7 +6483,7 @@ Result Solver::checkSatAssuming(const Term& assumption) const CVC5_API_TRY_CATCH_BEGIN; NodeManagerScope scope(getNodeManager()); CVC5_API_CHECK(!d_smtEngine->isQueryMade() - || d_smtEngine->getOptions().smt.incrementalSolving) + || d_smtEngine->getOptions().base.incrementalSolving) << "Cannot make multiple queries unless incremental solving is enabled " "(try --incremental)"; CVC5_API_SOLVER_CHECK_TERM_WITH_SORT(assumption, getBooleanSort()); @@ -6528,7 +6499,7 @@ Result Solver::checkSatAssuming(const std::vector<Term>& assumptions) const CVC5_API_TRY_CATCH_BEGIN; NodeManagerScope scope(getNodeManager()); CVC5_API_CHECK(!d_smtEngine->isQueryMade() || assumptions.size() == 0 - || d_smtEngine->getOptions().smt.incrementalSolving) + || d_smtEngine->getOptions().base.incrementalSolving) << "Cannot make multiple queries unless incremental solving is enabled " "(try --incremental)"; CVC5_API_SOLVER_CHECK_TERMS_WITH_SORT(assumptions, getBooleanSort()); @@ -6863,7 +6834,7 @@ std::vector<Term> Solver::getUnsatAssumptions(void) const { CVC5_API_TRY_CATCH_BEGIN; NodeManagerScope scope(getNodeManager()); - CVC5_API_CHECK(d_smtEngine->getOptions().smt.incrementalSolving) + CVC5_API_CHECK(d_smtEngine->getOptions().base.incrementalSolving) << "Cannot get unsat assumptions unless incremental solving is enabled " "(try --incremental)"; CVC5_API_CHECK(d_smtEngine->getOptions().smt.unsatAssumptions) @@ -7044,7 +7015,7 @@ void Solver::pop(uint32_t nscopes) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(d_smtEngine->getOptions().smt.incrementalSolving) + CVC5_API_CHECK(d_smtEngine->getOptions().base.incrementalSolving) << "Cannot pop when not solving incrementally (use --incremental)"; CVC5_API_CHECK(nscopes <= d_smtEngine->getNumUserLevels()) << "Cannot pop beyond first pushed context"; @@ -7176,7 +7147,7 @@ void Solver::push(uint32_t nscopes) const { NodeManagerScope scope(getNodeManager()); CVC5_API_TRY_CATCH_BEGIN; - CVC5_API_CHECK(d_smtEngine->getOptions().smt.incrementalSolving) + CVC5_API_CHECK(d_smtEngine->getOptions().base.incrementalSolving) << "Cannot push when not solving incrementally (use --incremental)"; //////// all checks before this line for (uint32_t n = 0; n < nscopes; ++n) diff --git a/src/api/cpp/cvc5.h b/src/api/cpp/cvc5.h index a1421cf12..161522654 100644 --- a/src/api/cpp/cvc5.h +++ b/src/api/cpp/cvc5.h @@ -2752,12 +2752,6 @@ class CVC5_EXPORT Solver Solver& operator=(const Solver&) = delete; /* .................................................................... */ - /* Solver Configuration */ - /* .................................................................... */ - - bool supportsFloatingPoint() const; - - /* .................................................................... */ /* Sorts Handling */ /* .................................................................... */ diff --git a/src/api/cpp/cvc5_kind.h b/src/api/cpp/cvc5_kind.h index 2ec190360..2c5d2873e 100644 --- a/src/api/cpp/cvc5_kind.h +++ b/src/api/cpp/cvc5_kind.h @@ -412,6 +412,22 @@ enum CVC5_EXPORT Kind : int32_t * - `Solver::mkTerm(const Op& op, const std::vector<Term>& children) const` */ IAND, + /** + * Operator for raising 2 to a non-negative integer power + * + * Create with: + * - `Solver::mkOp(Kind kind) const` + * + + * Parameters: + * - 1: Op of kind IAND + * - 2: Integer term + * + * Create with: + * - `Solver::mkTerm(const Op& op, const Term& child) const` + * - `Solver::mkTerm(const Op& op, const std::vector<Term>& children) const` + */ + POW2, #if 0 /* Synonym for MULT. */ NONLINEAR_MULT, diff --git a/src/api/java/cvc5/Grammar.java b/src/api/java/cvc5/Grammar.java new file mode 100644 index 000000000..f8c6b05c5 --- /dev/null +++ b/src/api/java/cvc5/Grammar.java @@ -0,0 +1,87 @@ +/****************************************************************************** + * Top contributors (to current version): + * Aina Niemetz, Andrew Reynolds, Abdalrhman Mohamed, Mudathir Mohamed + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * The cvc5 java API. + */ + +package cvc5; + +public class Grammar extends AbstractPointer { + // region construction and destruction + Grammar(Solver solver, long pointer) { + super(solver, pointer); + } + + protected static native void deletePointer(long pointer); + + public long getPointer() { + return pointer; + } + + @Override + public void finalize() { + deletePointer(pointer); + } + + // endregion + + /** + * Add \p rule to the set of rules corresponding to \p ntSymbol. + * @param ntSymbol the non-terminal to which the rule is added + * @param rule the rule to add + */ + public void addRule(Term ntSymbol, Term rule) { + addRule(pointer, ntSymbol.getPointer(), rule.getPointer()); + } + + private native void addRule( + long pointer, long ntSymbolPointer, long rulePointer); + + /** + * Add \p rules to the set of rules corresponding to \p ntSymbol. + * @param ntSymbol the non-terminal to which the rules are added + * @param rules the rules to add + */ + public void addRules(Term ntSymbol, Term[] rules) { + long[] pointers = Utils.getPointers(rules); + addRules(pointer, ntSymbol.getPointer(), pointers); + } + + public native void addRules( + long pointer, long ntSymbolPointer, long[] rulePointers); + + /** + * Allow \p ntSymbol to be an arbitrary constant. + * @param ntSymbol the non-terminal allowed to be any constant + */ + void addAnyConstant(Term ntSymbol) { + addAnyConstant(pointer, ntSymbol.getPointer()); + } + + private native void addAnyConstant(long pointer, long ntSymbolPointer); + + /** + * Allow \p ntSymbol to be any input variable to corresponding + * synth-fun/synth-inv with the same sort as \p ntSymbol. + * @param ntSymbol the non-terminal allowed to be any input constant + */ + void addAnyVariable(Term ntSymbol) { + addAnyVariable(pointer, ntSymbol.getPointer()); + } + + private native void addAnyVariable(long pointer, long ntSymbolPointer); + + /** + * @return a string representation of this grammar. + */ + protected native String toString(long pointer); +} diff --git a/src/api/java/jni/cvc5_Grammar.cpp b/src/api/java/jni/cvc5_Grammar.cpp new file mode 100644 index 000000000..95af2108f --- /dev/null +++ b/src/api/java/jni/cvc5_Grammar.cpp @@ -0,0 +1,120 @@ +/****************************************************************************** + * Top contributors (to current version): + * Mudathir Mohamed + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * The cvc5 Java API. + */ + +#include "cvc5_Grammar.h" + +#include "api/cpp/cvc5.h" +#include "cvc5JavaApi.h" + +using namespace cvc5::api; + +/* + * Class: cvc5_Grammar + * Method: deletePointer + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_cvc5_Grammar_deletePointer(JNIEnv*, + jclass, + jlong pointer) +{ + delete reinterpret_cast<Grammar*>(pointer); +} + +/* + * Class: cvc5_Grammar + * Method: addRule + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_cvc5_Grammar_addRule(JNIEnv* env, + jobject, + jlong pointer, + jlong ntSymbolPointer, + jlong rulePointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Grammar* current = reinterpret_cast<Grammar*>(pointer); + Term* ntSymbol = reinterpret_cast<Term*>(ntSymbolPointer); + Term* rule = reinterpret_cast<Term*>(rulePointer); + current->addRule(*ntSymbol, *rule); + CVC5_JAVA_API_TRY_CATCH_END(env); +} + +/* + * Class: cvc5_Grammar + * Method: addRules + * Signature: (JJ[J)V + */ +JNIEXPORT void JNICALL Java_cvc5_Grammar_addRules(JNIEnv* env, + jobject, + jlong pointer, + jlong ntSymbolPointer, + jlongArray rulePointers) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Grammar* current = reinterpret_cast<Grammar*>(pointer); + Term* ntSymbol = reinterpret_cast<Term*>(ntSymbolPointer); + std::vector<Term> rules = getObjectsFromPointers<Term>(env, rulePointers); + current->addRules(*ntSymbol, rules); + CVC5_JAVA_API_TRY_CATCH_END(env); +} + +/* + * Class: cvc5_Grammar + * Method: addAnyConstant + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_cvc5_Grammar_addAnyConstant(JNIEnv* env, + jobject, + jlong pointer, + jlong ntSymbolPointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Grammar* current = reinterpret_cast<Grammar*>(pointer); + Term* ntSymbol = reinterpret_cast<Term*>(ntSymbolPointer); + current->addAnyConstant(*ntSymbol); + CVC5_JAVA_API_TRY_CATCH_END(env); +} + +/* + * Class: cvc5_Grammar + * Method: addAnyVariable + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_cvc5_Grammar_addAnyVariable(JNIEnv* env, + jobject, + jlong pointer, + jlong ntSymbolPointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Grammar* current = reinterpret_cast<Grammar*>(pointer); + Term* ntSymbol = reinterpret_cast<Term*>(ntSymbolPointer); + current->addAnyVariable(*ntSymbol); + CVC5_JAVA_API_TRY_CATCH_END(env); +} + +/* + * Class: cvc5_Grammar + * Method: toString + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_cvc5_Grammar_toString(JNIEnv* env, + jobject, + jlong pointer) +{ + CVC5_JAVA_API_TRY_CATCH_BEGIN; + Grammar* current = reinterpret_cast<Grammar*>(pointer); + return env->NewStringUTF(current->toString().c_str()); + CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr); +} diff --git a/src/api/python/cvc5.pxd b/src/api/python/cvc5.pxd index fdc1872e7..99e471b0a 100644 --- a/src/api/python/cvc5.pxd +++ b/src/api/python/cvc5.pxd @@ -122,6 +122,7 @@ cdef extern from "api/cpp/cvc5.h" namespace "cvc5::api": Sort getSort() except + bint isNull() except + bint isIndexed() except + + size_t getNumIndices() except + T getIndices[T]() except + string toString() except + @@ -141,19 +142,23 @@ cdef extern from "api/cpp/cvc5.h" namespace "cvc5::api": bint isEntailmentUnknown() except + bint operator==(const Result& r) except + bint operator!=(const Result& r) except + - string getUnknownExplanation() except + + UnknownExplanation getUnknownExplanation() except + string toString() except + cdef cppclass RoundingMode: pass + cdef extern from "api/cpp/cvc5.h" namespace "cvc5::api::Result": + cdef cppclass UnknownExplanation: + pass + cdef cppclass Solver: Solver(Options*) except + - bint supportsFloatingPoint() except + Sort getBooleanSort() except + Sort getIntegerSort() except + + Sort getNullSort() except + Sort getRealSort() except + Sort getRegExpSort() except + Sort getRoundingModeSort() except + @@ -179,10 +184,10 @@ cdef extern from "api/cpp/cvc5.h" namespace "cvc5::api": Term mkTerm(Op op, const vector[Term]& children) except + Term mkTuple(const vector[Sort]& sorts, const vector[Term]& terms) except + Op mkOp(Kind kind) except + - Op mkOp(Kind kind, Kind k) except + Op mkOp(Kind kind, const string& arg) except + Op mkOp(Kind kind, uint32_t arg) except + Op mkOp(Kind kind, uint32_t arg1, uint32_t arg2) except + + Op mkOp(Kind kind, const vector[uint32_t]& args) except + # Sygus related functions Grammar mkSygusGrammar(const vector[Term]& boundVars, const vector[Term]& ntSymbols) except + Term mkSygusVar(Sort sort, const string& symbol) except + @@ -208,9 +213,11 @@ cdef extern from "api/cpp/cvc5.h" namespace "cvc5::api": Term mkRegexpEmpty() except + Term mkRegexpSigma() except + Term mkEmptySet(Sort s) except + + Term mkEmptyBag(Sort s) except + Term mkSepNil(Sort sort) except + Term mkString(const string& s) except + Term mkString(const wstring& s) except + + Term mkString(const string& s, bint useEscSequences) except + Term mkEmptySequence(Sort sort) except + Term mkUniverseSet(Sort sort) except + Term mkBitVector(uint32_t size) except + @@ -433,3 +440,16 @@ cdef extern from "api/cpp/cvc5.h" namespace "cvc5::api::RoundingMode": cdef RoundingMode ROUND_TOWARD_NEGATIVE, cdef RoundingMode ROUND_TOWARD_ZERO, cdef RoundingMode ROUND_NEAREST_TIES_TO_AWAY + + +cdef extern from "api/cpp/cvc5.h" namespace "cvc5::api::Result::UnknownExplanation": + cdef UnknownExplanation REQUIRES_FULL_CHECK + cdef UnknownExplanation INCOMPLETE + cdef UnknownExplanation TIMEOUT + cdef UnknownExplanation RESOURCEOUT + cdef UnknownExplanation MEMOUT + cdef UnknownExplanation INTERRUPTED + cdef UnknownExplanation NO_STATUS + cdef UnknownExplanation UNSUPPORTED + cdef UnknownExplanation OTHER + cdef UnknownExplanation UNKNOWN_REASON diff --git a/src/api/python/cvc5.pxi b/src/api/python/cvc5.pxi index 258005207..d31fdc126 100644 --- a/src/api/python/cvc5.pxi +++ b/src/api/python/cvc5.pxi @@ -18,6 +18,7 @@ from cvc5 cimport DatatypeDecl as c_DatatypeDecl from cvc5 cimport DatatypeSelector as c_DatatypeSelector from cvc5 cimport Result as c_Result from cvc5 cimport RoundingMode as c_RoundingMode +from cvc5 cimport UnknownExplanation as c_UnknownExplanation from cvc5 cimport Op as c_Op from cvc5 cimport Solver as c_Solver from cvc5 cimport Grammar as c_Grammar @@ -25,6 +26,10 @@ from cvc5 cimport Sort as c_Sort from cvc5 cimport ROUND_NEAREST_TIES_TO_EVEN, ROUND_TOWARD_POSITIVE from cvc5 cimport ROUND_TOWARD_NEGATIVE, ROUND_TOWARD_ZERO from cvc5 cimport ROUND_NEAREST_TIES_TO_AWAY +from cvc5 cimport REQUIRES_FULL_CHECK, INCOMPLETE, TIMEOUT +from cvc5 cimport RESOURCEOUT, MEMOUT, INTERRUPTED +from cvc5 cimport NO_STATUS, UNSUPPORTED, UNKNOWN_REASON +from cvc5 cimport OTHER from cvc5 cimport Term as c_Term from cvc5 cimport hash as c_hash from cvc5 cimport wstring as c_wstring @@ -340,10 +345,13 @@ cdef class Op: def isNull(self): return self.cop.isNull() + def getNumIndices(self): + return self.cop.getNumIndices() + def getIndices(self): indices = None try: - indices = self.cop.getIndices[string]() + indices = self.cop.getIndices[string]().decode() except: pass @@ -418,7 +426,7 @@ cdef class Result: return self.cr != other.cr def getUnknownExplanation(self): - return self.cr.getUnknownExplanation().decode() + return UnknownExplanation(<int> self.cr.getUnknownExplanation()) def __str__(self): return self.cr.toString().decode() @@ -451,6 +459,30 @@ cdef class RoundingMode: return self.name +cdef class UnknownExplanation: + cdef c_UnknownExplanation cue + cdef str name + def __cinit__(self, int ue): + # crm always assigned externally + self.cue = <c_UnknownExplanation> ue + self.name = __unknown_explanations[ue] + + def __eq__(self, UnknownExplanation other): + return (<int> self.cue) == (<int> other.cue) + + def __ne__(self, UnknownExplanation other): + return not self.__eq__(other) + + def __hash__(self): + return hash((<int> self.crm, self.name)) + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + cdef class Solver: cdef c_Solver* csolver @@ -460,9 +492,6 @@ 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() @@ -473,6 +502,11 @@ cdef class Solver: sort.csort = self.csolver.getIntegerSort() return sort + def getNullSort(self): + cdef Sort sort = Sort(self) + sort.csort = self.csolver.getNullSort() + return sort + def getRealSort(self): cdef Sort sort = Sort(self) sort.csort = self.csolver.getRealSort() @@ -675,8 +709,8 @@ cdef class Solver: result.cterm = self.csolver.mkTuple(csorts, cterms) return result - - def mkOp(self, kind k, arg0=None, arg1 = None): + @expand_list_arg(num_req_args=0) + def mkOp(self, kind k, *args): ''' Supports the following uses: Op mkOp(Kind kind) @@ -686,28 +720,30 @@ cdef class Solver: Op mkOp(Kind kind, uint32_t arg0, uint32_t arg1) ''' cdef Op op = Op(self) + cdef vector[int] v - if arg0 is None: + if len(args) == 0: op.cop = self.csolver.mkOp(k.k) - elif arg1 is None: - if isinstance(arg0, kind): - op.cop = self.csolver.mkOp(k.k, (<kind?> arg0).k) - elif isinstance(arg0, str): + elif len(args) == 1: + if isinstance(args[0], str): op.cop = self.csolver.mkOp(k.k, <const string &> - arg0.encode()) - elif isinstance(arg0, int): - op.cop = self.csolver.mkOp(k.k, <int?> arg0) + args[0].encode()) + elif isinstance(args[0], int): + op.cop = self.csolver.mkOp(k.k, <int?> args[0]) + elif isinstance(args[0], list): + for a in args[0]: + v.push_back((<int?> a)) + op.cop = self.csolver.mkOp(k.k, <const vector[uint32_t]&> v) else: raise ValueError("Unsupported signature" - " mkOp: {}".format(" X ".join([str(k), str(arg0)]))) - else: - if isinstance(arg0, int) and isinstance(arg1, int): - op.cop = self.csolver.mkOp(k.k, <int> arg0, - <int> arg1) + " mkOp: {}".format(" X ".join([str(k), str(args[0])]))) + elif len(args) == 2: + if isinstance(args[0], int) and isinstance(args[1], int): + op.cop = self.csolver.mkOp(k.k, <int> args[0], <int> args[1]) else: raise ValueError("Unsupported signature" - " mkOp: {}".format(" X ".join([k, arg0, arg1]))) + " mkOp: {}".format(" X ".join([k, args[0], args[1]]))) return op def mkTrue(self): @@ -781,17 +817,24 @@ cdef class Solver: term.cterm = self.csolver.mkEmptySet(s.csort) return term + def mkEmptyBag(self, Sort s): + cdef Term term = Term(self) + term.cterm = self.csolver.mkEmptyBag(s.csort) + return term def mkSepNil(self, Sort sort): cdef Term term = Term(self) term.cterm = self.csolver.mkSepNil(sort.csort) return term - def mkString(self, str s): + def mkString(self, str s, useEscSequences = None): cdef Term term = Term(self) cdef Py_ssize_t size cdef wchar_t* tmp = PyUnicode_AsWideCharString(s, &size) - term.cterm = self.csolver.mkString(c_wstring(tmp, size)) + if isinstance(useEscSequences, bool): + term.cterm = self.csolver.mkString(s.encode(), <bint> useEscSequences) + else: + term.cterm = self.csolver.mkString(c_wstring(tmp, size)) PyMem_Free(tmp) return term @@ -1867,3 +1910,30 @@ for rm_int, name in __rounding_modes.items(): del r del rm_int del name + + +# Generate unknown explanations +cdef __unknown_explanations = { + <int> REQUIRES_FULL_CHECK: "RequiresFullCheck", + <int> INCOMPLETE: "Incomplete", + <int> TIMEOUT: "Timeout", + <int> RESOURCEOUT: "Resourceout", + <int> MEMOUT: "Memout", + <int> INTERRUPTED: "Interrupted", + <int> NO_STATUS: "NoStatus", + <int> UNSUPPORTED: "Unsupported", + <int> OTHER: "Other", + <int> UNKNOWN_REASON: "UnknownReason" +} + +for ue_int, name in __unknown_explanations.items(): + u = UnknownExplanation(ue_int) + + if name in dir(mod_ref): + raise RuntimeError("Redefinition of Python UnknownExplanation %s."%name) + + setattr(mod_ref, name, u) + +del u +del ue_int +del name diff --git a/src/base/configuration.cpp b/src/base/configuration.cpp index 61951841b..c6b004574 100644 --- a/src/base/configuration.cpp +++ b/src/base/configuration.cpp @@ -120,25 +120,23 @@ std::string Configuration::copyright() { << "See licenses/antlr3-LICENSE for copyright and licensing information." << "\n\n"; - if (Configuration::isBuiltWithAbc() || Configuration::isBuiltWithCadical() + ss << "This version of cvc5 is linked against the following non-(L)GPL'ed\n" + << "third party libraries.\n\n"; + + ss << " CaDiCaL - Simplified Satisfiability Solver\n" + << " See https://github.com/arminbiere/cadical for copyright " + << "information.\n\n"; + + if (Configuration::isBuiltWithAbc() || Configuration::isBuiltWithCryptominisat() || Configuration::isBuiltWithKissat() - || Configuration::isBuiltWithSymFPU() || Configuration::isBuiltWithEditline()) { - ss << "This version of cvc5 is linked against the following non-(L)GPL'ed\n" - << "third party libraries.\n\n"; if (Configuration::isBuiltWithAbc()) { ss << " ABC - A System for Sequential Synthesis and Verification\n" << " See http://bitbucket.org/alanmi/abc for copyright and\n" << " licensing information.\n\n"; } - if (Configuration::isBuiltWithCadical()) - { - ss << " CaDiCaL - Simplified Satisfiability Solver\n" - << " See https://github.com/arminbiere/cadical for copyright " - << "information.\n\n"; - } if (Configuration::isBuiltWithCryptominisat()) { ss << " CryptoMiniSat - An Advanced SAT Solver\n" @@ -151,12 +149,6 @@ std::string Configuration::copyright() { << " See https://fmv.jku.at/kissat for copyright " << "information.\n\n"; } - if (Configuration::isBuiltWithSymFPU()) - { - ss << " SymFPU - The Symbolic Floating Point Unit\n" - << " See https://github.com/martin-cs/symfpu/tree/cvc5 for copyright " - << "information.\n\n"; - } if (Configuration::isBuiltWithEditline()) { ss << " Editline Library\n" @@ -165,6 +157,10 @@ std::string Configuration::copyright() { } } + ss << " SymFPU - The Symbolic Floating Point Unit\n" + << " See https://github.com/martin-cs/symfpu/tree/cvc5 for copyright " + << "information.\n\n"; + if (Configuration::isBuiltWithGmp() || Configuration::isBuiltWithPoly()) { ss << "This version of cvc5 is linked against the following third party\n" @@ -244,8 +240,6 @@ bool Configuration::isBuiltWithAbc() { return IS_ABC_BUILD; } -bool Configuration::isBuiltWithCadical() { return IS_CADICAL_BUILD; } - bool Configuration::isBuiltWithCryptominisat() { return IS_CRYPTOMINISAT_BUILD; } @@ -259,8 +253,6 @@ bool Configuration::isBuiltWithPoly() return IS_POLY_BUILD; } -bool Configuration::isBuiltWithSymFPU() { return IS_SYMFPU_BUILD; } - unsigned Configuration::getNumDebugTags() { #if defined(CVC5_DEBUG) && defined(CVC5_TRACING) /* -1 because a NULL pointer is inserted as the last value */ diff --git a/src/base/configuration.h b/src/base/configuration.h index 78e86f920..71c79c22e 100644 --- a/src/base/configuration.h +++ b/src/base/configuration.h @@ -103,8 +103,6 @@ public: static bool isBuiltWithAbc(); - static bool isBuiltWithCadical(); - static bool isBuiltWithCryptominisat(); static bool isBuiltWithKissat(); @@ -113,8 +111,6 @@ public: static bool isBuiltWithPoly(); - static bool isBuiltWithSymFPU(); - /* Return the number of debug tags */ static unsigned getNumDebugTags(); /* Return a sorted array of the debug tags name */ diff --git a/src/base/configuration_private.h b/src/base/configuration_private.h index 3027b23bc..b348da380 100644 --- a/src/base/configuration_private.h +++ b/src/base/configuration_private.h @@ -96,12 +96,6 @@ namespace cvc5 { # define IS_ABC_BUILD false #endif /* CVC5_USE_ABC */ -#if CVC5_USE_CADICAL -#define IS_CADICAL_BUILD true -#else /* CVC5_USE_CADICAL */ -#define IS_CADICAL_BUILD false -#endif /* CVC5_USE_CADICAL */ - #if CVC5_USE_CRYPTOMINISAT # define IS_CRYPTOMINISAT_BUILD true #else /* CVC5_USE_CRYPTOMINISAT */ @@ -126,12 +120,6 @@ namespace cvc5 { #define IS_EDITLINE_BUILD false #endif /* HAVE_LIBEDITLINE */ -#ifdef CVC5_USE_SYMFPU -#define IS_SYMFPU_BUILD true -#else /* HAVE_SYMFPU_HEADERS */ -#define IS_SYMFPU_BUILD false -#endif /* HAVE_SYMFPU_HEADERS */ - #if CVC5_GPL_DEPS # define IS_GPL_BUILD true #else /* CVC5_GPL_DEPS */ diff --git a/src/expr/attribute.h b/src/expr/attribute.h index b58cd45a9..e41b63191 100644 --- a/src/expr/attribute.h +++ b/src/expr/attribute.h @@ -38,14 +38,13 @@ namespace attr { /** * Attributes are roughly speaking [almost] global hash tables from Nodes * (TNodes) to data. Attributes can be thought of as additional fields used to - * extend NodeValues. Attributes are mutable and come in both sat - * context-dependent and non-context dependent varieties. Attributes live only - * as long as the node itself does. If a Node is garbage-collected, Attributes - * associated with it will automatically be garbage collected. (Being in the - * domain of an Attribute does not increase a Node's reference count.) To - * achieve this special relationship with Nodes, Attributes are mapped by hash - * tables (AttrHash<> and CDAttrHash<>) that live in the AttributeManager. The - * AttributeManager is owned by the NodeManager. + * extend NodeValues. Attributes are mutable. Attributes live only as long as + * the node itself does. If a Node is garbage-collected, Attributes associated + * with it will automatically be garbage collected. (Being in the domain of an + * Attribute does not increase a Node's reference count.) To achieve this + * special relationship with Nodes, Attributes are mapped by hash tables + * (AttrHash<>) that live in the AttributeManager. The AttributeManager is + * owned by the NodeManager. * * Example: * @@ -67,11 +66,11 @@ namespace attr { * ``` * * To separate Attributes of the same type in the same table, each of the - * structures `struct InstLevelAttributeId {};` is given a different unique value - * at load time. An example is the empty struct InstLevelAttributeId. These - * should be unique for each Attribute. Then via some template messiness when - * InstLevelAttribute() is passed as the argument to getAttribute(...) the load - * time id is instantiated. + * structures `struct InstLevelAttributeId {};` is given a different unique + * value at load time. An example is the empty struct InstLevelAttributeId. + * These should be unique for each Attribute. Then via some template messiness + * when InstLevelAttribute() is passed as the argument to getAttribute(...) the + * load time id is instantiated. */ // ATTRIBUTE MANAGER =========================================================== @@ -97,7 +96,7 @@ class AttributeManager { * getTable<> is a helper template that gets the right table from an * AttributeManager given its type. */ - template <class T, bool context_dep, class Enable> + template <class T, class Enable> friend struct getTable; bool d_inGarbageCollection; @@ -232,12 +231,13 @@ namespace attr { * `std::enable_if` in the template parameter and the condition is false), the * instantiation is ignored due to the SFINAE rule. */ -template <class T, bool context_dep, class Enable = void> +template <class T, class Enable = void> struct getTable; /** Access the "d_bools" member of AttributeManager. */ template <> -struct getTable<bool, false> { +struct getTable<bool> +{ static const AttrTableId id = AttrTableBool; typedef AttrHash<bool> table_type; static inline table_type& get(AttributeManager& am) { @@ -251,7 +251,6 @@ struct getTable<bool, false> { /** Access the "d_ints" member of AttributeManager. */ template <class T> struct getTable<T, - false, // Use this specialization only for unsigned integers typename std::enable_if<std::is_unsigned<T>::value>::type> { @@ -267,7 +266,8 @@ struct getTable<T, /** Access the "d_tnodes" member of AttributeManager. */ template <> -struct getTable<TNode, false> { +struct getTable<TNode> +{ static const AttrTableId id = AttrTableTNode; typedef AttrHash<TNode> table_type; static inline table_type& get(AttributeManager& am) { @@ -280,7 +280,8 @@ struct getTable<TNode, false> { /** Access the "d_nodes" member of AttributeManager. */ template <> -struct getTable<Node, false> { +struct getTable<Node> +{ static const AttrTableId id = AttrTableNode; typedef AttrHash<Node> table_type; static inline table_type& get(AttributeManager& am) { @@ -293,7 +294,8 @@ struct getTable<Node, false> { /** Access the "d_types" member of AttributeManager. */ template <> -struct getTable<TypeNode, false> { +struct getTable<TypeNode> +{ static const AttrTableId id = AttrTableTypeNode; typedef AttrHash<TypeNode> table_type; static inline table_type& get(AttributeManager& am) { @@ -306,7 +308,8 @@ struct getTable<TypeNode, false> { /** Access the "d_strings" member of AttributeManager. */ template <> -struct getTable<std::string, false> { +struct getTable<std::string> +{ static const AttrTableId id = AttrTableString; typedef AttrHash<std::string> table_type; static inline table_type& get(AttributeManager& am) { @@ -329,11 +332,9 @@ typename AttrKind::value_type AttributeManager::getAttribute(NodeValue* nv, const AttrKind&) const { typedef typename AttrKind::value_type value_type; typedef KindValueToTableValueMapping<value_type> mapping; - typedef typename getTable<value_type, AttrKind::context_dependent>:: - table_type table_type; + typedef typename getTable<value_type>::table_type table_type; - const table_type& ah = - getTable<value_type, AttrKind::context_dependent>::get(*this); + const table_type& ah = getTable<value_type>::get(*this); typename table_type::const_iterator i = ah.find(std::make_pair(AttrKind::getId(), nv)); @@ -371,12 +372,9 @@ struct HasAttribute<true, AttrKind> { typename AttrKind::value_type& ret) { typedef typename AttrKind::value_type value_type; typedef KindValueToTableValueMapping<value_type> mapping; - typedef typename getTable<value_type, - AttrKind::context_dependent>::table_type - table_type; + typedef typename getTable<value_type>::table_type table_type; - const table_type& ah = - getTable<value_type, AttrKind::context_dependent>::get(*am); + const table_type& ah = getTable<value_type>::get(*am); typename table_type::const_iterator i = ah.find(std::make_pair(AttrKind::getId(), nv)); @@ -400,11 +398,9 @@ struct HasAttribute<false, AttrKind> { NodeValue* nv) { typedef typename AttrKind::value_type value_type; //typedef KindValueToTableValueMapping<value_type> mapping; - typedef typename getTable<value_type, AttrKind::context_dependent>:: - table_type table_type; + typedef typename getTable<value_type>::table_type table_type; - const table_type& ah = - getTable<value_type, AttrKind::context_dependent>::get(*am); + const table_type& ah = getTable<value_type>::get(*am); typename table_type::const_iterator i = ah.find(std::make_pair(AttrKind::getId(), nv)); @@ -420,11 +416,9 @@ struct HasAttribute<false, AttrKind> { typename AttrKind::value_type& ret) { typedef typename AttrKind::value_type value_type; typedef KindValueToTableValueMapping<value_type> mapping; - typedef typename getTable<value_type, AttrKind::context_dependent>:: - table_type table_type; + typedef typename getTable<value_type>::table_type table_type; - const table_type& ah = - getTable<value_type, AttrKind::context_dependent>::get(*am); + const table_type& ah = getTable<value_type>::get(*am); typename table_type::const_iterator i = ah.find(std::make_pair(AttrKind::getId(), nv)); @@ -460,11 +454,9 @@ AttributeManager::setAttribute(NodeValue* nv, const typename AttrKind::value_type& value) { typedef typename AttrKind::value_type value_type; typedef KindValueToTableValueMapping<value_type> mapping; - typedef typename getTable<value_type, AttrKind::context_dependent>:: - table_type table_type; + typedef typename getTable<value_type>::table_type table_type; - table_type& ah = - getTable<value_type, AttrKind::context_dependent>::get(*this); + table_type& ah = getTable<value_type>::get(*this); ah[std::make_pair(AttrKind::getId(), nv)] = mapping::convert(value); } @@ -473,7 +465,7 @@ template <class T> inline void AttributeManager::deleteFromTable(AttrHash<T>& table, NodeValue* nv) { // This cannot use nv as anything other than a pointer! - const uint64_t last = attr::LastAttributeId<T, false>::getId(); + const uint64_t last = attr::LastAttributeId<T>::getId(); for (uint64_t id = 0; id < last; ++id) { table.erase(std::make_pair(id, nv)); @@ -493,8 +485,7 @@ inline void AttributeManager::deleteAllFromTable(AttrHash<T>& table) { template <class AttrKind> AttributeUniqueId AttributeManager::getAttributeId(const AttrKind& attr){ typedef typename AttrKind::value_type value_type; - AttrTableId tableId = getTable<value_type, - AttrKind::context_dependent>::id; + AttrTableId tableId = getTable<value_type>::id; return AttributeUniqueId(tableId, attr.getId()); } diff --git a/src/expr/attribute_internals.h b/src/expr/attribute_internals.h index c82e62836..2ae216d3c 100644 --- a/src/expr/attribute_internals.h +++ b/src/expr/attribute_internals.h @@ -372,8 +372,9 @@ namespace attr { * This is the last-attribute-assigner. IDs are not globally * unique; rather, they are unique for each table_value_type. */ -template <class T, bool context_dep> -struct LastAttributeId { +template <class T> +struct LastAttributeId +{ public: static uint64_t getNextId() { uint64_t* id = raw_id(); @@ -402,11 +403,8 @@ struct LastAttributeId { * @param T the tag for the attribute kind. * * @param value_t the underlying value_type for the attribute kind - * - * @param context_dep whether this attribute kind is - * context-dependent */ -template <class T, class value_t, bool context_dep = false> +template <class T, class value_t> class Attribute { /** @@ -432,11 +430,6 @@ public: static const bool has_default_value = false; /** - * Expose this setting to the users of this Attribute kind. - */ - static const bool context_dependent = context_dep; - - /** * Register this attribute kind and check that the ID is a valid ID * for bool-valued attributes. Fail an assert if not. Otherwise * return the id. @@ -444,15 +437,15 @@ public: static inline uint64_t registerAttribute() { typedef typename attr::KindValueToTableValueMapping<value_t>:: table_value_type table_value_type; - return attr::LastAttributeId<table_value_type, context_dep>::getNextId(); + return attr::LastAttributeId<table_value_type>::getNextId(); } };/* class Attribute<> */ /** * An "attribute type" structure for boolean flags (special). */ -template <class T, bool context_dep> -class Attribute<T, bool, context_dep> +template <class T> +class Attribute<T, bool> { /** IDs for bool-valued attributes are actually bit assignments. */ static const uint64_t s_id; @@ -480,17 +473,12 @@ public: static const bool default_value = false; /** - * Expose this setting to the users of this Attribute kind. - */ - static const bool context_dependent = context_dep; - - /** * Register this attribute kind and check that the ID is a valid ID * for bool-valued attributes. Fail an assert if not. Otherwise * return the id. */ static inline uint64_t registerAttribute() { - const uint64_t id = attr::LastAttributeId<bool, context_dep>::getNextId(); + const uint64_t id = attr::LastAttributeId<bool>::getNextId(); AlwaysAssert(id <= 63) << "Too many boolean node attributes registered " "during initialization !"; return id; @@ -500,15 +488,14 @@ public: // ATTRIBUTE IDENTIFIER ASSIGNMENT ============================================= /** Assign unique IDs to attributes at load time. */ -template <class T, class value_t, bool context_dep> -const uint64_t Attribute<T, value_t, context_dep>::s_id = - Attribute<T, value_t, context_dep>::registerAttribute(); - +template <class T, class value_t> +const uint64_t Attribute<T, value_t>::s_id = + Attribute<T, value_t>::registerAttribute(); /** Assign unique IDs to attributes at load time. */ -template <class T, bool context_dep> -const uint64_t Attribute<T, bool, context_dep>::s_id = - Attribute<T, bool, context_dep>::registerAttribute(); +template <class T> +const uint64_t Attribute<T, bool>::s_id = + Attribute<T, bool>::registerAttribute(); } // namespace expr } // namespace cvc5 diff --git a/src/main/command_executor.cpp b/src/main/command_executor.cpp index 6bdc1abc9..b6ead1b70 100644 --- a/src/main/command_executor.cpp +++ b/src/main/command_executor.cpp @@ -26,7 +26,8 @@ #include <vector> #include "main/main.h" -#include "options/options_public.h" +#include "options/base_options.h" +#include "options/main_options.h" #include "smt/command.h" #include "smt/smt_engine.h" @@ -65,7 +66,7 @@ CommandExecutor::~CommandExecutor() void CommandExecutor::printStatistics(std::ostream& out) const { - if (options::getStatistics(d_options)) + if (d_options.base.statistics) { getSmtEngine()->printStatistics(out); } @@ -73,7 +74,7 @@ void CommandExecutor::printStatistics(std::ostream& out) const void CommandExecutor::printStatisticsSafe(int fd) const { - if (options::getStatistics(d_options)) + if (d_options.base.statistics) { getSmtEngine()->printStatisticsSafe(fd); } @@ -81,7 +82,7 @@ void CommandExecutor::printStatisticsSafe(int fd) const bool CommandExecutor::doCommand(Command* cmd) { - if (options::getParseOnly(d_options)) + if (d_options.base.parseOnly) { return true; } @@ -100,9 +101,9 @@ bool CommandExecutor::doCommand(Command* cmd) return status; } else { - if (options::getVerbosity(d_options) > 2) + if (d_options.base.verbosity > 2) { - *options::getOut(d_options) << "Invoking: " << *cmd << std::endl; + *d_options.base.out << "Invoking: " << *cmd << std::endl; } return doCommandSingleton(cmd); @@ -111,7 +112,7 @@ bool CommandExecutor::doCommand(Command* cmd) void CommandExecutor::reset() { - printStatistics(*options::getErr(d_options)); + printStatistics(*d_options.base.err); /* We have to keep options passed via CL on reset. These options are stored * in CommandExecutor::d_options (populated and created in the driver), and * CommandExecutor::d_options only contains *these* options since the @@ -124,10 +125,10 @@ void CommandExecutor::reset() bool CommandExecutor::doCommandSingleton(Command* cmd) { bool status = true; - if (options::getVerbosity(d_options) >= -1) + if (d_options.base.verbosity >= -1) { status = solverInvoke( - d_solver.get(), d_symman.get(), cmd, options::getOut(d_options)); + d_solver.get(), d_symman.get(), cmd, d_options.base.out); } else { @@ -150,9 +151,9 @@ bool CommandExecutor::doCommandSingleton(Command* cmd) d_result = res = q->getResult(); } - if ((cs != nullptr || q != nullptr) && options::getStatsEveryQuery(d_options)) + if ((cs != nullptr || q != nullptr) && d_options.base.statisticsEveryQuery) { - getSmtEngine()->printStatisticsDiff(*options::getErr(d_options)); + getSmtEngine()->printStatisticsDiff(*d_options.base.err); } bool isResultUnsat = res.isUnsat() || res.isEntailed(); @@ -160,32 +161,32 @@ bool CommandExecutor::doCommandSingleton(Command* cmd) // dump the model/proof/unsat core if option is set if (status) { std::vector<std::unique_ptr<Command> > getterCommands; - if (options::getDumpModels(d_options) + if (d_options.driver.dumpModels && (res.isSat() || (res.isSatUnknown() && res.getUnknownExplanation() == api::Result::INCOMPLETE))) { getterCommands.emplace_back(new GetModelCommand()); } - if (options::getDumpProofs(d_options) && isResultUnsat) + if (d_options.driver.dumpProofs && isResultUnsat) { getterCommands.emplace_back(new GetProofCommand()); } - if (options::getDumpInstantiations(d_options) + if (d_options.driver.dumpInstantiations && GetInstantiationsCommand::isEnabled(d_solver.get(), res)) { getterCommands.emplace_back(new GetInstantiationsCommand()); } - if (options::getDumpUnsatCores(d_options) && isResultUnsat) + if ((d_options.driver.dumpUnsatCores || d_options.driver.dumpUnsatCoresFull) && isResultUnsat) { getterCommands.emplace_back(new GetUnsatCoreCommand()); } if (!getterCommands.empty()) { // set no time limit during dumping if applicable - if (options::getForceNoLimitCpuWhileDump(d_options)) + if (d_options.driver.forceNoLimitCpuWhileDump) { setNoLimitCPU(); } @@ -225,17 +226,17 @@ bool solverInvoke(api::Solver* solver, } void CommandExecutor::flushOutputStreams() { - printStatistics(*(options::getErr(d_options))); + printStatistics(*d_options.base.err); // make sure out and err streams are flushed too - if (options::getOut(d_options) != nullptr) + if (d_options.base.out != nullptr) { - *options::getOut(d_options) << std::flush; + *d_options.base.out << std::flush; } - if (options::getErr(d_options) != nullptr) + if (d_options.base.err != nullptr) { - *options::getErr(d_options) << std::flush; + *d_options.base.err << std::flush; } } diff --git a/src/main/driver_unified.cpp b/src/main/driver_unified.cpp index 75c7b2a01..2bc5c59f3 100644 --- a/src/main/driver_unified.cpp +++ b/src/main/driver_unified.cpp @@ -33,8 +33,9 @@ #include "main/main.h" #include "main/signal_handlers.h" #include "main/time_limit.h" +#include "options/base_options.h" #include "options/options.h" -#include "options/options_public.h" +#include "options/parser_options.h" #include "options/main_options.h" #include "options/set_language.h" #include "parser/parser.h" @@ -88,9 +89,9 @@ void printUsage(Options& opts, bool full) { << endl << "cvc5 options:" << endl; if(full) { - Options::printUsage(ss.str(), *(options::getOut(opts))); + Options::printUsage(ss.str(), *opts.base.out); } else { - Options::printShortUsage(ss.str(), *(options::getOut(opts))); + Options::printShortUsage(ss.str(), *opts.base.out); } } @@ -116,14 +117,14 @@ int runCvc5(int argc, char* argv[], Options& opts) printUsage(opts, true); exit(1); } - else if (options::getLanguageHelp(opts)) + else if (opts.base.languageHelp) { - Options::printLanguageHelp(*(options::getOut(opts))); + Options::printLanguageHelp(*opts.base.out); exit(1); } else if (opts.driver.version) { - *(options::getOut(opts)) << Configuration::about().c_str() << flush; + *opts.base.out << Configuration::about().c_str() << flush; exit(0); } @@ -131,7 +132,7 @@ int runCvc5(int argc, char* argv[], Options& opts) // If in competition mode, set output stream option to flush immediately #ifdef CVC5_COMPETITION_MODE - *(options::getOut(opts)) << unitbuf; + *opts.base.out << unitbuf; #endif /* CVC5_COMPETITION_MODE */ // We only accept one input file @@ -143,7 +144,7 @@ int runCvc5(int argc, char* argv[], Options& opts) const bool inputFromStdin = filenames.empty() || filenames[0] == "-"; // if we're reading from stdin on a TTY, default to interactive mode - if (!options::wasSetByUserInteractive(opts)) + if (!opts.driver.interactiveWasSetByUser) { opts.driver.interactive = inputFromStdin && isatty(fileno(stdin)); } @@ -157,33 +158,32 @@ int runCvc5(int argc, char* argv[], Options& opts) } const char* filename = filenameStr.c_str(); - if (options::getInputLanguage(opts) == language::input::LANG_AUTO) + if (opts.base.inputLanguage == language::input::LANG_AUTO) { if( inputFromStdin ) { // We can't do any fancy detection on stdin - options::setInputLanguage(language::input::LANG_CVC, opts); + opts.base.inputLanguage = language::input::LANG_CVC; } else { size_t len = filenameStr.size(); if(len >= 5 && !strcmp(".smt2", filename + len - 5)) { - options::setInputLanguage(language::input::LANG_SMTLIB_V2_6, opts); + opts.base.inputLanguage = language::input::LANG_SMTLIB_V2_6; } else if((len >= 2 && !strcmp(".p", filename + len - 2)) || (len >= 5 && !strcmp(".tptp", filename + len - 5))) { - options::setInputLanguage(language::input::LANG_TPTP, opts); + opts.base.inputLanguage = language::input::LANG_TPTP; } else if(( len >= 4 && !strcmp(".cvc", filename + len - 4) ) || ( len >= 5 && !strcmp(".cvc4", filename + len - 5) )) { - options::setInputLanguage(language::input::LANG_CVC, opts); + opts.base.inputLanguage = language::input::LANG_CVC; } else if((len >= 3 && !strcmp(".sy", filename + len - 3)) || (len >= 3 && !strcmp(".sl", filename + len - 3))) { // version 2 sygus is the default - options::setInputLanguage(language::input::LANG_SYGUS_V2, opts); + opts.base.inputLanguage = language::input::LANG_SYGUS_V2; } } } - if (options::getOutputLanguage(opts) == language::output::LANG_AUTO) + if (opts.base.outputLanguage == language::output::LANG_AUTO) { - options::setOutputLanguage( - language::toOutputLanguage(options::getInputLanguage(opts)), opts); + opts.base.outputLanguage = language::toOutputLanguage(opts.base.inputLanguage); } // Determine which messages to show based on smtcomp_mode and verbosity @@ -197,8 +197,8 @@ int runCvc5(int argc, char* argv[], Options& opts) } // important even for muzzled builds (to get result output right) - (*(options::getOut(opts))) - << language::SetLanguage(options::getOutputLanguage(opts)); + (*opts.base.out) + << language::SetLanguage(opts.base.outputLanguage); // Create the command executor to execute the parsed commands pExecutor = std::make_unique<CommandExecutor>(opts); @@ -213,7 +213,7 @@ int runCvc5(int argc, char* argv[], Options& opts) bool status = true; if (opts.driver.interactive && inputFromStdin) { - if (!options::wasSetByUserIncrementalSolving(opts)) + if (!opts.base.incrementalSolvingWasSetByUser) { cmd.reset(new SetOptionCommand("incremental", "true")); cmd->setMuted(true); @@ -240,7 +240,7 @@ int runCvc5(int argc, char* argv[], Options& opts) try { cmd.reset(shell.readCommand()); } catch(UnsafeInterruptException& e) { - (*options::getOut(opts)) << CommandInterrupted(); + *opts.base.out << CommandInterrupted(); break; } if (cmd == nullptr) @@ -253,7 +253,7 @@ int runCvc5(int argc, char* argv[], Options& opts) } else { - if (!options::wasSetByUserIncrementalSolving(opts)) + if (!opts.base.incrementalSolvingWasSetByUser) { cmd.reset(new SetOptionCommand("incremental", "false")); cmd->setMuted(true); @@ -266,20 +266,20 @@ int runCvc5(int argc, char* argv[], Options& opts) std::unique_ptr<Parser> parser(parserBuilder.build()); if( inputFromStdin ) { parser->setInput(Input::newStreamInput( - options::getInputLanguage(opts), cin, filename)); + opts.base.inputLanguage, cin, filename)); } else { - parser->setInput(Input::newFileInput(options::getInputLanguage(opts), + parser->setInput(Input::newFileInput(opts.base.inputLanguage, filename, - options::getMemoryMap(opts))); + opts.parser.memoryMap)); } bool interrupted = false; while (status) { if (interrupted) { - (*options::getOut(opts)) << CommandInterrupted(); + *opts.base.out << CommandInterrupted(); pExecutor->reset(); break; } @@ -313,9 +313,9 @@ int runCvc5(int argc, char* argv[], Options& opts) } #ifdef CVC5_COMPETITION_MODE - if (cvc5::options::getOut(opts) != nullptr) + if (opts.base.out != nullptr) { - *cvc5::options::getOut(opts) << std::flush; + *opts.base.out << std::flush; } // exit, don't return (don't want destructors to run) // _exit() from unistd.h doesn't run global destructors @@ -327,7 +327,7 @@ int runCvc5(int argc, char* argv[], Options& opts) pExecutor->flushOutputStreams(); #ifdef CVC5_DEBUG - if (opts.driver.earlyExit && options::wasSetByUserEarlyExit(opts)) + if (opts.driver.earlyExit && opts.driver.earlyExitWasSetByUser) { _exit(returnValue); } diff --git a/src/main/interactive_shell.cpp b/src/main/interactive_shell.cpp index 048c101f0..964b88ea0 100644 --- a/src/main/interactive_shell.cpp +++ b/src/main/interactive_shell.cpp @@ -40,10 +40,11 @@ #include "base/check.h" #include "base/output.h" #include "expr/symbol_manager.h" +#include "options/base_options.h" #include "options/language.h" #include "options/main_options.h" #include "options/options.h" -#include "options/options_public.h" +#include "options/parser_options.h" #include "parser/input.h" #include "parser/parser.h" #include "parser/parser_builder.h" @@ -89,16 +90,16 @@ static set<string> s_declarations; InteractiveShell::InteractiveShell(api::Solver* solver, SymbolManager* sm) : d_options(solver->getOptions()), - d_in(*options::getIn(d_options)), - d_out(*options::getOut(d_options)), + d_in(*d_options.base.in), + d_out(*d_options.base.out), d_quit(false) { ParserBuilder parserBuilder(solver, sm, d_options); /* Create parser with bogus input. */ d_parser = parserBuilder.build(); - if (options::wasSetByUserForceLogicString(d_options)) + if (d_options.parser.forceLogicStringWasSetByUser) { - LogicInfo tmp(options::getForceLogicString(d_options)); + LogicInfo tmp(d_options.parser.forceLogicString); d_parser->forceLogic(tmp.getLogicString()); } @@ -113,7 +114,7 @@ InteractiveShell::InteractiveShell(api::Solver* solver, SymbolManager* sm) ::using_history(); OutputLanguage lang = - toOutputLanguage(options::getInputLanguage(d_options)); + toOutputLanguage(d_options.base.inputLanguage); switch(lang) { case output::LANG_CVC: d_historyFilename = string(getenv("HOME")) + "/.cvc5_history"; @@ -314,7 +315,7 @@ restart: } d_parser->setInput(Input::newStringInput( - options::getInputLanguage(d_options), input, INPUT_FILENAME)); + d_options.base.inputLanguage, input, INPUT_FILENAME)); /* There may be more than one command in the input. Build up a sequence. */ @@ -365,7 +366,7 @@ restart: } catch (ParserException& pe) { - if (language::isOutputLang_smt2(options::getOutputLanguage(d_options))) + if (language::isOutputLang_smt2(d_options.base.outputLanguage)) { d_out << "(error \"" << pe << "\")" << endl; } diff --git a/src/main/main.cpp b/src/main/main.cpp index 2b25e6c93..a00e29b04 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -26,10 +26,10 @@ #include "base/output.h" #include "main/command_executor.h" #include "main/interactive_shell.h" +#include "options/base_options.h" #include "options/language.h" #include "options/option_exception.h" #include "options/options.h" -#include "options/options_public.h" #include "parser/parser.h" #include "parser/parser_builder.h" #include "parser/parser_exception.h" @@ -53,25 +53,25 @@ int main(int argc, char* argv[]) { return runCvc5(argc, argv, opts); } catch(OptionException& e) { #ifdef CVC5_COMPETITION_MODE - *options::getOut(opts) << "unknown" << endl; + *opts.base.out << "unknown" << endl; #endif cerr << "(error \"" << e << "\")" << endl << endl << "Please use --help to get help on command-line options." << endl; } catch(Exception& e) { #ifdef CVC5_COMPETITION_MODE - *options::getOut(opts) << "unknown" << endl; + *opts.base.out << "unknown" << endl; #endif - if (language::isOutputLang_smt2(options::getOutputLanguage(opts))) + if (language::isOutputLang_smt2(opts.base.outputLanguage)) { - *options::getOut(opts) << "(error \"" << e << "\")" << endl; + *opts.base.out << "(error \"" << e << "\")" << endl; } else { - *options::getErr(opts) << "(error \"" << e << "\")" << endl; + *opts.base.err << "(error \"" << e << "\")" << endl; } - if (options::getStatistics(opts) && pExecutor != nullptr) + if (opts.base.statistics && pExecutor != nullptr) { totalTime.reset(); - pExecutor->printStatistics(*options::getErr(opts)); + pExecutor->printStatistics(*opts.base.err); } } exit(1); diff --git a/src/main/time_limit.cpp b/src/main/time_limit.cpp index c0fc6846a..28a0087bb 100644 --- a/src/main/time_limit.cpp +++ b/src/main/time_limit.cpp @@ -56,7 +56,7 @@ #include <cstring> #include "base/exception.h" -#include "options/options_public.h" +#include "options/base_options.h" #include "signal_handlers.h" namespace cvc5 { @@ -80,7 +80,7 @@ TimeLimit::~TimeLimit() TimeLimit install_time_limit(const Options& opts) { - unsigned long ms = options::getCumulativeTimeLimit(opts); + uint64_t ms = opts.base.cumulativeMillisecondLimit; // Skip if no time limit shall be set. if (ms == 0) { return TimeLimit(); diff --git a/src/omt/bitvector_optimizer.cpp b/src/omt/bitvector_optimizer.cpp index bce6c9b6d..01cb6da42 100644 --- a/src/omt/bitvector_optimizer.cpp +++ b/src/omt/bitvector_optimizer.cpp @@ -53,15 +53,13 @@ OptimizationResult OMTOptimizerBitVector::minimize(SmtEngine* optChecker, Result intermediateSatResult = optChecker->checkSat(); // Model-value of objective (used in optimization loop) Node value; - if (intermediateSatResult.isUnknown()) + if (intermediateSatResult.isUnknown() + || intermediateSatResult.isSat() == Result::UNSAT) { - return OptimizationResult(OptimizationResult::UNKNOWN, value); + return OptimizationResult(intermediateSatResult, value); } - if (intermediateSatResult.isSat() == Result::UNSAT) - { - return OptimizationResult(OptimizationResult::UNSAT, value); - } - + // the last result that is SAT + Result lastSatResult = intermediateSatResult; // value equals to upperBound value = optChecker->getValue(target); @@ -104,39 +102,35 @@ OptimizationResult OMTOptimizerBitVector::minimize(SmtEngine* optChecker, nm->mkNode(LTOperator, target, nm->mkConst(pivot)))); } intermediateSatResult = optChecker->checkSat(); - if (intermediateSatResult.isUnknown() || intermediateSatResult.isNull()) - { - optChecker->pop(); - return OptimizationResult(OptimizationResult::UNKNOWN, value); - } - if (intermediateSatResult.isSat() == Result::SAT) + switch (intermediateSatResult.isSat()) { - value = optChecker->getValue(target); - upperBound = value.getConst<BitVector>(); - } - else if (intermediateSatResult.isSat() == Result::UNSAT) - { - if (lowerBound == pivot) - { - // lowerBound == pivot ==> upperbound = lowerbound + 1 - // and lowerbound <= target < upperbound is UNSAT - // return the upperbound + case Result::SAT_UNKNOWN: optChecker->pop(); - return OptimizationResult(OptimizationResult::OPTIMAL, value); - } - else - { - lowerBound = pivot; - } - } - else - { - optChecker->pop(); - return OptimizationResult(OptimizationResult::UNKNOWN, value); + return OptimizationResult(intermediateSatResult, value); + case Result::SAT: + lastSatResult = intermediateSatResult; + value = optChecker->getValue(target); + upperBound = value.getConst<BitVector>(); + break; + case Result::UNSAT: + if (lowerBound == pivot) + { + // lowerBound == pivot ==> upperbound = lowerbound + 1 + // and lowerbound <= target < upperbound is UNSAT + // return the upperbound + optChecker->pop(); + return OptimizationResult(lastSatResult, value); + } + else + { + lowerBound = pivot; + } + break; + default: Unreachable(); } optChecker->pop(); } - return OptimizationResult(OptimizationResult::OPTIMAL, value); + return OptimizationResult(lastSatResult, value); } OptimizationResult OMTOptimizerBitVector::maximize(SmtEngine* optChecker, @@ -148,15 +142,13 @@ OptimizationResult OMTOptimizerBitVector::maximize(SmtEngine* optChecker, Result intermediateSatResult = optChecker->checkSat(); // Model-value of objective (used in optimization loop) Node value; - if (intermediateSatResult.isUnknown()) + if (intermediateSatResult.isUnknown() + || intermediateSatResult.isSat() == Result::UNSAT) { - return OptimizationResult(OptimizationResult::UNKNOWN, value); + return OptimizationResult(intermediateSatResult, value); } - if (intermediateSatResult.isSat() == Result::UNSAT) - { - return OptimizationResult(OptimizationResult::UNSAT, value); - } - + // the last result that is SAT + Result lastSatResult = intermediateSatResult; // value equals to upperBound value = optChecker->getValue(target); @@ -196,39 +188,35 @@ OptimizationResult OMTOptimizerBitVector::maximize(SmtEngine* optChecker, nm->mkNode(GTOperator, target, nm->mkConst(pivot)), nm->mkNode(LEOperator, target, nm->mkConst(upperBound)))); intermediateSatResult = optChecker->checkSat(); - if (intermediateSatResult.isUnknown() || intermediateSatResult.isNull()) - { - optChecker->pop(); - return OptimizationResult(OptimizationResult::UNKNOWN, value); - } - if (intermediateSatResult.isSat() == Result::SAT) + switch (intermediateSatResult.isSat()) { - value = optChecker->getValue(target); - lowerBound = value.getConst<BitVector>(); - } - else if (intermediateSatResult.isSat() == Result::UNSAT) - { - if (lowerBound == pivot) - { - // upperbound = lowerbound + 1 - // and lowerbound < target <= upperbound is UNSAT - // return the lowerbound + case Result::SAT_UNKNOWN: optChecker->pop(); - return OptimizationResult(OptimizationResult::OPTIMAL, value); - } - else - { - upperBound = pivot; - } - } - else - { - optChecker->pop(); - return OptimizationResult(OptimizationResult::UNKNOWN, value); + return OptimizationResult(intermediateSatResult, value); + case Result::SAT: + lastSatResult = intermediateSatResult; + value = optChecker->getValue(target); + lowerBound = value.getConst<BitVector>(); + break; + case Result::UNSAT: + if (lowerBound == pivot) + { + // upperbound = lowerbound + 1 + // and lowerbound < target <= upperbound is UNSAT + // return the lowerbound + optChecker->pop(); + return OptimizationResult(lastSatResult, value); + } + else + { + upperBound = pivot; + } + break; + default: Unreachable(); } optChecker->pop(); } - return OptimizationResult(OptimizationResult::OPTIMAL, value); + return OptimizationResult(lastSatResult, value); } } // namespace cvc5::omt diff --git a/src/omt/integer_optimizer.cpp b/src/omt/integer_optimizer.cpp index 045268337..379b0cd43 100644 --- a/src/omt/integer_optimizer.cpp +++ b/src/omt/integer_optimizer.cpp @@ -33,13 +33,10 @@ OptimizationResult OMTOptimizerInteger::optimize(SmtEngine* optChecker, Result intermediateSatResult = optChecker->checkSat(); // Model-value of objective (used in optimization loop) Node value; - if (intermediateSatResult.isUnknown()) + if (intermediateSatResult.isUnknown() + || intermediateSatResult.isSat() == Result::UNSAT) { - return OptimizationResult(OptimizationResult::UNKNOWN, value); - } - if (intermediateSatResult.isSat() == Result::UNSAT) - { - return OptimizationResult(OptimizationResult::UNSAT, value); + return OptimizationResult(intermediateSatResult, value); } // node storing target > old_value (used in optimization loop) Node increment; @@ -56,12 +53,14 @@ OptimizationResult OMTOptimizerInteger::optimize(SmtEngine* optChecker, // then assert optimization_target > current_model_value incrementalOperator = kind::GT; } + Result lastSatResult = intermediateSatResult; // Workhorse of linear search: // This loop will keep incrmenting/decrementing the objective until unsat // When unsat is hit, // the optimized value is the model value just before the unsat call while (intermediateSatResult.isSat() == Result::SAT) { + lastSatResult = intermediateSatResult; value = optChecker->getValue(target); Assert(!value.isNull()); increment = nm->mkNode(incrementalOperator, target, value); @@ -69,7 +68,7 @@ OptimizationResult OMTOptimizerInteger::optimize(SmtEngine* optChecker, intermediateSatResult = optChecker->checkSat(); } optChecker->pop(); - return OptimizationResult(OptimizationResult::OPTIMAL, value); + return OptimizationResult(lastSatResult, value); } OptimizationResult OMTOptimizerInteger::minimize(SmtEngine* optChecker, diff --git a/src/options/CMakeLists.txt b/src/options/CMakeLists.txt index 978c32888..cc7b621a8 100644 --- a/src/options/CMakeLists.txt +++ b/src/options/CMakeLists.txt @@ -17,7 +17,6 @@ check_python_module("toml") libcvc5_add_sources( - base_handlers.h decision_weight.h didyoumean.cpp didyoumean.h @@ -55,7 +54,6 @@ set(options_toml_files proof_options.toml prop_options.toml quantifiers_options.toml - resource_manager_options.toml sep_options.toml sets_options.toml smt_options.toml diff --git a/src/options/README b/src/options/README deleted file mode 100644 index 868690b85..000000000 --- a/src/options/README +++ /dev/null @@ -1,127 +0,0 @@ -Modules -======= - - Each options module starts with the following required attributes: - - id ... (string) ID of the module (e.g., "ARITH") - name ... (string) name of the module (e.g., "Arithmetic Theory") - header ... (string) name of the options header to generated (e.g., "options/arith_options.h") - - A module defines 0 or more options. - - In general, each attribute/value pair is required to be in one line. - Comments start with # and are not allowed in attribute/value lines. - - -Options -======= - - Options can be defined with the [[option]] tag, the required attributes for - an option are: - - category ... (string) common | expert | regular | undocumented - type ... (string) C++ type of the option value - - Optional attributes are: - - name ... (string) option name that is used to access via - options::<name>() - smt_name ... (string) alternative name to access option via - set-option/get-option commands - short ... (string) short option name consisting of one character - (no '-' prefix required) - long ... (string) long option name (required if short is specified, - no '--' prefix required). - long option names may have a suffix '=XXX' where - 'XXX' can be used to indicate the type of the - option value, e.g., '=MODE', '=LANG', '=N', ... - default ... (string) default value of type 'type' - handler ... (string) handler for parsing option values before setting - option - predicates ... (list) functions that check whether given option value is - valid - includes ... (list) header files required by handler/predicates - alternate ... (bool) true (default): add --no-<long> alternative option - false: omit --no-<long> alternative option - help ... (string) documentation (required if category is not - undocumented) - - Note that if an option defines a long option name with type 'bool', - mkoptions.py automatically generates a --no-<long> option to set the option - to false. - This behaviour can be explicitely disabled for options with attribute - alternate = false. - More information on how to use handler and predicates can be found - at the end of the README. - - - Example: - - [[option]] - name = "outputLanguage" - smt_name = "output-language" - category = "common" - short = "" - long = "output-lang=LANG" - type = "OutputLanguage" - default = "language::output::LANG_AUTO" - handler = "stringToOutputLanguage" - predicates = [] - includes = ["options/language.h"] - help = "force output language (default is \"auto\"; see --output-lang help)" - - -Further information (the old option package) -============================================ - - The options/ package supports a wide range of operations for responding to - an option being set. Roughly the three major concepts are: - - - handler to parse an option before setting its value. - - predicates to reject bad values for the option. - - More details on each class of custom handlers. - - - handler = "" - - Handlers provide support for parsing custom option types. - The signature for a handler call is: - - T custom-option-handler(std::string option, std::string optarg, - OptionsHandler* handler); - - where T is the type of the option. The suggested implementation is to - implement custom-handler as a dispatch into a function on handler with the - signature: - - T OptionsHandler::custom-option-handler(std::string option, - std::string optarg); - - The handlers are run before predicates. - Having multiple handlers is considered bad practice and is unsupported. - Handlers may have arbitrary side effects, but should call no code - inaccessible to liboptions. For side effects that are not required in order - to parse the option, using :predicate is recommended. Memory - management done by a handler needs to either be encapsulated by the type - and the destructor for the type or should *always* be owned by handler. - More elaborate memory management schemes are not currently supported. - - - predicates = [...] - - Predicates provide support for checking whether or not the value of an - option is acceptable. Predicates are run after handlers. - The signature for a predicate call is: - - void custom-predicate(std::string option, T value, - OptionsHandler* handler); - - where T is the type of the option. The suggested implementation is to - implement custom-predicate as a dispatch into a function on handler with - the signature: - - void OptionsHandler::custom-predicate(std::string option, T value); - - The predicates are run after handlers. Multiple - predicates may be defined for the same option, but the order they are run - is not guaranteed. Predicates may have arbitrary side effects, but should - call no code inaccessible to liboptions. diff --git a/src/options/README.md b/src/options/README.md new file mode 100644 index 000000000..df5686abc --- /dev/null +++ b/src/options/README.md @@ -0,0 +1,211 @@ +Specifying Modules +================== + +Every options module, that is a group of options that belong together in some +way, is declared in its own file in `options/{module name}_options.toml`. Each +options module starts with the following required attributes: + +* `id` (string): ID of the module (e.g., `"arith"`) +* `name` (string): name of the module (e.g., `"Arithmetic Theory"`) + +Additional, a module can optionally be defined to be public. A public module +includes `cvc5_public.h` instead of `cvc5_private.h` can thus be included from +"external" code like the parser or the main driver. + +* `public` (bool): make option module public + +A module defines 0 or more options. + +In general, each attribute/value pair is required to be in one line. Comments +start with # and are not allowed in attribute/value lines. + +After parsing, a module is extended to have the following attributes: + +* `id`: lower-case version of the parsed `id` +* `id_cap`: upper-case version of `id` (used for the `Holder{id_cap}` class) +* `filename`: base filename for generated files (`"{id}_options"`) +* `header`: generated header name (`"options/{filename}.h"`) + + +Specifying Options +================== + +Options can be defined within a module file with the `[[option]]` tag, the +required attributes for an option are: + +* `category` (string): one of `common`, `expert`, `regular`, or `undocumented` +* `type` (string): the C++ type of the option value + +Optional attributes are: + +* `name` (string): the option name used to access the option internally + (`d_option.{module.id}.{name}`) +* `long` (string): long option name (without `--` prefix). Long option names may + have a suffix `=XXX` where `XXX` can be used to indicate the type of the + option value, e.g., `=MODE`, `=LANG`, `=N`, ... +* `short` (string): short option name consisting of one character (no `-` prefix + required), can be given if `long` is specified +* `alias` (list): alternative names that can be used instead of `long` +* `default` (string): default value, needs to be a valid C++ expression of type + `type` +* `alternate` (bool, default `true`): if `true`, adds `--no-{long}` alternative + option +* `mode` (list): used to define options whose type shall be an auto-generated + enum, more details below +* `handler` (string): alternate parsing routine for option types not covered by + the default parsers, more details below +* `predicates` (list): custom validation function to check whether an option + value is valid, more details below +* `includes` (list): additional header files required by handler or predicate + functions +* `help` (string): documentation string (required, unless the `category` is + `undocumented`) +* `help_mode` (string): documentation for the mode enum (required if `mode` is + given) + + +Handler functions +----------------- + +Custom handler functions are used to turn the option value from a `std::string` +into the type specified by `type`. Standard handler functions are provided for +basic types (`std::string`, `bool`, integer types and floating point types) as +well as enums specified by `mode`. A custom handler function needs to be member +function of `options::OptionsHandler` with signature `{type} {handler}(const +std::string& option, const std::string& flag, const std::string& optionvalue)`, +or alternatively `void {handler}(const std::string& option, const std::string& +flag)` if the `type` is `void`. The two parameters `option` and `flag` hold the +canonical and the actually used option names, respectively, and they may differ +if an alternative name (from `alias`) was used. While `option` should be used to +identify an option (e.g. by comparing against `*__name`), `flag` should be +usually used in user messages. + + +Predicate functions +------------------- + +Predicate functions are used to check whether an option value is valid after it +has been parsed by a (standard or custom) handler function. Like a handler +function, a predicate function needs to be a member function of +`options::OptionsHandler` with signature `void {predicate}(const std::string& +option, const std::string& flag, {type} value)`. If the check fails, the +predicate should raise an `OptionException`. + + +Mode options +------------ + +An option can be defined to hold one of a given set of values we call modes. +Doing so automatically defines an `enum class` for the set of modes and makes +the option accept one of the values from the enum. The enum class will be called +`{type}` and methods `operator<<` and `stringTo{enum}` are automatically +generated. A mode is defined by specifying `[[option.mode.{NAME}]]` after the +main `[[option]]` section with the following attributes: + +* `name` (string): the string value that corresponds to the enum value +* `help` (string): documentation about this mode + +Example: + + [[option]] + name = "bitblastMode" + category = "regular" + long = "bitblast=MODE" + type = "BitblastMode" + default = "LAZY" + help = "choose bitblasting mode, see --bitblast=help" + help_mode = "Bit-blasting modes." + [[option.mode.LAZY]] + name = "lazy" + help = "Separate boolean structure and term reasoning between the core SAT solver and the bit-vector SAT solver." + [[option.mode.EAGER]] + name = "eager" + help = "Bitblast eagerly to bit-vector SAT solver." + +The option can now be set with `--bitblast=lazy`, `(set-option :bitblast +eager)`, or `options::set("bitblast", "eager")`. + + +Generated code +============== + +The entire options setup heavily relies on generating a lot of code from the +information retrieved from the `*_options.toml` files. After code generation, +files related to options live either in `src/options/` (if not changed) or in +`build/src/options/` (if automatically generated). After all code has been +generated, the entire options setup consists of the following components: + +* `options.h`: core `Options` class +* `options_api.h`: utility methods used by the API (`parse()`, `set()`, `get()`, + ...) +* `options_public.h`: utility methods used to access options from outside of + libcvc5 +* `{module}_options.h`: specifics for one single options module + + +`Options` class +--------------- + +The `Options` class is the central entry point for regular usage of options. It +holds a `std::unique_ptr` to an "option holder" for every option module, that +can be accessed using references `{module}` (either as `const&` or `&`). These +holders hold the actual option data for the specific module. + +The holder types are forward declared and can thus only be accessed if one also +includes the appropriate `{module}_options.h`, which contains the proper +declaration for the holder class. + + +Option modules +-------------- + +Every option module declares an "option holder" class, which is a simple struct +that has two members for every option (that is not declared as `type = void`): +the actual option value as `{option.type} {option.name}` and a Boolean flag +`bool {option.name}__setByUser` that indicates whether the option value was +explicitly set by the user. If any of the options of a module is a mode option, +the option module also defines an enum class that corresponds to the mode, +including `operator<<()` and `stringTo{mode type}`. + +For convenience, the option modules also provide methods `void +{module.id}::setDefault{option.name}(Options& opts, {option.type} value)`. Each +such method sets the option value to the given value, if the option was not yet +set by the user, i.e., the `__setByUser` flag is false. Additionally, every +option module exports the `long` option name as `static constexpr const char* +{module.id}::{option.name}__name`. + + +Full Example +============ + + [[option]] + category = "regular" + name = "decisionMode" + long = "decision=MODE" + alias = ["decision-mode"] + type = "DecisionMode" + default = "INTERNAL" + predicates = ["setDecisionModeStopOnly"] + help = "choose decision mode, see --decision=help" + help_mode = "Decision modes." + [[option.mode.INTERNAL]] + name = "internal" + help = "Use the internal decision heuristics of the SAT solver." + [[option.mode.JUSTIFICATION]] + name = "justification" + help = "An ATGP-inspired justification heuristic." + [[option.mode.RELEVANCY]] + name = "justification-stoponly" + help = "Use the justification heuristic only to stop early, not for decisions." + +This defines a new option that is accessible via +`d_options.{module.id}.decisionMode` and stores an automatically generated mode +`DecisionMode`, an enum class with the values `INTERNAL`, `JUSTIFICATION` and +`RELEVANCY`. From the outside, it can be set by `--decision=internal`, but also +with `--decision-mode=justification`, and similarly from an SMT-LIB input with +`(set-option :decision internal)` and `(set-option :decision-mode +justification)`. The command-line help for this option looks as follows: + + --output-lang=LANG | --output-language=LANG + force output language (default is "auto"; see + --output-lang help) diff --git a/src/options/base_handlers.h b/src/options/base_handlers.h deleted file mode 100644 index 86112a907..000000000 --- a/src/options/base_handlers.h +++ /dev/null @@ -1,87 +0,0 @@ -/****************************************************************************** - * Top contributors (to current version): - * Morgan Deters, Tim King, Mathias Preiner - * - * This file is part of the cvc5 project. - * - * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS - * in the top-level source directory and their institutional affiliations. - * All rights reserved. See the file COPYING in the top-level source - * directory for licensing information. - * **************************************************************************** - * - * [[ Add one-line brief description here ]] - * - * [[ Add lengthier description here ]] - * \todo document this file - */ - -#include "cvc5_private.h" - -#ifndef CVC5__BASE_HANDLERS_H -#define CVC5__BASE_HANDLERS_H - -#include <iostream> -#include <string> -#include <sstream> - -#include "options/option_exception.h" - -namespace cvc5 { -namespace options { - -template <template <class U> class Cmp> -class comparator { - long d_lbound; - double d_dbound; - bool d_hasLbound; - - public: - comparator(int i) : d_lbound(i), d_dbound(0.0), d_hasLbound(true) {} - comparator(long l) : d_lbound(l), d_dbound(0.0), d_hasLbound(true) {} - comparator(double d) : d_lbound(0), d_dbound(d), d_hasLbound(false) {} - template <class T> - void operator()(std::string option, const T& value) { - if((d_hasLbound && !(Cmp<T>()(value, T(d_lbound)))) || - (!d_hasLbound && !(Cmp<T>()(value, T(d_dbound))))) { - std::stringstream ss; - ss << option << ": " << value << " is not a legal setting"; - throw OptionException(ss.str()); - } - } -};/* class comparator */ - -struct greater : public comparator<std::greater> { - greater(int i) : comparator<std::greater>(i) {} - greater(long l) : comparator<std::greater>(l) {} - greater(double d) : comparator<std::greater>(d) {} -};/* struct greater */ - -struct greater_equal : public comparator<std::greater_equal> { - greater_equal(int i) : comparator<std::greater_equal>(i) {} - greater_equal(long l) : comparator<std::greater_equal>(l) {} - greater_equal(double d) : comparator<std::greater_equal>(d) {} -};/* struct greater_equal */ - -struct less : public comparator<std::less> { - less(int i) : comparator<std::less>(i) {} - less(long l) : comparator<std::less>(l) {} - less(double d) : comparator<std::less>(d) {} -};/* struct less */ - -struct less_equal : public comparator<std::less_equal> { - less_equal(int i) : comparator<std::less_equal>(i) {} - less_equal(long l) : comparator<std::less_equal>(l) {} - less_equal(double d) : comparator<std::less_equal>(d) {} -};/* struct less_equal */ - -struct not_equal : public comparator<std::not_equal_to> { - not_equal(int i) : comparator<std::not_equal_to>(i) {} - not_equal(long l) : comparator<std::not_equal_to>(l) {} - not_equal(double d) : comparator<std::not_equal_to>(d) {} -};/* struct not_equal_to */ - -} // namespace options -} // namespace cvc5 - -#endif /* CVC5__BASE_HANDLERS_H */ diff --git a/src/options/base_options.toml b/src/options/base_options.toml index f9d1c1a18..64d373509 100644 --- a/src/options/base_options.toml +++ b/src/options/base_options.toml @@ -1,5 +1,6 @@ id = "BASE" name = "Base" +public = true [[option]] name = "in" @@ -76,6 +77,15 @@ name = "Base" help = "decrease verbosity (may be repeated)" [[option]] + name = "incrementalSolving" + category = "common" + short = "i" + long = "incremental" + type = "bool" + default = "true" + help = "enable incremental solving" + +[[option]] name = "statistics" long = "stats" category = "common" @@ -144,3 +154,52 @@ name = "Base" long = "print-success" type = "bool" help = "print the \"success\" output required of SMT-LIBv2" + +[[option]] + name = "cumulativeMillisecondLimit" + category = "common" + long = "tlimit=MS" + type = "uint64_t" + help = "set time limit in milliseconds of wall clock time" + +[[option]] + name = "perCallMillisecondLimit" + category = "common" + long = "tlimit-per=MS" + type = "uint64_t" + help = "set time limit per query in milliseconds" + +[[option]] + name = "cumulativeResourceLimit" + category = "common" + long = "rlimit=N" + type = "uint64_t" + help = "set resource limit" + +[[option]] + name = "perCallResourceLimit" + alias = ["reproducible-resource-limit"] + category = "common" + long = "rlimit-per=N" + type = "uint64_t" + help = "set resource limit per query" + +# --rweight is used to override the default of one particular resource weight. +# It can be given multiple times to override multiple weights. When options are +# parsed, the resource manager might now be created yet, and it is not clear +# how an option handler would access it in a reasonable way. The option handler +# thus merely puts the data in another option that holds a vector of strings. +# This other option "resourceWeightHolder" has the sole purpose of storing +# this data in a way so that the resource manager can access it in its +# constructor. +[[option]] + category = "expert" + long = "rweight=VAL=N" + type = "std::string" + handler = "setResourceWeight" + help = "set a single resource weight" + +[[option]] + name = "resourceWeightHolder" + category = "undocumented" + type = "std::vector<std::string>" diff --git a/src/options/main_options.toml b/src/options/main_options.toml index e8bb8ea72..19bb97f34 100644 --- a/src/options/main_options.toml +++ b/src/options/main_options.toml @@ -87,3 +87,51 @@ public = true type = "bool" default = "false" help = "spin on segfault/other crash waiting for gdb" + +[[option]] + name = "dumpModels" + category = "regular" + long = "dump-models" + type = "bool" + default = "false" + help = "output models after every SAT/INVALID/UNKNOWN response" + +[[option]] + name = "dumpProofs" + category = "regular" + long = "dump-proofs" + type = "bool" + default = "false" + help = "output proofs after every UNSAT/VALID response" + +[[option]] + name = "dumpInstantiations" + category = "regular" + long = "dump-instantiations" + type = "bool" + default = "false" + help = "output instantiations of quantified formulas after every UNSAT/VALID response" + +[[option]] + name = "dumpUnsatCores" + category = "regular" + long = "dump-unsat-cores" + type = "bool" + default = "false" + help = "output unsat cores after every UNSAT/VALID response" + +[[option]] + name = "dumpUnsatCoresFull" + category = "regular" + long = "dump-unsat-cores-full" + type = "bool" + default = "false" + help = "dump the full unsat core, including unlabeled assertions" + +[[option]] + name = "forceNoLimitCpuWhileDump" + category = "regular" + long = "force-no-limit-cpu-while-dump" + type = "bool" + default = "false" + help = "Force no CPU limit when dumping models and proofs"
\ No newline at end of file diff --git a/src/options/mkoptions.py b/src/options/mkoptions.py index 7e1cf68e4..e2fbd4cf1 100644 --- a/src/options/mkoptions.py +++ b/src/options/mkoptions.py @@ -210,6 +210,30 @@ def get_holder_ref_decls(modules): return concat_format(' options::Holder{id_cap}& {id};', modules) +def get_handler(option): + """Render handler call for assignment functions""" + optname = option.long_name if option.long else "" + if option.handler: + if option.type == 'void': + return 'opts.handler().{}("{}", option)'.format(option.handler, optname) + else: + return 'opts.handler().{}("{}", option, optionarg)'.format(option.handler, optname) + elif option.mode: + return 'stringTo{}(optionarg)'.format(option.type) + elif option.type != 'bool': + return 'handleOption<{}>("{}", option, optionarg)'.format(option.type, optname) + return None + + +def get_predicates(option): + """Render predicate calls for assignment functions""" + if not option.predicates: + return [] + optname = option.long_name if option.long else "" + assert option.type != 'void' + return ['opts.handler().{}("{}", option, value);'.format(x, optname) + for x in option.predicates] + class Module(object): """Options module. @@ -713,31 +737,10 @@ def codegen_all_modules(modules, build_dir, dst_dir, tpl_options_h, tpl_options_ sphinxgen.add(module, option) # Generate handler call - handler = None - if option.handler: - if option.type == 'void': - handler = 'opts.handler().{}(option)'.format(option.handler) - else: - handler = \ - 'opts.handler().{}(option, optionarg)'.format(option.handler) - elif option.mode: - handler = 'stringTo{}(optionarg)'.format(option.type) - elif option.type != 'bool': - handler = \ - 'handleOption<{}>(option, optionarg)'.format(option.type) + handler = get_handler(option) # Generate predicate calls - predicates = [] - if option.predicates: - if option.type == 'bool': - predicates = \ - ['opts.handler().{}(option, value);'.format(x) \ - for x in option.predicates] - else: - assert option.type != 'void' - predicates = \ - ['opts.handler().{}(option, value);'.format(x) \ - for x in option.predicates] + predicates = get_predicates(option) # Generate options_handler and getopt_long cases = [] @@ -813,7 +816,7 @@ def codegen_all_modules(modules, build_dir, dst_dir, tpl_options_h, tpl_options_ name=option.name, option='key')) elif option.handler: - h = 'handler->{handler}("{smtname}"' + h = 'handler->{handler}("{smtname}", key' if argument_req: h += ', optionarg' h += ');' diff --git a/src/options/options_handler.cpp b/src/options/options_handler.cpp index c1c843802..07138dce3 100644 --- a/src/options/options_handler.cpp +++ b/src/options/options_handler.cpp @@ -33,7 +33,6 @@ #include "options/didyoumean.h" #include "options/language.h" #include "options/option_exception.h" -#include "options/resource_manager_options.h" #include "options/smt_options.h" #include "options/theory_options.h" @@ -68,10 +67,11 @@ void throwLazyBBUnsupported(options::SatSolverMode m) OptionsHandler::OptionsHandler(Options* options) : d_options(options) { } -unsigned long OptionsHandler::limitHandler(std::string option, - std::string optarg) +uint64_t OptionsHandler::limitHandler(const std::string& option, + const std::string& flag, + const std::string& optarg) { - unsigned long ms; + uint64_t ms; std::istringstream convert(optarg); if (!(convert >> ms)) { @@ -81,14 +81,18 @@ unsigned long OptionsHandler::limitHandler(std::string option, return ms; } -void OptionsHandler::setResourceWeight(std::string option, std::string optarg) +void OptionsHandler::setResourceWeight(const std::string& option, + const std::string& flag, + const std::string& optarg) { - d_options->resman.resourceWeightHolder.emplace_back(optarg); + d_options->base.resourceWeightHolder.emplace_back(optarg); } // theory/quantifiers/options_handlers.h -void OptionsHandler::checkInstWhenMode(std::string option, InstWhenMode mode) +void OptionsHandler::checkInstWhenMode(const std::string& option, + const std::string& flag, + InstWhenMode mode) { if (mode == InstWhenMode::PRE_FULL) { @@ -98,7 +102,9 @@ void OptionsHandler::checkInstWhenMode(std::string option, InstWhenMode mode) } // theory/bv/options_handlers.h -void OptionsHandler::abcEnabledBuild(std::string option, bool value) +void OptionsHandler::abcEnabledBuild(const std::string& option, + const std::string& flag, + bool value) { #ifndef CVC5_USE_ABC if(value) { @@ -111,7 +117,9 @@ void OptionsHandler::abcEnabledBuild(std::string option, bool value) #endif /* CVC5_USE_ABC */ } -void OptionsHandler::abcEnabledBuild(std::string option, std::string value) +void OptionsHandler::abcEnabledBuild(const std::string& option, + const std::string& flag, + const std::string& value) { #ifndef CVC5_USE_ABC if(!value.empty()) { @@ -124,7 +132,9 @@ void OptionsHandler::abcEnabledBuild(std::string option, std::string value) #endif /* CVC5_USE_ABC */ } -void OptionsHandler::checkBvSatSolver(std::string option, SatSolverMode m) +void OptionsHandler::checkBvSatSolver(const std::string& option, + const std::string& flag, + SatSolverMode m) { if (m == SatSolverMode::CRYPTOMINISAT && !Configuration::isBuiltWithCryptominisat()) @@ -136,15 +146,6 @@ void OptionsHandler::checkBvSatSolver(std::string option, SatSolverMode m) throw OptionException(ss.str()); } - if (m == SatSolverMode::CADICAL && !Configuration::isBuiltWithCadical()) - { - std::stringstream ss; - ss << "option `" << option - << "' requires a CaDiCaL build of cvc5; this binary was not built with " - "CaDiCaL support"; - throw OptionException(ss.str()); - } - if (m == SatSolverMode::KISSAT && !Configuration::isBuiltWithKissat()) { std::stringstream ss; @@ -167,7 +168,9 @@ void OptionsHandler::checkBvSatSolver(std::string option, SatSolverMode m) } } -void OptionsHandler::checkBitblastMode(std::string option, BitblastMode m) +void OptionsHandler::checkBitblastMode(const std::string& option, + const std::string& flag, + BitblastMode m) { if (m == options::BitblastMode::LAZY) { @@ -186,7 +189,9 @@ void OptionsHandler::checkBitblastMode(std::string option, BitblastMode m) } } -void OptionsHandler::setBitblastAig(std::string option, bool arg) +void OptionsHandler::setBitblastAig(const std::string& option, + const std::string& flag, + bool arg) { if(arg) { if (d_options->bv.bitblastModeWasSetByUser) { @@ -212,8 +217,9 @@ szs\n\ + Print instantiations as SZS compliant proof.\n\ "; -InstFormatMode OptionsHandler::stringToInstFormatMode(std::string option, - std::string optarg) +InstFormatMode OptionsHandler::stringToInstFormatMode(const std::string& option, + const std::string& flag, + const std::string& optarg) { if(optarg == "default") { return InstFormatMode::DEFAULT; @@ -229,24 +235,30 @@ InstFormatMode OptionsHandler::stringToInstFormatMode(std::string option, } // decision/options_handlers.h -void OptionsHandler::setDecisionModeStopOnly(std::string option, DecisionMode m) +void OptionsHandler::setDecisionModeStopOnly(const std::string& option, + const std::string& flag, + DecisionMode m) { d_options->decision.decisionStopOnly = (m == DecisionMode::RELEVANCY); } -void OptionsHandler::setProduceAssertions(std::string option, bool value) +void OptionsHandler::setProduceAssertions(const std::string& option, + const std::string& flag, + bool value) { d_options->smt.produceAssertions = value; d_options->smt.interactiveMode = value; } -void OptionsHandler::setStats(const std::string& option, bool value) +void OptionsHandler::setStats(const std::string& option, + const std::string& flag, + bool value) { #ifndef CVC5_STATISTICS_ON if (value) { std::stringstream ss; - ss << "option `" << option + ss << "option `" << flag << "' requires a statistics-enabled build of cvc5; this binary was not " "built with statistics support"; throw OptionException(ss.str()); @@ -283,18 +295,25 @@ void OptionsHandler::setStats(const std::string& option, bool value) } } -void OptionsHandler::threadN(std::string option) { - throw OptionException(option + " is not a real option by itself. Use e.g. --thread0=\"--random-seed=10 --random-freq=0.02\" --thread1=\"--random-seed=20 --random-freq=0.05\""); +void OptionsHandler::threadN(const std::string& option, const std::string& flag) +{ + throw OptionException(flag + " is not a real option by itself. Use e.g. --thread0=\"--random-seed=10 --random-freq=0.02\" --thread1=\"--random-seed=20 --random-freq=0.05\""); } // expr/options_handlers.h -void OptionsHandler::setDefaultExprDepthPredicate(std::string option, int depth) { +void OptionsHandler::setDefaultExprDepthPredicate(const std::string& option, + const std::string& flag, + int depth) +{ if(depth < -1) { throw OptionException("--expr-depth requires a positive argument, or -1."); } } -void OptionsHandler::setDefaultDagThreshPredicate(std::string option, int dag) { +void OptionsHandler::setDefaultDagThreshPredicate(const std::string& option, + const std::string& flag, + int dag) +{ if(dag < 0) { throw OptionException("--dag-thresh requires a nonnegative argument."); } @@ -313,12 +332,16 @@ static void print_config_cond (const char * str, bool cond = false) { print_config(str, cond ? "yes" : "no"); } -void OptionsHandler::copyright(std::string option) { +void OptionsHandler::copyright(const std::string& option, + const std::string& flag) +{ std::cout << Configuration::copyright() << std::endl; exit(0); } -void OptionsHandler::showConfiguration(std::string option) { +void OptionsHandler::showConfiguration(const std::string& option, + const std::string& flag) +{ std::cout << Configuration::about() << std::endl; print_config ("version", Configuration::getVersionString()); @@ -365,13 +388,11 @@ void OptionsHandler::showConfiguration(std::string option) { print_config_cond("abc", Configuration::isBuiltWithAbc()); print_config_cond("cln", Configuration::isBuiltWithCln()); print_config_cond("glpk", Configuration::isBuiltWithGlpk()); - print_config_cond("cadical", Configuration::isBuiltWithCadical()); print_config_cond("cryptominisat", Configuration::isBuiltWithCryptominisat()); print_config_cond("gmp", Configuration::isBuiltWithGmp()); print_config_cond("kissat", Configuration::isBuiltWithKissat()); print_config_cond("poly", Configuration::isBuiltWithPoly()); print_config_cond("editline", Configuration::isBuiltWithEditline()); - print_config_cond("symfpu", Configuration::isBuiltWithSymFPU()); exit(0); } @@ -386,7 +407,8 @@ static void printTags(unsigned ntags, char const* const* tags) std::cout << std::endl; } -void OptionsHandler::showDebugTags(std::string option) +void OptionsHandler::showDebugTags(const std::string& option, + const std::string& flag) { if (!Configuration::isDebugBuild()) { @@ -400,7 +422,8 @@ void OptionsHandler::showDebugTags(std::string option) exit(0); } -void OptionsHandler::showTraceTags(std::string option) +void OptionsHandler::showTraceTags(const std::string& option, + const std::string& flag) { if (!Configuration::isTracingBuild()) { @@ -432,7 +455,9 @@ static std::string suggestTags(char const* const* validTags, return didYouMean.getMatchAsString(inputTag); } -void OptionsHandler::enableTraceTag(std::string option, std::string optarg) +void OptionsHandler::enableTraceTag(const std::string& option, + const std::string& flag, + const std::string& optarg) { if(!Configuration::isTracingBuild()) { @@ -454,7 +479,9 @@ void OptionsHandler::enableTraceTag(std::string option, std::string optarg) Trace.on(optarg); } -void OptionsHandler::enableDebugTag(std::string option, std::string optarg) +void OptionsHandler::enableDebugTag(const std::string& option, + const std::string& flag, + const std::string& optarg) { if (!Configuration::isDebugBuild()) { @@ -485,8 +512,9 @@ void OptionsHandler::enableDebugTag(std::string option, std::string optarg) Trace.on(optarg); } -OutputLanguage OptionsHandler::stringToOutputLanguage(std::string option, - std::string optarg) +OutputLanguage OptionsHandler::stringToOutputLanguage(const std::string& option, + const std::string& flag, + const std::string& optarg) { if(optarg == "help") { d_options->base.languageHelp = true; @@ -503,8 +531,9 @@ OutputLanguage OptionsHandler::stringToOutputLanguage(std::string option, Unreachable(); } -InputLanguage OptionsHandler::stringToInputLanguage(std::string option, - std::string optarg) +InputLanguage OptionsHandler::stringToInputLanguage(const std::string& option, + const std::string& flag, + const std::string& optarg) { if(optarg == "help") { d_options->base.languageHelp = true; @@ -521,7 +550,9 @@ InputLanguage OptionsHandler::stringToInputLanguage(std::string option, } /* options/base_options_handlers.h */ -void OptionsHandler::setVerbosity(std::string option, int value) +void OptionsHandler::setVerbosity(const std::string& option, + const std::string& flag, + int value) { if(Configuration::isMuzzledBuild()) { DebugChannel.setStream(&cvc5::null_os); @@ -551,14 +582,18 @@ void OptionsHandler::setVerbosity(std::string option, int value) } } -void OptionsHandler::increaseVerbosity(std::string option) { +void OptionsHandler::increaseVerbosity(const std::string& option, + const std::string& flag) +{ d_options->base.verbosity += 1; - setVerbosity(option, options::verbosity()); + setVerbosity(option, flag, d_options->base.verbosity); } -void OptionsHandler::decreaseVerbosity(std::string option) { +void OptionsHandler::decreaseVerbosity(const std::string& option, + const std::string& flag) +{ d_options->base.verbosity -= 1; - setVerbosity(option, options::verbosity()); + setVerbosity(option, flag, d_options->base.verbosity); } } // namespace options diff --git a/src/options/options_handler.h b/src/options/options_handler.h index 4b9b1c0ae..3b3f80e6c 100644 --- a/src/options/options_handler.h +++ b/src/options/options_handler.h @@ -19,9 +19,9 @@ #define CVC5__OPTIONS__OPTIONS_HANDLER_H #include <ostream> +#include <sstream> #include <string> -#include "options/base_handlers.h" #include "options/bv_options.h" #include "options/decision_options.h" #include "options/language.h" @@ -44,72 +44,117 @@ class OptionsHandler { public: OptionsHandler(Options* options); - void unsignedGreater0(const std::string& option, unsigned value) { - options::greater(0)(option, value); + template <typename T> + void geqZero(const std::string& option, + const std::string& flag, + T value) const + { + if (value < 0) + { + std::stringstream ss; + ss << flag << ": " << value << " is not a legal setting, should be " + << value << " >= 0."; + throw OptionException(ss.str()); + } } - - void unsignedLessEqual2(const std::string& option, unsigned value) { - options::less_equal(2)(option, value); - } - - void doubleGreaterOrEqual0(const std::string& option, double value) { - options::greater_equal(0.0)(option, value); - } - - void doubleLessOrEqual1(const std::string& option, double value) { - options::less_equal(1.0)(option, value); + template <typename T> + void betweenZeroAndOne(const std::string& option, + const std::string& flag, + T value) const + { + if (value < 0 || value > 1) + { + std::stringstream ss; + ss << flag << ": " << value + << " is not a legal setting, should be 0 <= " << flag << " <= 1."; + throw OptionException(ss.str()); + } } // theory/quantifiers/options_handlers.h - void checkInstWhenMode(std::string option, InstWhenMode mode); + void checkInstWhenMode(const std::string& option, + const std::string& flag, + InstWhenMode mode); // theory/bv/options_handlers.h - void abcEnabledBuild(std::string option, bool value); - void abcEnabledBuild(std::string option, std::string value); - - template<class T> void checkSatSolverEnabled(std::string option, T m); - - void checkBvSatSolver(std::string option, SatSolverMode m); - void checkBitblastMode(std::string option, BitblastMode m); - - void setBitblastAig(std::string option, bool arg); + void abcEnabledBuild(const std::string& option, + const std::string& flag, + bool value); + void abcEnabledBuild(const std::string& option, + const std::string& flag, + const std::string& value); + + void checkBvSatSolver(const std::string& option, + const std::string& flag, + SatSolverMode m); + void checkBitblastMode(const std::string& option, + const std::string& flag, + BitblastMode m); + + void setBitblastAig(const std::string& option, + const std::string& flag, + bool arg); // printer/options_handlers.h - InstFormatMode stringToInstFormatMode(std::string option, std::string optarg); + InstFormatMode stringToInstFormatMode(const std::string& option, + const std::string& flag, + const std::string& optarg); // decision/options_handlers.h - void setDecisionModeStopOnly(std::string option, DecisionMode m); + void setDecisionModeStopOnly(const std::string& option, + const std::string& flag, + DecisionMode m); /** * Throws a ModalException if this option is being set after final * initialization. */ - void setProduceAssertions(std::string option, bool value); + void setProduceAssertions(const std::string& option, + const std::string& flag, + bool value); - void setStats(const std::string& option, bool value); + void setStats(const std::string& option, const std::string& flag, bool value); - unsigned long limitHandler(std::string option, std::string optarg); - void setResourceWeight(std::string option, std::string optarg); + uint64_t limitHandler(const std::string& option, + const std::string& flag, + const std::string& optarg); + void setResourceWeight(const std::string& option, + const std::string& flag, + const std::string& optarg); /* expr/options_handlers.h */ - void setDefaultExprDepthPredicate(std::string option, int depth); - void setDefaultDagThreshPredicate(std::string option, int dag); + void setDefaultExprDepthPredicate(const std::string& option, + const std::string& flag, + int depth); + void setDefaultDagThreshPredicate(const std::string& option, + const std::string& flag, + int dag); /* main/options_handlers.h */ - void copyright(std::string option); - void showConfiguration(std::string option); - void showDebugTags(std::string option); - void showTraceTags(std::string option); - void threadN(std::string option); + void copyright(const std::string& option, const std::string& flag); + void showConfiguration(const std::string& option, const std::string& flag); + void showDebugTags(const std::string& option, const std::string& flag); + void showTraceTags(const std::string& option, const std::string& flag); + void threadN(const std::string& option, const std::string& flag); /* options/base_options_handlers.h */ - void setVerbosity(std::string option, int value); - void increaseVerbosity(std::string option); - void decreaseVerbosity(std::string option); - OutputLanguage stringToOutputLanguage(std::string option, std::string optarg); - InputLanguage stringToInputLanguage(std::string option, std::string optarg); - void enableTraceTag(std::string option, std::string optarg); - void enableDebugTag(std::string option, std::string optarg); + void setVerbosity(const std::string& option, + const std::string& flag, + int value); + void increaseVerbosity(const std::string& option, const std::string& flag); + void decreaseVerbosity(const std::string& option, const std::string& flag); + OutputLanguage stringToOutputLanguage(const std::string& option, + const std::string& flag, + const std::string& optarg); + InputLanguage stringToInputLanguage(const std::string& option, + const std::string& flag, + const std::string& optarg); + void enableTraceTag(const std::string& option, + const std::string& flag, + const std::string& optarg); + void enableDebugTag(const std::string& option, + const std::string& flag, + const std::string& optarg); private: @@ -121,18 +166,6 @@ public: }; /* class OptionHandler */ -template<class T> -void OptionsHandler::checkSatSolverEnabled(std::string option, T m) -{ -#if !defined(CVC5_USE_CRYPTOMINISAT) && !defined(CVC5_USE_CADICAL) \ - && !defined(CVC5_USE_KISSAT) - std::stringstream ss; - ss << "option `" << option - << "' requires cvc5 to be built with CryptoMiniSat or CaDiCaL or Kissat"; - throw OptionException(ss.str()); -#endif -} - } // namespace options } // namespace cvc5 diff --git a/src/options/options_public.cpp b/src/options/options_public.cpp index 35e891f5a..552058312 100644 --- a/src/options/options_public.cpp +++ b/src/options/options_public.cpp @@ -17,118 +17,10 @@ #include "options_public.h" -#include <fstream> -#include <ostream> -#include <string> -#include <vector> - -#include "base/listener.h" -#include "base/modal_exception.h" -#include "options/base_options.h" -#include "options/language.h" -#include "options/main_options.h" -#include "options/option_exception.h" -#include "options/options.h" -#include "options/parser_options.h" -#include "options/printer_modes.h" -#include "options/printer_options.h" -#include "options/resource_manager_options.h" -#include "options/smt_options.h" #include "options/uf_options.h" namespace cvc5::options { -InputLanguage getInputLanguage(const Options& opts) -{ - return opts.base.inputLanguage; -} -InstFormatMode getInstFormatMode(const Options& opts) -{ - return opts.printer.instFormatMode; -} -OutputLanguage getOutputLanguage(const Options& opts) -{ - return opts.base.outputLanguage; -} bool getUfHo(const Options& opts) { return opts.uf.ufHo; } -bool getDumpInstantiations(const Options& opts) -{ - return opts.smt.dumpInstantiations; -} -bool getDumpModels(const Options& opts) { return opts.smt.dumpModels; } -bool getDumpProofs(const Options& opts) { return opts.smt.dumpProofs; } -bool getDumpUnsatCores(const Options& opts) -{ - return opts.smt.dumpUnsatCores || opts.smt.dumpUnsatCoresFull; -} -bool getFilesystemAccess(const Options& opts) -{ - return opts.parser.filesystemAccess; -} -bool getForceNoLimitCpuWhileDump(const Options& opts) -{ - return opts.smt.forceNoLimitCpuWhileDump; -} -bool getIncrementalSolving(const Options& opts) -{ - return opts.smt.incrementalSolving; -} -bool getLanguageHelp(const Options& opts) { return opts.base.languageHelp; } -bool getMemoryMap(const Options& opts) { return opts.parser.memoryMap; } -bool getParseOnly(const Options& opts) { return opts.base.parseOnly; } -bool getProduceModels(const Options& opts) { return opts.smt.produceModels; } -bool getSemanticChecks(const Options& opts) -{ - return opts.parser.semanticChecks; -} -bool getStatistics(const Options& opts) { return opts.base.statistics; } -bool getStatsEveryQuery(const Options& opts) -{ - return opts.base.statisticsEveryQuery; -} -bool getStrictParsing(const Options& opts) -{ - return opts.parser.strictParsing; -} -uint64_t getCumulativeTimeLimit(const Options& opts) -{ - return opts.resman.cumulativeMillisecondLimit; -} -const std::string& getForceLogicString(const Options& opts) -{ - return opts.parser.forceLogicString; -} -int32_t getVerbosity(const Options& opts) { return opts.base.verbosity; } - -std::istream* getIn(const Options& opts) { return opts.base.in; } -std::ostream* getErr(const Options& opts) { return opts.base.err; } -std::ostream* getOut(const Options& opts) { return opts.base.out; } - -void setInputLanguage(InputLanguage val, Options& opts) -{ - opts.base.inputLanguage = val; -} -void setOut(std::ostream* val, Options& opts) { opts.base.out = val; } -void setOutputLanguage(OutputLanguage val, Options& opts) -{ - opts.base.outputLanguage = val; -} - -bool wasSetByUserEarlyExit(const Options& opts) -{ - return opts.driver.earlyExitWasSetByUser; -} -bool wasSetByUserForceLogicString(const Options& opts) -{ - return opts.parser.forceLogicStringWasSetByUser; -} -bool wasSetByUserIncrementalSolving(const Options& opts) -{ - return opts.smt.incrementalSolvingWasSetByUser; -} -bool wasSetByUserInteractive(const Options& opts) -{ - return opts.driver.interactiveWasSetByUser; -} } // namespace cvc5::options diff --git a/src/options/options_public.h b/src/options/options_public.h index 1d2f9edba..60929c96c 100644 --- a/src/options/options_public.h +++ b/src/options/options_public.h @@ -23,47 +23,11 @@ #ifndef CVC5__OPTIONS__OPTIONS_PUBLIC_H #define CVC5__OPTIONS__OPTIONS_PUBLIC_H -#include "options/language.h" #include "options/options.h" -#include "options/printer_modes.h" namespace cvc5::options { -InputLanguage getInputLanguage(const Options& opts) CVC5_EXPORT; -InstFormatMode getInstFormatMode(const Options& opts) CVC5_EXPORT; -OutputLanguage getOutputLanguage(const Options& opts) CVC5_EXPORT; bool getUfHo(const Options& opts) CVC5_EXPORT; -bool getDumpInstantiations(const Options& opts) CVC5_EXPORT; -bool getDumpModels(const Options& opts) CVC5_EXPORT; -bool getDumpProofs(const Options& opts) CVC5_EXPORT; -bool getDumpUnsatCores(const Options& opts) CVC5_EXPORT; -bool getFilesystemAccess(const Options& opts) CVC5_EXPORT; -bool getForceNoLimitCpuWhileDump(const Options& opts) CVC5_EXPORT; -bool getIncrementalSolving(const Options& opts) CVC5_EXPORT; -bool getLanguageHelp(const Options& opts) CVC5_EXPORT; -bool getMemoryMap(const Options& opts) CVC5_EXPORT; -bool getParseOnly(const Options& opts) CVC5_EXPORT; -bool getProduceModels(const Options& opts) CVC5_EXPORT; -bool getSemanticChecks(const Options& opts) CVC5_EXPORT; -bool getStatistics(const Options& opts) CVC5_EXPORT; -bool getStatsEveryQuery(const Options& opts) CVC5_EXPORT; -bool getStrictParsing(const Options& opts) CVC5_EXPORT; -uint64_t getCumulativeTimeLimit(const Options& opts) CVC5_EXPORT; -const std::string& getForceLogicString(const Options& opts) CVC5_EXPORT; -int32_t getVerbosity(const Options& opts) CVC5_EXPORT; - -std::istream* getIn(const Options& opts) CVC5_EXPORT; -std::ostream* getErr(const Options& opts) CVC5_EXPORT; -std::ostream* getOut(const Options& opts) CVC5_EXPORT; - -void setInputLanguage(InputLanguage val, Options& opts) CVC5_EXPORT; -void setOut(std::ostream* val, Options& opts) CVC5_EXPORT; -void setOutputLanguage(OutputLanguage val, Options& opts) CVC5_EXPORT; - -bool wasSetByUserEarlyExit(const Options& opts) CVC5_EXPORT; -bool wasSetByUserForceLogicString(const Options& opts) CVC5_EXPORT; -bool wasSetByUserIncrementalSolving(const Options& opts) CVC5_EXPORT; -bool wasSetByUserInteractive(const Options& opts) CVC5_EXPORT; } // namespace cvc5::options diff --git a/src/options/options_template.cpp b/src/options/options_template.cpp index e909a5f0a..2c22065c2 100644 --- a/src/options/options_template.cpp +++ b/src/options/options_template.cpp @@ -58,7 +58,6 @@ extern int optreset; ${headers_module}$ #include "base/cvc5config.h" -#include "options/base_handlers.h" ${headers_handler}$ @@ -82,7 +81,9 @@ thread_local Options* Options::s_current = NULL; */ template <class T, bool is_numeric, bool is_integer> struct OptionHandler { - static T handle(std::string option, std::string optionarg); + static T handle(const std::string& option, + const std::string& flag, + const std::string& optionarg); };/* struct OptionHandler<> */ /** Variant for integral C++ types */ @@ -99,32 +100,35 @@ struct OptionHandler<T, true, true> { return str.find('-') != std::string::npos; } - static T handle(const std::string& option, const std::string& optionarg) { + static T handle(const std::string& option, + const std::string& flag, + const std::string& optionarg) + { try { T i; bool success = stringToInt(i, optionarg); if(!success){ - throw OptionException(option + ": failed to parse "+ optionarg + - " as an integer of the appropriate type."); + throw OptionException(flag + ": failed to parse " + optionarg + + " as an integer of the appropriate type."); } // Depending in the platform unsigned numbers with '-' signs may parse. // Reject these by looking for any minus if it is not signed. if( (! std::numeric_limits<T>::is_signed) && containsMinus(optionarg) ) { // unsigned type but user gave negative argument - throw OptionException(option + " requires a nonnegative argument"); + throw OptionException(flag + " requires a nonnegative argument"); } else if(i < std::numeric_limits<T>::min()) { // negative overflow for type std::stringstream ss; - ss << option << " requires an argument >= " - << std::numeric_limits<T>::min(); + ss << flag + << " requires an argument >= " << std::numeric_limits<T>::min(); throw OptionException(ss.str()); } else if(i > std::numeric_limits<T>::max()) { // positive overflow for type std::stringstream ss; - ss << option << " requires an argument <= " - << std::numeric_limits<T>::max(); + ss << flag + << " requires an argument <= " << std::numeric_limits<T>::max(); throw OptionException(ss.str()); } @@ -137,7 +141,7 @@ struct OptionHandler<T, true, true> { // } } catch(std::invalid_argument&) { // user gave something other than an integer - throw OptionException(option + " requires an integer argument"); + throw OptionException(flag + " requires an integer argument"); } } };/* struct OptionHandler<T, true, true> */ @@ -145,29 +149,33 @@ struct OptionHandler<T, true, true> { /** Variant for numeric but non-integral C++ types */ template <class T> struct OptionHandler<T, true, false> { - static T handle(std::string option, std::string optionarg) { - std::stringstream in(optionarg); + static T handle(const std::string& option, + const std::string& flag, + const std::string& optionarg) + { + std::stringstream inss(optionarg); long double r; - in >> r; - if(! in.eof()) { + inss >> r; + if (!inss.eof()) + { // we didn't consume the whole string (junk at end) - throw OptionException(option + " requires a numeric argument"); + throw OptionException(flag + " requires a numeric argument"); } if(! std::numeric_limits<T>::is_signed && r < 0.0) { // unsigned type but user gave negative value - throw OptionException(option + " requires a nonnegative argument"); + throw OptionException(flag + " requires a nonnegative argument"); } else if(r < -std::numeric_limits<T>::max()) { // negative overflow for type std::stringstream ss; - ss << option << " requires an argument >= " - << -std::numeric_limits<T>::max(); + ss << flag + << " requires an argument >= " << -std::numeric_limits<T>::max(); throw OptionException(ss.str()); } else if(r > std::numeric_limits<T>::max()) { // positive overflow for type std::stringstream ss; - ss << option << " requires an argument <= " - << std::numeric_limits<T>::max(); + ss << flag + << " requires an argument <= " << std::numeric_limits<T>::max(); throw OptionException(ss.str()); } @@ -178,7 +186,10 @@ struct OptionHandler<T, true, false> { /** Variant for non-numeric C++ types */ template <class T> struct OptionHandler<T, false, false> { - static T handle(std::string option, std::string optionarg) { + static T handle(const std::string& option, + const std::string& flag, + const std::string& optionarg) + { T::unsupported_handleOption_call___please_write_me; // The above line causes a compiler error if this version of the template // is ever instantiated (meaning that a specialization is missing). So @@ -191,36 +202,26 @@ struct OptionHandler<T, false, false> { /** Handle an option of type T in the default way. */ template <class T> -T handleOption(std::string option, std::string optionarg) { - return OptionHandler<T, std::numeric_limits<T>::is_specialized, std::numeric_limits<T>::is_integer>::handle(option, optionarg); +T handleOption(const std::string& option, + const std::string& flag, + const std::string& optionarg) +{ + return OptionHandler<T, + std::numeric_limits<T>::is_specialized, + std::numeric_limits<T>::is_integer>::handle(option, + flag, + optionarg); } /** Handle an option of type std::string in the default way. */ template <> -std::string handleOption<std::string>(std::string option, std::string optionarg) { +std::string handleOption<std::string>(const std::string& option, + const std::string& flag, + const std::string& optionarg) +{ return optionarg; } -/** - * Run handler, and any user-given predicates, for option T. - * If a user specifies a :handler or :predicates, it overrides this. - */ -template <class T> -typename T::type runHandlerAndPredicates(T, std::string option, std::string optionarg, options::OptionsHandler* handler) { - // By default, parse the option argument in a way appropriate for its type. - // E.g., for "unsigned int" options, ensure that the provided argument is - // a nonnegative integer that fits in the unsigned int type. - - return handleOption<typename T::type>(option, optionarg); -} - -template <class T> -void runBoolPredicates(T, std::string option, bool b, options::OptionsHandler* handler) { - // By default, nothing to do for bool. Users add things with - // :predicate in options files to provide custom checking routines - // that can throw exceptions. -} - Options::Options(OptionsListener* ol) : d_handler(new options::OptionsHandler(this)), // clang-format off diff --git a/src/options/parser_options.toml b/src/options/parser_options.toml index 6fc683368..f19b903a6 100644 --- a/src/options/parser_options.toml +++ b/src/options/parser_options.toml @@ -1,5 +1,6 @@ id = "PARSER" name = "Parser" +public = true [[option]] name = "strictParsing" diff --git a/src/options/prop_options.toml b/src/options/prop_options.toml index 26d7a451b..eda5ea963 100644 --- a/src/options/prop_options.toml +++ b/src/options/prop_options.toml @@ -8,7 +8,7 @@ name = "SAT Layer" long = "random-freq=P" type = "double" default = "0.0" - predicates = ["doubleGreaterOrEqual0", "doubleLessOrEqual1"] + predicates = ["betweenZeroAndOne"] help = "sets the frequency of random decisions in the sat solver (P=0.0 by default)" [[option]] @@ -24,7 +24,7 @@ name = "SAT Layer" category = "regular" type = "double" default = "0.95" - predicates = ["doubleGreaterOrEqual0", "doubleLessOrEqual1"] + predicates = ["betweenZeroAndOne"] help = "variable activity decay factor for Minisat" [[option]] @@ -32,7 +32,7 @@ name = "SAT Layer" category = "regular" type = "double" default = "0.999" - predicates = ["doubleGreaterOrEqual0", "doubleLessOrEqual1"] + predicates = ["betweenZeroAndOne"] help = "clause activity decay factor for Minisat" [[option]] @@ -49,7 +49,7 @@ name = "SAT Layer" long = "restart-int-inc=F" type = "double" default = "3.0" - predicates = ["doubleGreaterOrEqual0"] + predicates = ["geqZero"] help = "sets the restart interval increase factor for the sat solver (F=3.0 by default)" [[option]] diff --git a/src/options/resource_manager_options.toml b/src/options/resource_manager_options.toml deleted file mode 100644 index 6d5c4d4cf..000000000 --- a/src/options/resource_manager_options.toml +++ /dev/null @@ -1,51 +0,0 @@ -id = "RESMAN" -name = "Resource Manager" - -[[option]] - name = "cumulativeMillisecondLimit" - category = "common" - long = "tlimit=MS" - type = "uint64_t" - help = "set time limit in milliseconds of wall clock time" - -[[option]] - name = "perCallMillisecondLimit" - category = "common" - long = "tlimit-per=MS" - type = "uint64_t" - help = "set time limit per query in milliseconds" - -[[option]] - name = "cumulativeResourceLimit" - category = "common" - long = "rlimit=N" - type = "uint64_t" - help = "set resource limit" - -[[option]] - name = "perCallResourceLimit" - alias = ["reproducible-resource-limit"] - category = "common" - long = "rlimit-per=N" - type = "uint64_t" - help = "set resource limit per query" - -# --rweight is used to override the default of one particular resource weight. -# It can be given multiple times to override multiple weights. When options are -# parsed, the resource manager might now be created yet, and it is not clear -# how an option handler would access it in a reasonable way. The option handler -# thus merely puts the data in another option that holds a vector of strings. -# This other option "resourceWeightHolder" has the sole purpose of storing -# this data in a way so that the resource manager can access it in its -# constructor. -[[option]] - category = "expert" - long = "rweight=VAL=N" - type = "std::string" - handler = "setResourceWeight" - help = "set a single resource weight" - -[[option]] - name = "resourceWeightHolder" - category = "undocumented" - type = "std::vector<std::string>" diff --git a/src/options/smt_options.toml b/src/options/smt_options.toml index d1354f777..4d08aa672 100644 --- a/src/options/smt_options.toml +++ b/src/options/smt_options.toml @@ -79,14 +79,6 @@ name = "SMT Layer" help = "after SAT/INVALID/UNKNOWN, check that the generated model satisfies user and internal assertions" [[option]] - name = "dumpModels" - category = "regular" - long = "dump-models" - type = "bool" - default = "false" - help = "output models after every SAT/INVALID/UNKNOWN response" - -[[option]] name = "modelCoresMode" category = "regular" long = "model-cores=MODE" @@ -131,14 +123,6 @@ name = "SMT Layer" help = "produce proofs, support check-proofs and get-proof" [[option]] - name = "dumpProofs" - category = "regular" - long = "dump-proofs" - type = "bool" - default = "false" - help = "output proofs after every UNSAT/VALID response" - -[[option]] name = "checkProofs" category = "regular" long = "check-proofs" @@ -146,14 +130,6 @@ name = "SMT Layer" help = "after UNSAT/VALID, check the generated proof (with proof)" [[option]] - name = "dumpInstantiations" - category = "regular" - long = "dump-instantiations" - type = "bool" - default = "false" - help = "output instantiations of quantified formulas after every UNSAT/VALID response" - -[[option]] name = "sygusOut" category = "regular" long = "sygus-out=MODE" @@ -218,22 +194,6 @@ name = "SMT Layer" help = "after UNSAT/VALID, produce and check an unsat core (expensive)" [[option]] - name = "dumpUnsatCores" - category = "regular" - long = "dump-unsat-cores" - type = "bool" - default = "false" - help = "output unsat cores after every UNSAT/VALID response" - -[[option]] - name = "dumpUnsatCoresFull" - category = "regular" - long = "dump-unsat-cores-full" - type = "bool" - default = "false" - help = "dump the full unsat core, including unlabeled assertions" - -[[option]] name = "unsatAssumptions" category = "regular" long = "produce-unsat-assumptions" @@ -360,15 +320,6 @@ name = "SMT Layer" help = "calculate sort inference of input problem, convert the input based on monotonic sorts" [[option]] - name = "incrementalSolving" - category = "common" - short = "i" - long = "incremental" - type = "bool" - default = "true" - help = "enable incremental solving" - -[[option]] name = "abstractValues" category = "regular" long = "abstract-values" @@ -422,14 +373,6 @@ name = "SMT Layer" help = "set the diagnostic output channel of the solver" [[option]] - name = "forceNoLimitCpuWhileDump" - category = "regular" - long = "force-no-limit-cpu-while-dump" - type = "bool" - default = "false" - help = "Force no CPU limit when dumping models and proofs" - -[[option]] name = "foreignTheoryRewrite" category = "regular" long = "foreign-theory-rewrite" diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index d96e94d43..eab982013 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -26,8 +26,8 @@ #include "base/check.h" #include "base/output.h" #include "expr/kind.h" +#include "options/base_options.h" #include "options/options.h" -#include "options/options_public.h" #include "parser/input.h" #include "parser/parser_exception.h" #include "smt/command.h" @@ -900,7 +900,7 @@ std::wstring Parser::processAdHocStringEsc(const std::string& s) api::Term Parser::mkStringConstant(const std::string& s) { if (language::isInputLang_smt2_6( - options::getInputLanguage(d_solver->getOptions()))) + d_solver->getOptions().base.inputLanguage)) { return d_solver->mkString(s, true); } diff --git a/src/parser/parser_builder.cpp b/src/parser/parser_builder.cpp index 1f25e00dd..816803ccc 100644 --- a/src/parser/parser_builder.cpp +++ b/src/parser/parser_builder.cpp @@ -21,8 +21,9 @@ #include "api/cpp/cvc5.h" #include "base/check.h" #include "cvc/cvc.h" +#include "options/base_options.h" #include "options/options.h" -#include "options/options_public.h" +#include "options/parser_options.h" #include "parser/antlr_input.h" #include "parser/input.h" #include "parser/parser.h" @@ -120,14 +121,14 @@ ParserBuilder& ParserBuilder::withParseOnly(bool flag) { ParserBuilder& ParserBuilder::withOptions(const Options& opts) { ParserBuilder& retval = *this; - retval = retval.withInputLanguage(options::getInputLanguage(opts)) - .withChecks(options::getSemanticChecks(opts)) - .withStrictMode(options::getStrictParsing(opts)) - .withParseOnly(options::getParseOnly(opts)) - .withIncludeFile(options::getFilesystemAccess(opts)); - if (options::wasSetByUserForceLogicString(opts)) + retval = retval.withInputLanguage(opts.base.inputLanguage) + .withChecks(opts.parser.semanticChecks) + .withStrictMode(opts.parser.strictParsing) + .withParseOnly(opts.base.parseOnly) + .withIncludeFile(opts.parser.filesystemAccess); + if (opts.parser.forceLogicStringWasSetByUser) { - LogicInfo tmp(options::getForceLogicString(opts)); + LogicInfo tmp(opts.parser.forceLogicString); retval = retval.withForcedLogic(tmp.getLogicString()); } return retval; diff --git a/src/parser/smt2/smt2.cpp b/src/parser/smt2/smt2.cpp index 56aebdcf7..282b72974 100644 --- a/src/parser/smt2/smt2.cpp +++ b/src/parser/smt2/smt2.cpp @@ -17,6 +17,7 @@ #include <algorithm> #include "base/check.h" +#include "options/base_options.h" #include "options/options.h" #include "options/options_public.h" #include "parser/antlr_input.h" @@ -846,7 +847,7 @@ api::Term Smt2::mkAbstractValue(const std::string& name) InputLanguage Smt2::getLanguage() const { - return options::getInputLanguage(d_solver->getOptions()); + return d_solver->getOptions().base.inputLanguage; } void Smt2::parseOpApplyTypeAscription(ParseOp& p, api::Sort type) diff --git a/src/preprocessing/passes/ackermann.cpp b/src/preprocessing/passes/ackermann.cpp index 89029b5eb..eb6410291 100644 --- a/src/preprocessing/passes/ackermann.cpp +++ b/src/preprocessing/passes/ackermann.cpp @@ -29,8 +29,8 @@ #include "base/check.h" #include "expr/node_algorithm.h" #include "expr/skolem_manager.h" +#include "options/base_options.h" #include "options/options.h" -#include "options/smt_options.h" #include "preprocessing/assertion_pipeline.h" #include "preprocessing/preprocessing_pass_context.h" diff --git a/src/preprocessing/passes/int_to_bv.cpp b/src/preprocessing/passes/int_to_bv.cpp index 15a16888d..df9d44e39 100644 --- a/src/preprocessing/passes/int_to_bv.cpp +++ b/src/preprocessing/passes/int_to_bv.cpp @@ -26,6 +26,7 @@ #include "expr/node.h" #include "expr/node_traversal.h" #include "expr/skolem_manager.h" +#include "options/base_options.h" #include "options/smt_options.h" #include "preprocessing/assertion_pipeline.h" #include "theory/rewriter.h" diff --git a/src/preprocessing/passes/ite_simp.cpp b/src/preprocessing/passes/ite_simp.cpp index 5bfb2a79f..d1dd389ae 100644 --- a/src/preprocessing/passes/ite_simp.cpp +++ b/src/preprocessing/passes/ite_simp.cpp @@ -17,6 +17,7 @@ #include <vector> +#include "options/base_options.h" #include "options/smt_options.h" #include "preprocessing/assertion_pipeline.h" #include "preprocessing/preprocessing_pass_context.h" diff --git a/src/preprocessing/passes/miplib_trick.cpp b/src/preprocessing/passes/miplib_trick.cpp index 79fcc4028..a5720e758 100644 --- a/src/preprocessing/passes/miplib_trick.cpp +++ b/src/preprocessing/passes/miplib_trick.cpp @@ -22,7 +22,7 @@ #include "expr/node_self_iterator.h" #include "expr/skolem_manager.h" #include "options/arith_options.h" -#include "options/smt_options.h" +#include "options/base_options.h" #include "preprocessing/assertion_pipeline.h" #include "preprocessing/preprocessing_pass_context.h" #include "smt/smt_statistics_registry.h" diff --git a/src/proof/proof_rule.h b/src/proof/proof_rule.h index a42b30773..c1cf0338a 100644 --- a/src/proof/proof_rule.h +++ b/src/proof/proof_rule.h @@ -688,9 +688,9 @@ enum class PfRule : uint32_t //================================================= Array rules // ======== Read over write // Children: (P:(not (= i1 i2))) - // Arguments: ((select (store a i2 e) i1)) + // Arguments: ((select (store a i1 e) i2)) // ---------------------------------------- - // Conclusion: (= (select (store a i2 e) i1) (select a i1)) + // Conclusion: (= (select (store a i1 e) i2) (select a i2)) ARRAYS_READ_OVER_WRITE, // ======== Read over write, contrapositive // Children: (P:(not (= (select (store a i2 e) i1) (select a i1))) diff --git a/src/prop/cadical.cpp b/src/prop/cadical.cpp index ec8919b0b..ddf20f5a1 100644 --- a/src/prop/cadical.cpp +++ b/src/prop/cadical.cpp @@ -17,8 +17,6 @@ #include "prop/cadical.h" -#ifdef CVC5_USE_CADICAL - #include "base/check.h" #include "util/statistics_registry.h" @@ -191,5 +189,3 @@ CadicalSolver::Statistics::Statistics(StatisticsRegistry& registry, } // namespace prop } // namespace cvc5 - -#endif // CVC5_USE_CADICAL diff --git a/src/prop/cadical.h b/src/prop/cadical.h index b5e26df9f..46c7c7e42 100644 --- a/src/prop/cadical.h +++ b/src/prop/cadical.h @@ -20,8 +20,6 @@ #ifndef CVC5__PROP__CADICAL_H #define CVC5__PROP__CADICAL_H -#ifdef CVC5_USE_CADICAL - #include "prop/sat_solver.h" #include <cadical.hpp> @@ -103,5 +101,4 @@ class CadicalSolver : public SatSolver } // namespace prop } // namespace cvc5 -#endif // CVC5_USE_CADICAL #endif // CVC5__PROP__CADICAL_H diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp index f8a34ec42..4897f8e6a 100644 --- a/src/prop/cnf_stream.cpp +++ b/src/prop/cnf_stream.cpp @@ -21,14 +21,15 @@ #include "base/output.h" #include "expr/node.h" #include "options/bv_options.h" +#include "printer/printer.h" #include "proof/clause_id.h" #include "prop/minisat/minisat.h" #include "prop/prop_engine.h" #include "prop/theory_proxy.h" #include "smt/dump.h" #include "smt/smt_engine.h" -#include "printer/printer.h" #include "smt/smt_engine_scope.h" +#include "smt/smt_statistics_registry.h" #include "theory/theory.h" #include "theory/theory_engine.h" @@ -52,7 +53,8 @@ CnfStream::CnfStream(SatSolver* satSolver, d_registrar(registrar), d_name(name), d_removable(false), - d_resourceManager(rm) + d_resourceManager(rm), + d_stats(name) { } @@ -139,6 +141,7 @@ void CnfStream::ensureLiteral(TNode n) n.toString().c_str(), n.getType().toString().c_str()); Trace("cnf") << "ensureLiteral(" << n << ")\n"; + TimerStat::CodeTimer codeTimer(d_stats.d_cnfConversionTime, true); if (hasLiteral(n)) { ensureMappingForLiteral(n); @@ -292,7 +295,7 @@ SatLiteral CnfStream::getLiteral(TNode node) { return literal; } -SatLiteral CnfStream::handleXor(TNode xorNode) +void CnfStream::handleXor(TNode xorNode) { Assert(!hasLiteral(xorNode)) << "Atom already mapped!"; Assert(xorNode.getKind() == kind::XOR) << "Expecting an XOR expression!"; @@ -300,8 +303,8 @@ SatLiteral CnfStream::handleXor(TNode xorNode) Assert(!d_removable) << "Removable clauses can not contain Boolean structure"; Trace("cnf") << "CnfStream::handleXor(" << xorNode << ")\n"; - SatLiteral a = toCNF(xorNode[0]); - SatLiteral b = toCNF(xorNode[1]); + SatLiteral a = getLiteral(xorNode[0]); + SatLiteral b = getLiteral(xorNode[1]); SatLiteral xorLit = newLiteral(xorNode); @@ -309,11 +312,9 @@ SatLiteral CnfStream::handleXor(TNode xorNode) assertClause(xorNode.negate(), ~a, ~b, ~xorLit); assertClause(xorNode, a, ~b, xorLit); assertClause(xorNode, ~a, b, xorLit); - - return xorLit; } -SatLiteral CnfStream::handleOr(TNode orNode) +void CnfStream::handleOr(TNode orNode) { Assert(!hasLiteral(orNode)) << "Atom already mapped!"; Assert(orNode.getKind() == kind::OR) << "Expecting an OR expression!"; @@ -322,37 +323,31 @@ SatLiteral CnfStream::handleOr(TNode orNode) Trace("cnf") << "CnfStream::handleOr(" << orNode << ")\n"; // Number of children - unsigned n_children = orNode.getNumChildren(); - - // Transform all the children first - TNode::const_iterator node_it = orNode.begin(); - TNode::const_iterator node_it_end = orNode.end(); - SatClause clause(n_children + 1); - for(int i = 0; node_it != node_it_end; ++node_it, ++i) { - clause[i] = toCNF(*node_it); - } + size_t numChildren = orNode.getNumChildren(); // Get the literal for this node SatLiteral orLit = newLiteral(orNode); - // lit <- (a_1 | a_2 | a_3 | ... | a_n) - // lit | ~(a_1 | a_2 | a_3 | ... | a_n) - // (lit | ~a_1) & (lit | ~a_2) & (lit & ~a_3) & ... & (lit & ~a_n) - for(unsigned i = 0; i < n_children; ++i) { + // Transform all the children first + SatClause clause(numChildren + 1); + for (size_t i = 0; i < numChildren; ++i) + { + clause[i] = getLiteral(orNode[i]); + + // lit <- (a_1 | a_2 | a_3 | ... | a_n) + // lit | ~(a_1 | a_2 | a_3 | ... | a_n) + // (lit | ~a_1) & (lit | ~a_2) & (lit & ~a_3) & ... & (lit & ~a_n) assertClause(orNode, orLit, ~clause[i]); } // lit -> (a_1 | a_2 | a_3 | ... | a_n) // ~lit | a_1 | a_2 | a_3 | ... | a_n - clause[n_children] = ~orLit; + clause[numChildren] = ~orLit; // This needs to go last, as the clause might get modified by the SAT solver assertClause(orNode.negate(), clause); - - // Return the literal - return orLit; } -SatLiteral CnfStream::handleAnd(TNode andNode) +void CnfStream::handleAnd(TNode andNode) { Assert(!hasLiteral(andNode)) << "Atom already mapped!"; Assert(andNode.getKind() == kind::AND) << "Expecting an AND expression!"; @@ -361,37 +356,32 @@ SatLiteral CnfStream::handleAnd(TNode andNode) Trace("cnf") << "handleAnd(" << andNode << ")\n"; // Number of children - unsigned n_children = andNode.getNumChildren(); - - // Transform all the children first (remembering the negation) - TNode::const_iterator node_it = andNode.begin(); - TNode::const_iterator node_it_end = andNode.end(); - SatClause clause(n_children + 1); - for(int i = 0; node_it != node_it_end; ++node_it, ++i) { - clause[i] = ~toCNF(*node_it); - } + size_t numChildren = andNode.getNumChildren(); // Get the literal for this node SatLiteral andLit = newLiteral(andNode); - // lit -> (a_1 & a_2 & a_3 & ... & a_n) - // ~lit | (a_1 & a_2 & a_3 & ... & a_n) - // (~lit | a_1) & (~lit | a_2) & ... & (~lit | a_n) - for(unsigned i = 0; i < n_children; ++i) { + // Transform all the children first (remembering the negation) + SatClause clause(numChildren + 1); + for (size_t i = 0; i < numChildren; ++i) + { + clause[i] = ~getLiteral(andNode[i]); + + // lit -> (a_1 & a_2 & a_3 & ... & a_n) + // ~lit | (a_1 & a_2 & a_3 & ... & a_n) + // (~lit | a_1) & (~lit | a_2) & ... & (~lit | a_n) assertClause(andNode.negate(), ~andLit, ~clause[i]); } // lit <- (a_1 & a_2 & a_3 & ... a_n) // lit | ~(a_1 & a_2 & a_3 & ... & a_n) // lit | ~a_1 | ~a_2 | ~a_3 | ... | ~a_n - clause[n_children] = andLit; + clause[numChildren] = andLit; // This needs to go last, as the clause might get modified by the SAT solver assertClause(andNode, clause); - - return andLit; } -SatLiteral CnfStream::handleImplies(TNode impliesNode) +void CnfStream::handleImplies(TNode impliesNode) { Assert(!hasLiteral(impliesNode)) << "Atom already mapped!"; Assert(impliesNode.getKind() == kind::IMPLIES) @@ -401,8 +391,8 @@ SatLiteral CnfStream::handleImplies(TNode impliesNode) Trace("cnf") << "handleImplies(" << impliesNode << ")\n"; // Convert the children to cnf - SatLiteral a = toCNF(impliesNode[0]); - SatLiteral b = toCNF(impliesNode[1]); + SatLiteral a = getLiteral(impliesNode[0]); + SatLiteral b = getLiteral(impliesNode[1]); SatLiteral impliesLit = newLiteral(impliesNode); @@ -415,11 +405,9 @@ SatLiteral CnfStream::handleImplies(TNode impliesNode) // (a | l) & (~b | l) assertClause(impliesNode, a, impliesLit); assertClause(impliesNode, ~b, impliesLit); - - return impliesLit; } -SatLiteral CnfStream::handleIff(TNode iffNode) +void CnfStream::handleIff(TNode iffNode) { Assert(!hasLiteral(iffNode)) << "Atom already mapped!"; Assert(iffNode.getKind() == kind::EQUAL) << "Expecting an EQUAL expression!"; @@ -428,8 +416,8 @@ SatLiteral CnfStream::handleIff(TNode iffNode) Trace("cnf") << "handleIff(" << iffNode << ")\n"; // Convert the children to CNF - SatLiteral a = toCNF(iffNode[0]); - SatLiteral b = toCNF(iffNode[1]); + SatLiteral a = getLiteral(iffNode[0]); + SatLiteral b = getLiteral(iffNode[1]); // Get the now literal SatLiteral iffLit = newLiteral(iffNode); @@ -447,11 +435,9 @@ SatLiteral CnfStream::handleIff(TNode iffNode) // (~a | ~b | lit) & (a | b | lit) assertClause(iffNode, ~a, ~b, iffLit); assertClause(iffNode, a, b, iffLit); - - return iffLit; } -SatLiteral CnfStream::handleIte(TNode iteNode) +void CnfStream::handleIte(TNode iteNode) { Assert(!hasLiteral(iteNode)) << "Atom already mapped!"; Assert(iteNode.getKind() == kind::ITE); @@ -460,9 +446,9 @@ SatLiteral CnfStream::handleIte(TNode iteNode) Trace("cnf") << "handleIte(" << iteNode[0] << " " << iteNode[1] << " " << iteNode[2] << ")\n"; - SatLiteral condLit = toCNF(iteNode[0]); - SatLiteral thenLit = toCNF(iteNode[1]); - SatLiteral elseLit = toCNF(iteNode[2]); + SatLiteral condLit = getLiteral(iteNode[0]); + SatLiteral thenLit = getLiteral(iteNode[1]); + SatLiteral elseLit = getLiteral(iteNode[2]); SatLiteral iteLit = newLiteral(iteNode); @@ -485,47 +471,79 @@ SatLiteral CnfStream::handleIte(TNode iteNode) assertClause(iteNode, iteLit, ~thenLit, ~elseLit); assertClause(iteNode, iteLit, ~condLit, ~thenLit); assertClause(iteNode, iteLit, condLit, ~elseLit); - - return iteLit; } SatLiteral CnfStream::toCNF(TNode node, bool negated) { Trace("cnf") << "toCNF(" << node << ", negated = " << (negated ? "true" : "false") << ")\n"; + + TNode cur; SatLiteral nodeLit; - Node negatedNode = node.notNode(); - - // If the non-negated node has already been translated, get the translation - if(hasLiteral(node)) { - Trace("cnf") << "toCNF(): already translated\n"; - nodeLit = getLiteral(node); - // Return the (maybe negated) literal - return !negated ? nodeLit : ~nodeLit; - } - // Handle each Boolean operator case - switch (node.getKind()) + std::vector<TNode> visit; + std::unordered_map<TNode, bool> cache; + + visit.push_back(node); + while (!visit.empty()) { - case kind::NOT: nodeLit = ~toCNF(node[0]); break; - case kind::XOR: nodeLit = handleXor(node); break; - case kind::ITE: nodeLit = handleIte(node); break; - case kind::IMPLIES: nodeLit = handleImplies(node); break; - case kind::OR: nodeLit = handleOr(node); break; - case kind::AND: nodeLit = handleAnd(node); break; - case kind::EQUAL: - nodeLit = - node[0].getType().isBoolean() ? handleIff(node) : convertAtom(node); - break; - default: + cur = visit.back(); + Assert(cur.getType().isBoolean()); + + if (hasLiteral(cur)) { - nodeLit = convertAtom(node); + visit.pop_back(); + continue; } - break; + + const auto& it = cache.find(cur); + if (it == cache.end()) + { + cache.emplace(cur, false); + Kind k = cur.getKind(); + // Only traverse Boolean nodes + if (k == kind::NOT || k == kind::XOR || k == kind::ITE + || k == kind::IMPLIES || k == kind::OR || k == kind::AND + || (k == kind::EQUAL && cur[0].getType().isBoolean())) + { + // Preserve the order of the recursive version + for (size_t i = 0, size = cur.getNumChildren(); i < size; ++i) + { + visit.push_back(cur[size - 1 - i]); + } + } + continue; + } + else if (!it->second) + { + it->second = true; + Kind k = cur.getKind(); + switch (k) + { + case kind::NOT: Assert(hasLiteral(cur[0])); break; + case kind::XOR: handleXor(cur); break; + case kind::ITE: handleIte(cur); break; + case kind::IMPLIES: handleImplies(cur); break; + case kind::OR: handleOr(cur); break; + case kind::AND: handleAnd(cur); break; + default: + if (k == kind::EQUAL && cur[0].getType().isBoolean()) + { + handleIff(cur); + } + else + { + convertAtom(cur); + } + break; + } + } + visit.pop_back(); } - // Return the (maybe negated) literal + + nodeLit = getLiteral(node); Trace("cnf") << "toCNF(): resulting literal: " << (!negated ? nodeLit : ~nodeLit) << "\n"; - return !negated ? nodeLit : ~nodeLit; + return negated ? ~nodeLit : nodeLit; } void CnfStream::convertAndAssertAnd(TNode node, bool negated) @@ -707,6 +725,7 @@ void CnfStream::convertAndAssert(TNode node, << ", negated = " << (negated ? "true" : "false") << ", removable = " << (removable ? "true" : "false") << ")\n"; d_removable = removable; + TimerStat::CodeTimer codeTimer(d_stats.d_cnfConversionTime, true); convertAndAssert(node, negated); } @@ -745,5 +764,11 @@ void CnfStream::convertAndAssert(TNode node, bool negated) } } +CnfStream::Statistics::Statistics(const std::string& name) + : d_cnfConversionTime(smtStatisticsRegistry().registerTimer( + name + "::CnfStream::cnfConversionTime")) +{ +} + } // namespace prop } // namespace cvc5 diff --git a/src/prop/cnf_stream.h b/src/prop/cnf_stream.h index 264e26777..aeed97380 100644 --- a/src/prop/cnf_stream.h +++ b/src/prop/cnf_stream.h @@ -191,16 +191,16 @@ class CnfStream { */ SatLiteral toCNF(TNode node, bool negated = false); - /** Specific clausifiers, based on the formula kinds, that clausify a formula, - * by calling toCNF into each of the formula's children under the respective - * kind, and introduce a literal definitionally equal to it. */ - SatLiteral handleNot(TNode node); - SatLiteral handleXor(TNode node); - SatLiteral handleImplies(TNode node); - SatLiteral handleIff(TNode node); - SatLiteral handleIte(TNode node); - SatLiteral handleAnd(TNode node); - SatLiteral handleOr(TNode node); + /** + * Specific clausifiers that clausify a formula based on the given formula + * kind and introduce a literal definitionally equal to it. + */ + void handleXor(TNode node); + void handleImplies(TNode node); + void handleIff(TNode node); + void handleIte(TNode node); + void handleAnd(TNode node); + void handleOr(TNode node); /** Stores the literal of the given node in d_literalToNodeMap. * @@ -309,6 +309,14 @@ class CnfStream { /** Pointer to resource manager for associated SmtEngine */ ResourceManager* d_resourceManager; + + private: + struct Statistics + { + Statistics(const std::string& name); + TimerStat d_cnfConversionTime; + } d_stats; + }; /* class CnfStream */ } // namespace prop diff --git a/src/prop/minisat/core/Solver.cc b/src/prop/minisat/core/Solver.cc index fd86d3a42..6f99a47f0 100644 --- a/src/prop/minisat/core/Solver.cc +++ b/src/prop/minisat/core/Solver.cc @@ -27,6 +27,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "base/check.h" #include "base/output.h" +#include "options/base_options.h" #include "options/main_options.h" #include "options/prop_options.h" #include "options/smt_options.h" diff --git a/src/prop/proof_cnf_stream.h b/src/prop/proof_cnf_stream.h index 9972581c0..af131c2c3 100644 --- a/src/prop/proof_cnf_stream.h +++ b/src/prop/proof_cnf_stream.h @@ -133,7 +133,6 @@ class ProofCnfStream : public ProofGenerator * Specific clausifiers, based on the formula kinds, that clausify a formula, * by calling toCNF into each of the formula's children under the respective * kind, and introduce a literal definitionally equal to it. */ - SatLiteral handleNot(TNode node); SatLiteral handleXor(TNode node); SatLiteral handleImplies(TNode node); SatLiteral handleIff(TNode node); diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp index fe3a5ecff..62b2f655c 100644 --- a/src/prop/prop_engine.cpp +++ b/src/prop/prop_engine.cpp @@ -107,7 +107,8 @@ PropEngine::PropEngine(TheoryEngine* te, userContext, &d_outMgr, rm, - FormulaLitPolicy::TRACK); + FormulaLitPolicy::TRACK, + "prop"); // connect theory proxy d_theoryProxy->finishInit(d_cnfStream); diff --git a/src/prop/sat_solver_factory.cpp b/src/prop/sat_solver_factory.cpp index 446f72451..0855cbda5 100644 --- a/src/prop/sat_solver_factory.cpp +++ b/src/prop/sat_solver_factory.cpp @@ -53,13 +53,9 @@ SatSolver* SatSolverFactory::createCryptoMinisat(StatisticsRegistry& registry, SatSolver* SatSolverFactory::createCadical(StatisticsRegistry& registry, const std::string& name) { -#ifdef CVC5_USE_CADICAL CadicalSolver* res = new CadicalSolver(registry, name); res->init(); return res; -#else - Unreachable() << "cvc5 was not compiled with CaDiCaL support."; -#endif } SatSolver* SatSolverFactory::createKissat(StatisticsRegistry& registry, diff --git a/src/smt/command.cpp b/src/smt/command.cpp index d672b79a6..5f0da7a0c 100644 --- a/src/smt/command.cpp +++ b/src/smt/command.cpp @@ -31,6 +31,7 @@ #include "expr/symbol_manager.h" #include "expr/type_node.h" #include "options/options.h" +#include "options/main_options.h" #include "options/printer_options.h" #include "options/smt_options.h" #include "printer/printer.h" diff --git a/src/smt/optimization_solver.cpp b/src/smt/optimization_solver.cpp index e85ea82ef..a46452004 100644 --- a/src/smt/optimization_solver.cpp +++ b/src/smt/optimization_solver.cpp @@ -32,12 +32,11 @@ OptimizationSolver::OptimizationSolver(SmtEngine* parent) : d_parent(parent), d_optChecker(), d_objectives(parent->getUserContext()), - d_results(), - d_objectiveCombination(LEXICOGRAPHIC) + d_results() { } -OptimizationResult::ResultType OptimizationSolver::checkOpt() +Result OptimizationSolver::checkOpt(ObjectiveCombination combination) { // if the results of the previous call have different size than the // objectives, then we should clear the pareto optimization context @@ -48,7 +47,7 @@ OptimizationResult::ResultType OptimizationSolver::checkOpt() { d_results.emplace_back(); } - switch (d_objectiveCombination) + switch (combination) { case BOX: return optimizeBox(); break; case LEXICOGRAPHIC: return optimizeLexicographicIterative(); break; @@ -76,16 +75,9 @@ void OptimizationSolver::addObjective(TNode target, std::vector<OptimizationResult> OptimizationSolver::getValues() { - Assert(d_objectives.size() == d_results.size()); return d_results; } -void OptimizationSolver::setObjectiveCombination( - ObjectiveCombination combination) -{ - d_objectiveCombination = combination; -} - std::unique_ptr<SmtEngine> OptimizationSolver::createOptCheckerWithTimeout( SmtEngine* parentSMTSolver, bool needsTimeout, unsigned long timeout) { @@ -106,13 +98,12 @@ std::unique_ptr<SmtEngine> OptimizationSolver::createOptCheckerWithTimeout( return optChecker; } -OptimizationResult::ResultType OptimizationSolver::optimizeBox() +Result OptimizationSolver::optimizeBox() { // resets the optChecker d_optChecker = createOptCheckerWithTimeout(d_parent); OptimizationResult partialResult; - OptimizationResult::ResultType aggregatedResultType = - OptimizationResult::OPTIMAL; + Result aggregatedResult(Result::Sat::SAT); std::unique_ptr<OMTOptimizer> optimizer; for (size_t i = 0, numObj = d_objectives.size(); i < numObj; ++i) { @@ -134,18 +125,19 @@ OptimizationResult::ResultType OptimizationSolver::optimizeBox() } // match the optimization result type, and aggregate the results of // subproblems - switch (partialResult.getType()) + switch (partialResult.getResult().isSat()) { - case OptimizationResult::OPTIMAL: break; - case OptimizationResult::UNBOUNDED: break; - case OptimizationResult::UNSAT: - if (aggregatedResultType == OptimizationResult::OPTIMAL) + case Result::SAT: break; + case Result::UNSAT: + // the assertions are unsatisfiable + for (size_t j = 0; j < numObj; ++j) { - aggregatedResultType = OptimizationResult::UNSAT; + d_results[j] = partialResult; } - break; - case OptimizationResult::UNKNOWN: - aggregatedResultType = OptimizationResult::UNKNOWN; + d_optChecker.reset(); + return partialResult.getResult(); + case Result::SAT_UNKNOWN: + aggregatedResult = partialResult.getResult(); break; default: Unreachable(); } @@ -154,15 +146,20 @@ OptimizationResult::ResultType OptimizationSolver::optimizeBox() } // kill optChecker after optimization ends d_optChecker.reset(); - return aggregatedResultType; + return aggregatedResult; } -OptimizationResult::ResultType -OptimizationSolver::optimizeLexicographicIterative() +Result OptimizationSolver::optimizeLexicographicIterative() { // resets the optChecker d_optChecker = createOptCheckerWithTimeout(d_parent); - OptimizationResult partialResult; + // partialResult defaults to SAT if no objective is present + // NOTE: the parenthesis around Result(Result::SAT) is required, + // otherwise the compiler will report "parameter declarator cannot be + // qualified". For more details: + // https://stackoverflow.com/questions/44045257/c-compiler-error-c2751-what-exactly-causes-it + // https://en.wikipedia.org/wiki/Most_vexing_parse + OptimizationResult partialResult((Result(Result::SAT)), TNode()); std::unique_ptr<OMTOptimizer> optimizer; for (size_t i = 0, numObj = d_objectives.size(); i < numObj; ++i) { @@ -186,26 +183,33 @@ OptimizationSolver::optimizeLexicographicIterative() d_results[i] = partialResult; // checks the optimization result of the current objective - switch (partialResult.getType()) + switch (partialResult.getResult().isSat()) { - case OptimizationResult::OPTIMAL: + case Result::SAT: // assert target[i] == value[i] and proceed d_optChecker->assertFormula(d_optChecker->getNodeManager()->mkNode( kind::EQUAL, d_objectives[i].getTarget(), d_results[i].getValue())); break; - case OptimizationResult::UNBOUNDED: return OptimizationResult::UNBOUNDED; - case OptimizationResult::UNSAT: return OptimizationResult::UNSAT; - case OptimizationResult::UNKNOWN: return OptimizationResult::UNKNOWN; + case Result::UNSAT: + d_optChecker.reset(); + return partialResult.getResult(); + case Result::SAT_UNKNOWN: + d_optChecker.reset(); + return partialResult.getResult(); default: Unreachable(); } + + // if the result for the current objective is unbounded + // then just stop + if (partialResult.isUnbounded()) break; } // kill optChecker in case pareto misuses it d_optChecker.reset(); - // now all objectives are OPTIMAL, just return OPTIMAL as overall result - return OptimizationResult::OPTIMAL; + // now all objectives are optimal, just return SAT as the overall result + return partialResult.getResult(); } -OptimizationResult::ResultType OptimizationSolver::optimizeParetoNaiveGIA() +Result OptimizationSolver::optimizeParetoNaiveGIA() { // initial call to Pareto optimizer, create the checker if (!d_optChecker) d_optChecker = createOptCheckerWithTimeout(d_parent); @@ -216,8 +220,8 @@ OptimizationResult::ResultType OptimizationSolver::optimizeParetoNaiveGIA() switch (satResult.isSat()) { - case Result::Sat::UNSAT: return OptimizationResult::UNSAT; - case Result::Sat::SAT_UNKNOWN: return OptimizationResult::UNKNOWN; + case Result::Sat::UNSAT: return satResult; + case Result::Sat::SAT_UNKNOWN: return satResult; case Result::Sat::SAT: { // if satisfied, use d_results to store the initial results @@ -226,14 +230,15 @@ OptimizationResult::ResultType OptimizationSolver::optimizeParetoNaiveGIA() for (size_t i = 0, numObj = d_objectives.size(); i < numObj; ++i) { d_results[i] = OptimizationResult( - OptimizationResult::OPTIMAL, - d_optChecker->getValue(d_objectives[i].getTarget())); + satResult, d_optChecker->getValue(d_objectives[i].getTarget())); } break; } default: Unreachable(); } + Result lastSatResult = satResult; + // a vector storing assertions saying that no objective is worse std::vector<Node> noWorseObj; // a vector storing assertions saying that there is at least one objective @@ -278,15 +283,15 @@ OptimizationResult::ResultType OptimizationSolver::optimizeParetoNaiveGIA() case Result::Sat::SAT_UNKNOWN: // if result is UNKNOWN, abort the current session and return UNKNOWN d_optChecker.reset(); - return OptimizationResult::UNKNOWN; + return satResult; case Result::Sat::SAT: { + lastSatResult = satResult; // if result is SAT, update d_results to the more optimal values for (size_t i = 0, numObj = d_objectives.size(); i < numObj; ++i) { d_results[i] = OptimizationResult( - OptimizationResult::OPTIMAL, - d_optChecker->getValue(d_objectives[i].getTarget())); + satResult, d_optChecker->getValue(d_objectives[i].getTarget())); } break; } @@ -302,7 +307,7 @@ OptimizationResult::ResultType OptimizationSolver::optimizeParetoNaiveGIA() // for the next run. d_optChecker->assertFormula(nm->mkOr(someObjBetter)); - return OptimizationResult::OPTIMAL; + return lastSatResult; } } // namespace smt diff --git a/src/smt/optimization_solver.h b/src/smt/optimization_solver.h index 6d138deb2..d13168780 100644 --- a/src/smt/optimization_solver.h +++ b/src/smt/optimization_solver.h @@ -33,63 +33,75 @@ namespace smt { /** * The optimization result of an optimization objective * containing: - * - whether it's optimal or not - * - if so, the optimal value, otherwise the value might be empty node or - * something suboptimal + * - the optimization result: SAT/UNSAT/UNKNOWN + * - the optimal value if SAT and bounded + * (optimal value reached and it's not infinity), + * or an empty node if SAT and unbounded + * (optimal value is +inf for maximum or -inf for minimum), + * otherwise the value might be empty node + * or something suboptimal + * - whether the objective is unbounded */ class OptimizationResult { public: /** - * Enum indicating whether the checkOpt result - * is optimal or not. - **/ - enum ResultType - { - // whether the value is optimal is UNKNOWN - UNKNOWN, - // the original set of assertions has result UNSAT - UNSAT, - // the value is optimal - OPTIMAL, - // the goal is unbounded, - // if objective is maximize, it's +infinity - // if objective is minimize, it's -infinity - UNBOUNDED, - }; - - /** * Constructor * @param type the optimization outcome * @param value the optimized value + * @param unbounded whether the objective is unbounded **/ - OptimizationResult(ResultType type, TNode value) - : d_type(type), d_value(value) + OptimizationResult(Result result, TNode value, bool unbounded = false) + : d_result(result), d_value(value), d_unbounded(unbounded) + { + } + OptimizationResult() + : d_result(Result::Sat::SAT_UNKNOWN, + Result::UnknownExplanation::NO_STATUS), + d_value(), + d_unbounded(false) { } - OptimizationResult() : d_type(UNKNOWN), d_value() {} ~OptimizationResult() = default; /** * Returns an enum indicating whether - * the result is optimal or not. - * @return an enum showing whether the result is optimal, unbounded, - * unsat or unknown. + * the result is SAT or not. + * @return whether the result is SAT, UNSAT or SAT_UNKNOWN **/ - ResultType getType() const { return d_type; } + Result getResult() const { return d_result; } + /** * Returns the optimal value. * @return Node containing the optimal value, - * if getType() is not OPTIMAL, it might return an empty node or a node - * containing non-optimal value + * if result is unbounded, this will be an empty node, + * if getResult() is UNSAT, it will return an empty node, + * if getResult() is SAT_UNKNOWN, it will return something suboptimal + * or an empty node, depending on how the solver runs. **/ Node getValue() const { return d_value; } + /** + * Checks whether the objective is unbouned + * @return whether the objective is unbounded + * if the objective is unbounded (this function returns true), + * then the optimal value is: + * +inf, if it's maximize; + * -inf, if it's minimize + **/ + bool isUnbounded() const { return d_unbounded; } + private: - /** the indicating whether the result is optimal or something else **/ - ResultType d_type; - /** if the result is optimal, this is storing the optimal value **/ + /** indicating whether the result is SAT, UNSAT or UNKNOWN **/ + Result d_result; + /** if the result is bounded, this is storing the value **/ Node d_value; + /** whether the objective is unbounded + * If this is true, then: + * if objective is maximize, it's +infinity; + * if objective is minimize, it's -infinity + **/ + bool d_unbounded; }; /** @@ -199,10 +211,10 @@ class OptimizationSolver /** * Run the optimization loop for the added objective * For multiple objective combination, it defaults to lexicographic, - * and combination could be set by calling - * setObjectiveCombination(BOX/LEXICOGRAPHIC/PARETO) + * possible combinations: BOX, LEXICOGRAPHIC, PARETO + * @param combination BOX / LEXICOGRAPHIC / PARETO */ - OptimizationResult::ResultType checkOpt(); + Result checkOpt(ObjectiveCombination combination = LEXICOGRAPHIC); /** * Add an optimization objective. @@ -223,11 +235,6 @@ class OptimizationSolver **/ std::vector<OptimizationResult> getValues(); - /** - * Sets the objective combination - **/ - void setObjectiveCombination(ObjectiveCombination combination); - private: /** * Initialize an SMT subsolver for offline optimization purpose @@ -244,26 +251,26 @@ class OptimizationSolver /** * Optimize multiple goals in Box order - * @return OPTIMAL if all of the objectives are either OPTIMAL or UNBOUNDED; - * UNSAT if at least one objective is UNSAT and no objective is UNKNOWN; - * UNKNOWN if any of the objective is UNKNOWN. + * @return SAT if all of the objectives are optimal or unbounded; + * UNSAT if at least one objective is UNSAT and no objective is SAT_UNKNOWN; + * SAT_UNKNOWN if any of the objective is SAT_UNKNOWN. **/ - OptimizationResult::ResultType optimizeBox(); + Result optimizeBox(); /** * Optimize multiple goals in Lexicographic order, * using iterative implementation - * @return OPTIMAL if all objectives are OPTIMAL and bounded; - * UNBOUNDED if one of the objectives is UNBOUNDED + * @return SAT if the objectives are optimal, + * if one of the objectives is unbounded, + * the optimization will stop at that objective; + * UNSAT if any of the objectives is UNSAT * and optimization will stop at that objective; - * UNSAT if one of the objectives is UNSAT - * and optimization will stop at that objective; - * UNKNOWN if one of the objectives is UNKNOWN + * SAT_UNKNOWN if any of the objectives is UNKNOWN * and optimization will stop at that objective; * If the optimization is stopped at an objective, - * all objectives following that objective will be UNKNOWN. + * all objectives following that objective will be SAT_UNKNOWN. **/ - OptimizationResult::ResultType optimizeLexicographicIterative(); + Result optimizeLexicographicIterative(); /** * Optimize multiple goals in Pareto order @@ -277,11 +284,12 @@ class OptimizationSolver * D. Rayside, H.-C. Estler, and D. Jackson. The Guided Improvement Algorithm. * Technical Report MIT-CSAIL-TR-2009-033, MIT, 2009. * - * @return if it finds a new Pareto optimal result it will return OPTIMAL; + * @return if it finds a new Pareto optimal result it will return SAT; * if it exhausts the results in the Pareto front it will return UNSAT; - * if the underlying SMT solver returns UNKNOWN, it will return UNKNOWN. + * if the underlying SMT solver returns SAT_UNKNOWN, + * it will return SAT_UNKNOWN. **/ - OptimizationResult::ResultType optimizeParetoNaiveGIA(); + Result optimizeParetoNaiveGIA(); /** A pointer to the parent SMT engine **/ SmtEngine* d_parent; @@ -294,9 +302,6 @@ class OptimizationSolver /** The results of the optimizations from the last checkOpt call **/ std::vector<OptimizationResult> d_results; - - /** The current objective combination method **/ - ObjectiveCombination d_objectiveCombination; }; } // namespace smt diff --git a/src/smt/preprocessor.cpp b/src/smt/preprocessor.cpp index 7406b922e..3c0a4ac5b 100644 --- a/src/smt/preprocessor.cpp +++ b/src/smt/preprocessor.cpp @@ -15,6 +15,7 @@ #include "smt/preprocessor.h" +#include "options/base_options.h" #include "options/expr_options.h" #include "options/smt_options.h" #include "preprocessing/preprocessing_pass_context.h" diff --git a/src/smt/set_defaults.cpp b/src/smt/set_defaults.cpp index cd05b84c4..e119ce4d4 100644 --- a/src/smt/set_defaults.cpp +++ b/src/smt/set_defaults.cpp @@ -66,7 +66,7 @@ void setDefaults(LogicInfo& logic, bool isInternalSubsolver) // unsat cores and proofs shenanigans if (options::dumpUnsatCoresFull()) { - opts.smt.dumpUnsatCores = true; + opts.driver.dumpUnsatCores = true; } if (options::checkUnsatCores() || options::dumpUnsatCores() || options::unsatAssumptions() diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp index bd48fe0ea..9056e7c94 100644 --- a/src/smt/smt_engine.cpp +++ b/src/smt/smt_engine.cpp @@ -29,7 +29,6 @@ #include "options/option_exception.h" #include "options/printer_options.h" #include "options/proof_options.h" -#include "options/resource_manager_options.h" #include "options/smt_options.h" #include "options/theory_options.h" #include "printer/printer.h" @@ -1811,16 +1810,16 @@ void SmtEngine::setResourceLimit(uint64_t units, bool cumulative) { if (cumulative) { - d_env->d_options.resman.cumulativeResourceLimit = units; + d_env->d_options.base.cumulativeResourceLimit = units; } else { - d_env->d_options.resman.perCallResourceLimit = units; + d_env->d_options.base.perCallResourceLimit = units; } } void SmtEngine::setTimeLimit(uint64_t millis) { - d_env->d_options.resman.perCallMillisecondLimit = millis; + d_env->d_options.base.perCallMillisecondLimit = millis; } unsigned long SmtEngine::getResourceUsage() const diff --git a/src/smt/smt_engine_state.cpp b/src/smt/smt_engine_state.cpp index 4afa15a3b..cb0a94123 100644 --- a/src/smt/smt_engine_state.cpp +++ b/src/smt/smt_engine_state.cpp @@ -16,6 +16,7 @@ #include "smt/smt_engine_state.h" #include "base/modal_exception.h" +#include "options/base_options.h" #include "options/option_exception.h" #include "options/smt_options.h" #include "smt/smt_engine.h" diff --git a/src/smt/smt_engine_stats.cpp b/src/smt/smt_engine_stats.cpp index 417d345cb..c76a8a2e7 100644 --- a/src/smt/smt_engine_stats.cpp +++ b/src/smt/smt_engine_stats.cpp @@ -25,8 +25,6 @@ SmtEngineStatistics::SmtEngineStatistics(const std::string& name) name + "definitionExpansionTime")), d_numConstantProps( smtStatisticsRegistry().registerInt(name + "numConstantProps")), - d_cnfConversionTime( - smtStatisticsRegistry().registerTimer(name + "cnfConversionTime")), d_numAssertionsPre(smtStatisticsRegistry().registerInt( name + "numAssertionsPreITERemoval")), d_numAssertionsPost(smtStatisticsRegistry().registerInt( diff --git a/src/smt/smt_engine_stats.h b/src/smt/smt_engine_stats.h index 441721a54..db914b560 100644 --- a/src/smt/smt_engine_stats.h +++ b/src/smt/smt_engine_stats.h @@ -30,8 +30,6 @@ struct SmtEngineStatistics TimerStat d_definitionExpansionTime; /** number of constant propagations found during nonclausal simp */ IntStat d_numConstantProps; - /** time spent converting to CNF */ - TimerStat d_cnfConversionTime; /** Number of assertions before ite removal */ IntStat d_numAssertionsPre; /** Number of assertions after ite removal */ diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp index d7b70f501..f5783ab6b 100644 --- a/src/smt/smt_solver.cpp +++ b/src/smt/smt_solver.cpp @@ -239,7 +239,6 @@ void SmtSolver::processAssertions(Assertions& as) // Push the formula to SAT { Chat() << "converting to CNF..." << endl; - TimerStat::CodeTimer codeTimer(d_stats.d_cnfConversionTime); const std::vector<Node>& assertions = ap.ref(); // It is important to distinguish the input assertions from the skolem // definitions, as the decision justification heuristic treates the latter diff --git a/src/smt/sygus_solver.cpp b/src/smt/sygus_solver.cpp index 8fa610cda..98278ef9e 100644 --- a/src/smt/sygus_solver.cpp +++ b/src/smt/sygus_solver.cpp @@ -20,6 +20,7 @@ #include "base/modal_exception.h" #include "expr/dtype.h" #include "expr/skolem_manager.h" +#include "options/base_options.h" #include "options/option_exception.h" #include "options/quantifiers_options.h" #include "options/smt_options.h" diff --git a/src/theory/arith/arith_ite_utils.cpp b/src/theory/arith/arith_ite_utils.cpp index 99b95719f..3dff64113 100644 --- a/src/theory/arith/arith_ite_utils.cpp +++ b/src/theory/arith/arith_ite_utils.cpp @@ -22,6 +22,7 @@ #include "base/output.h" #include "expr/skolem_manager.h" +#include "options/base_options.h" #include "options/smt_options.h" #include "preprocessing/util/ite_utilities.h" #include "theory/arith/arith_utilities.h" diff --git a/src/theory/arith/kinds b/src/theory/arith/kinds index 396befb35..0c93db90f 100644 --- a/src/theory/arith/kinds +++ b/src/theory/arith/kinds @@ -26,6 +26,7 @@ operator INTS_MODULUS_TOTAL 2 "integer modulus with interpreted division by 0 (i operator ABS 1 "absolute value" parameterized DIVISIBLE DIVISIBLE_OP 1 "divisibility-by-k predicate; first parameter is a DIVISIBLE_OP, second is integer term" operator POW 2 "arithmetic power" +operator POW2 1 "arithmetic power of 2" operator EXPONENTIAL 1 "exponential" operator SINE 1 "sine" @@ -148,6 +149,7 @@ typerule ARCTANGENT "SimpleTypeRule<RReal, AReal>" typerule ARCCOSECANT "SimpleTypeRule<RReal, AReal>" typerule ARCSECANT "SimpleTypeRule<RReal, AReal>" typerule ARCCOTANGENT "SimpleTypeRule<RReal, AReal>" +typerule POW2 "SimpleTypeRule<RInteger, AInteger>" typerule SQRT "SimpleTypeRule<RReal, AReal>" diff --git a/src/theory/arith/nl/cad/lazard_evaluation.cpp b/src/theory/arith/nl/cad/lazard_evaluation.cpp index 82b127ed0..2fee21cbf 100644 --- a/src/theory/arith/nl/cad/lazard_evaluation.cpp +++ b/src/theory/arith/nl/cad/lazard_evaluation.cpp @@ -1,5 +1,7 @@ #include "theory/arith/nl/cad/lazard_evaluation.h" +#ifdef CVC5_POLY_IMP + #include "base/check.h" #include "base/output.h" @@ -44,3 +46,5 @@ std::vector<poly::Interval> LazardEvaluation::infeasibleRegions( } } // namespace cvc5::theory::arith::nl::cad + +#endif diff --git a/src/theory/arith/nl/cad/lazard_evaluation.h b/src/theory/arith/nl/cad/lazard_evaluation.h index 0edb12010..3bb971c4c 100644 --- a/src/theory/arith/nl/cad/lazard_evaluation.h +++ b/src/theory/arith/nl/cad/lazard_evaluation.h @@ -19,6 +19,8 @@ #ifndef CVC5__THEORY__ARITH__NL__CAD__LAZARD_EVALUATION_H #define CVC5__THEORY__ARITH__NL__CAD__LAZARD_EVALUATION_H +#ifdef CVC5_POLY_IMP + #include <poly/polyxx.h> #include <memory> @@ -106,4 +108,5 @@ class LazardEvaluation } // namespace cvc5::theory::arith::nl::cad -#endif
\ No newline at end of file +#endif +#endif diff --git a/src/theory/arith/nl/pow2_solver.cpp b/src/theory/arith/nl/pow2_solver.cpp new file mode 100644 index 000000000..534895c7f --- /dev/null +++ b/src/theory/arith/nl/pow2_solver.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * Top contributors (to current version): + * Andrew Reynolds, Makai Mann, Gereon Kremer + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * Implementation of pow2 solver. + */ + +#include "theory/arith/nl/pow2_solver.h" + +#include "theory/arith/arith_msum.h" +#include "theory/arith/arith_state.h" +#include "theory/arith/arith_utilities.h" +#include "theory/arith/inference_manager.h" +#include "theory/arith/nl/nl_model.h" +#include "theory/rewriter.h" + +using namespace cvc5::kind; + +namespace cvc5 { +namespace theory { +namespace arith { +namespace nl { + +Pow2Solver::Pow2Solver(InferenceManager& im, ArithState& state, NlModel& model) + : d_im(im), d_model(model), d_initRefine(state.getUserContext()) +{ + NodeManager* nm = NodeManager::currentNM(); + d_false = nm->mkConst(false); + d_true = nm->mkConst(true); + d_zero = nm->mkConst(Rational(0)); + d_one = nm->mkConst(Rational(1)); + d_two = nm->mkConst(Rational(2)); +} + +Pow2Solver::~Pow2Solver() {} + +void Pow2Solver::initLastCall(const std::vector<Node>& assertions, + const std::vector<Node>& false_asserts, + const std::vector<Node>& xts) +{ + d_pow2s.clear(); + Trace("pow2-mv") << "POW2 terms : " << std::endl; + for (const Node& a : xts) + { + Kind ak = a.getKind(); + if (ak != POW2) + { + // don't care about other terms + continue; + } + d_pow2s.push_back(a); + } + Trace("pow2") << "We have " << d_pow2s.size() << " pow2 terms." << std::endl; +} + +void Pow2Solver::checkInitialRefine() {} + +void Pow2Solver::checkFullRefine() {} + +Node Pow2Solver::valueBasedLemma(Node i) { return Node(); } + +} // namespace nl +} // namespace arith +} // namespace theory +} // namespace cvc5 diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp index a675c1bf4..97b29b6b3 100644 --- a/src/theory/arith/theory_arith_private.cpp +++ b/src/theory/arith/theory_arith_private.cpp @@ -35,7 +35,7 @@ #include "expr/node_builder.h" #include "expr/skolem_manager.h" #include "options/arith_options.h" -#include "options/smt_options.h" // for incrementalSolving() +#include "options/base_options.h" #include "preprocessing/util/ite_utilities.h" #include "proof/proof_generator.h" #include "proof/proof_node_manager.h" diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp index ea18b3180..be8e1a08e 100644 --- a/src/theory/arrays/theory_arrays.cpp +++ b/src/theory/arrays/theory_arrays.cpp @@ -151,6 +151,8 @@ bool TheoryArrays::needsEqualityEngine(EeSetupInfo& esi) { esi.d_notify = &d_notify; esi.d_name = d_instanceName + "ee"; + esi.d_notifyNewClass = true; + esi.d_notifyMerge = true; return true; } diff --git a/src/theory/bv/bitblast/eager_bitblaster.cpp b/src/theory/bv/bitblast/eager_bitblaster.cpp index 9871f2a92..55ed6c41d 100644 --- a/src/theory/bv/bitblast/eager_bitblaster.cpp +++ b/src/theory/bv/bitblast/eager_bitblaster.cpp @@ -16,6 +16,7 @@ #include "theory/bv/bitblast/eager_bitblaster.h" #include "cvc5_private.h" +#include "options/base_options.h" #include "options/bv_options.h" #include "options/smt_options.h" #include "prop/cnf_stream.h" diff --git a/src/theory/bv/bitblast/simple_bitblaster.cpp b/src/theory/bv/bitblast/simple_bitblaster.cpp index a38dfdfe5..357a54b1a 100644 --- a/src/theory/bv/bitblast/simple_bitblaster.cpp +++ b/src/theory/bv/bitblast/simple_bitblaster.cpp @@ -17,6 +17,7 @@ #include "theory/theory_model.h" #include "theory/theory_state.h" +#include "options/bv_options.h" namespace cvc5 { namespace theory { @@ -129,6 +130,15 @@ Node BBSimple::getModelFromSatSolver(TNode a, bool fullModel) return utils::mkConst(bits.size(), value); } +void BBSimple::computeRelevantTerms(std::set<Node>& termSet) +{ + Assert(options::bitblastMode() == options::BitblastMode::EAGER); + for (const auto& var : d_variables) + { + termSet.insert(var); + } +} + bool BBSimple::collectModelValues(TheoryModel* m, const std::set<Node>& relevantTerms) { diff --git a/src/theory/bv/bitblast/simple_bitblaster.h b/src/theory/bv/bitblast/simple_bitblaster.h index ebbb2891f..ec0899145 100644 --- a/src/theory/bv/bitblast/simple_bitblaster.h +++ b/src/theory/bv/bitblast/simple_bitblaster.h @@ -53,6 +53,8 @@ class BBSimple : public TBitblaster<Node> /** Create 'bits' for variable 'var'. */ void makeVariable(TNode var, Bits& bits) override; + /** Add d_variables to termSet. */ + void computeRelevantTerms(std::set<Node>& termSet); /** Collect model values for all relevant terms given in 'relevantTerms'. */ bool collectModelValues(TheoryModel* m, const std::set<Node>& relevantTerms); diff --git a/src/theory/bv/bv_eager_solver.cpp b/src/theory/bv/bv_eager_solver.cpp index 2d0ae1931..b0082b992 100644 --- a/src/theory/bv/bv_eager_solver.cpp +++ b/src/theory/bv/bv_eager_solver.cpp @@ -15,6 +15,7 @@ #include "theory/bv/bv_eager_solver.h" +#include "options/base_options.h" #include "options/bv_options.h" #include "options/smt_options.h" #include "theory/bv/bitblast/aig_bitblaster.h" diff --git a/src/theory/bv/bv_solver.h b/src/theory/bv/bv_solver.h index 8ff4318c0..6ccc6c7c1 100644 --- a/src/theory/bv/bv_solver.h +++ b/src/theory/bv/bv_solver.h @@ -32,7 +32,7 @@ class BVSolver BVSolver(TheoryState& state, TheoryInferenceManager& inferMgr) : d_state(state), d_im(inferMgr){}; - virtual ~BVSolver(){}; + virtual ~BVSolver() {} /** * Returns true if we need an equality engine. If so, we initialize the @@ -71,7 +71,7 @@ class BVSolver virtual bool needsCheckLastEffort() { return false; } - virtual void propagate(Theory::Effort e){}; + virtual void propagate(Theory::Effort e) {} virtual TrustNode explain(TNode n) { @@ -80,17 +80,20 @@ class BVSolver return TrustNode::null(); } + /** Additionally collect terms relevant for collecting model values. */ + virtual void computeRelevantTerms(std::set<Node>& termSet) {} + /** Collect model values in m based on the relevant terms given by termSet */ virtual bool collectModelValues(TheoryModel* m, const std::set<Node>& termSet) = 0; virtual std::string identify() const = 0; - virtual TrustNode ppRewrite(TNode t) { return TrustNode::null(); }; + virtual TrustNode ppRewrite(TNode t) { return TrustNode::null(); } - virtual void ppStaticLearn(TNode in, NodeBuilder& learned){}; + virtual void ppStaticLearn(TNode in, NodeBuilder& learned) {} - virtual void presolve(){}; + virtual void presolve() {} virtual void notifySharedTerm(TNode t) {} diff --git a/src/theory/bv/bv_solver_bitblast.cpp b/src/theory/bv/bv_solver_bitblast.cpp index dc2c7e2a3..3ae4a7f0a 100644 --- a/src/theory/bv/bv_solver_bitblast.cpp +++ b/src/theory/bv/bv_solver_bitblast.cpp @@ -96,17 +96,19 @@ BVSolverBitblast::BVSolverBitblast(TheoryState* s, { case options::SatSolverMode::CRYPTOMINISAT: d_satSolver.reset(prop::SatSolverFactory::createCryptoMinisat( - smtStatisticsRegistry(), "theory::bv::BVSolverBitblast")); + smtStatisticsRegistry(), "theory::bv::BVSolverBitblast::")); break; default: d_satSolver.reset(prop::SatSolverFactory::createCadical( - smtStatisticsRegistry(), "theory::bv::BVSolverBitblast")); + smtStatisticsRegistry(), "theory::bv::BVSolverBitblast::")); } d_cnfStream.reset(new prop::CnfStream(d_satSolver.get(), d_bbRegistrar.get(), d_nullContext.get(), nullptr, - smt::currentResourceManager())); + smt::currentResourceManager(), + prop::FormulaLitPolicy::INTERNAL, + "theory::bv::BVSolverBitblast")); } void BVSolverBitblast::postCheck(Theory::Effort level) @@ -236,6 +238,21 @@ TrustNode BVSolverBitblast::explain(TNode n) return d_im.explainLit(n); } +void BVSolverBitblast::computeRelevantTerms(std::set<Node>& termSet) +{ + /* BITVECTOR_EAGER_ATOM wraps input assertions that may also contain + * equalities. As a result, these equalities are not handled by the equality + * engine and terms below these equalities do not appear in `termSet`. + * We need to make sure that we compute model values for all relevant terms + * in BitblastMode::EAGER and therefore add all variables from the + * bit-blaster to `termSet`. + */ + if (options::bitblastMode() == options::BitblastMode::EAGER) + { + d_bitblaster->computeRelevantTerms(termSet); + } +} + bool BVSolverBitblast::collectModelValues(TheoryModel* m, const std::set<Node>& termSet) { diff --git a/src/theory/bv/bv_solver_bitblast.h b/src/theory/bv/bv_solver_bitblast.h index 31d9443c8..c5134c6fc 100644 --- a/src/theory/bv/bv_solver_bitblast.h +++ b/src/theory/bv/bv_solver_bitblast.h @@ -64,6 +64,8 @@ class BVSolverBitblast : public BVSolver EqualityStatus getEqualityStatus(TNode a, TNode b) override; + void computeRelevantTerms(std::set<Node>& termSet) override; + bool collectModelValues(TheoryModel* m, const std::set<Node>& termSet) override; diff --git a/src/theory/bv/int_blaster.cpp b/src/theory/bv/int_blaster.cpp new file mode 100644 index 000000000..9da9d1c2b --- /dev/null +++ b/src/theory/bv/int_blaster.cpp @@ -0,0 +1,240 @@ +/****************************************************************************** + * Top contributors (to current version): + * Yoni Zohar + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * Int-blasting utility + */ + +#include "theory/bv/int_blaster.h" + +#include <cmath> +#include <string> +#include <unordered_map> +#include <vector> + +#include "expr/node.h" +#include "expr/node_traversal.h" +#include "expr/skolem_manager.h" +#include "options/option_exception.h" +#include "options/uf_options.h" +#include "theory/rewriter.h" +#include "util/iand.h" +#include "util/rational.h" + +namespace cvc5 { +using namespace cvc5::theory; + +IntBlaster::IntBlaster(context::Context* c, + options::SolveBVAsIntMode mode, + uint64_t granularity, + bool introduceFreshIntVars) + : d_binarizeCache(c), + d_intblastCache(c), + d_rangeAssertions(c), + d_bitwiseAssertions(c), + d_mode(mode), + d_granularity(granularity), + d_context(c), + d_introduceFreshIntVars(introduceFreshIntVars) +{ + d_nm = NodeManager::currentNM(); + d_zero = d_nm->mkConst<Rational>(0); + d_one = d_nm->mkConst<Rational>(1); +}; + +void IntBlaster::addRangeConstraint(Node node, + uint64_t size, + std::vector<Node>& lemmas) +{ +} + +void IntBlaster::addBitwiseConstraint(Node bitwiseConstraint, + std::vector<Node>& lemmas) +{ +} + +Node IntBlaster::mkRangeConstraint(Node newVar, uint64_t k) { return Node(); } + +Node IntBlaster::maxInt(uint64_t k) { return Node(); } + +Node IntBlaster::pow2(uint64_t k) { return Node(); } + +Node IntBlaster::modpow2(Node n, uint64_t exponent) { return Node(); } + +Node IntBlaster::makeBinary(Node n) +{ + if (d_binarizeCache.find(n) != d_binarizeCache.end()) + { + return d_binarizeCache[n]; + } + uint64_t numChildren = n.getNumChildren(); + kind::Kind_t k = n.getKind(); + Node result = n; + if ((numChildren > 2) + && (k == kind::BITVECTOR_ADD || k == kind::BITVECTOR_MULT + || k == kind::BITVECTOR_AND || k == kind::BITVECTOR_OR + || k == kind::BITVECTOR_XOR || k == kind::BITVECTOR_CONCAT)) + { + result = n[0]; + for (uint64_t i = 1; i < numChildren; i++) + { + result = d_nm->mkNode(n.getKind(), result, n[i]); + } + } + d_binarizeCache[n] = result; + Trace("int-blaster-debug") << "binarization result: " << result << std::endl; + return result; +} + +/** + * Translate n to Integers via post-order traversal. + */ +Node IntBlaster::intBlast(Node n, + std::vector<Node>& lemmas, + std::map<Node, Node>& skolems) +{ + // make sure the node is re-written + n = Rewriter::rewrite(n); + + // helper vector for traversal. + std::vector<Node> toVisit; + toVisit.push_back(makeBinary(n)); + + while (!toVisit.empty()) + { + Node current = toVisit.back(); + uint64_t currentNumChildren = current.getNumChildren(); + if (d_intblastCache.find(current) == d_intblastCache.end()) + { + // This is the first time we visit this node and it is not in the cache. + // We mark this node as visited but not translated by assiging + // a null node to it. + d_intblastCache[current] = Node(); + // all the node's children are added to the stack to be visited + // before visiting this node again. + for (const Node& child : current) + { + toVisit.push_back(makeBinary(child)); + } + // If this is a UF applicatinon, we also add the function to + // toVisit. + if (current.getKind() == kind::APPLY_UF) + { + toVisit.push_back(current.getOperator()); + } + } + else + { + // We already visited and translated this node + if (!d_intblastCache[current].get().isNull()) + { + // We are done computing the translation for current + toVisit.pop_back(); + } + else + { + // We are now visiting current on the way back up. + // This is when we do the actual translation. + Node translation; + if (currentNumChildren == 0) + { + translation = translateNoChildren(current, lemmas, skolems); + } + else + { + /** + * The current node has children. + * Since we are on the way back up, + * these children were already translated. + * We save their translation for easy access. + * If the node's kind is APPLY_UF, + * we also need to include the translated uninterpreted function in + * this list. + */ + std::vector<Node> translated_children; + if (current.getKind() == kind::APPLY_UF) + { + translated_children.push_back( + d_intblastCache[current.getOperator()]); + } + for (uint64_t i = 0; i < currentNumChildren; i++) + { + translated_children.push_back(d_intblastCache[current[i]]); + } + translation = + translateWithChildren(current, translated_children, lemmas); + } + + Assert(!translation.isNull()); + // Map the current node to its translation in the cache. + d_intblastCache[current] = translation; + // Also map the translation to itself. + d_intblastCache[translation] = translation; + toVisit.pop_back(); + } + } + } + return d_intblastCache[n].get(); +} + +Node IntBlaster::unsignedToSigned(Node n, uint64_t bw) { return Node(); } + +Node IntBlaster::translateWithChildren( + Node original, + const std::vector<Node>& translated_children, + std::vector<Node>& lemmas) +{ + Node binarized = makeBinary(original); + // continue to process the binarized version + return Node(); +} + +Node IntBlaster::translateNoChildren(Node original, + std::vector<Node>& lemmas, + std::map<Node, Node>& skolems) +{ + return Node(); +} + +Node IntBlaster::defineBVUFAsIntUF(Node bvUF, Node intUF) { return Node(); } + +Node IntBlaster::translateFunctionSymbol(Node bvUF, + std::map<Node, Node>& skolems) +{ + return Node(); +} + +bool IntBlaster::childrenTypesChanged(Node n) { return true; } + +Node IntBlaster::castToType(Node n, TypeNode tn) { return Node(); } + +Node IntBlaster::reconstructNode(Node originalNode, + TypeNode resultType, + const std::vector<Node>& translated_children) +{ + return Node(); +} + +Node IntBlaster::createShiftNode(std::vector<Node> children, + uint64_t bvsize, + bool isLeftShift) +{ + return Node(); +} + +Node IntBlaster::translateQuantifiedFormula(Node quantifiedNode) +{ + return Node(); +} + +Node IntBlaster::createBVNotNode(Node n, uint64_t bvsize) { return Node(); } + +} // namespace cvc5 diff --git a/src/theory/bv/int_blaster.h b/src/theory/bv/int_blaster.h index f8717e045..444eb88a7 100644 --- a/src/theory/bv/int_blaster.h +++ b/src/theory/bv/int_blaster.h @@ -75,9 +75,10 @@ namespace cvc5 { ** Tr((bvult a b)) = Tr(a) < Tr(b) ** Similar transformations are done for bvule, bvugt, and bvuge. ** -** Bit-vector operators that are not listed above are either eliminated using -** the function eliminationPass, or go through the following default -*translation, that also works for non-bit-vector operators +** Bit-vector operators that are not listed above are either +** eliminated using the BV rewriter, +** or go through the following default +** translation, that also works for non-bit-vector operators ** with result type BV: ** Tr((op t1 ... tn)) = (bv2nat (op (cast t1) ... (cast tn))) ** where (cast x) is ((_ nat2bv k) x) or just x, @@ -118,8 +119,7 @@ class IntBlaster * ff((bv2nat x))), where k is the bit-width of the domain of f, i is the * bit-width of its range, and ff is a Int->Int function that corresponds to * f. For functions with other signatures this is similar - * @return integer node that corresponds to n, or a null node if d_supportNoBV - * is set to false and n is note purely BV. + * @return integer node that corresponds to n */ Node intBlast(Node n, std::vector<Node>& lemmas, @@ -165,18 +165,15 @@ class IntBlaster Node mkRangeConstraint(Node newVar, uint64_t k); /** - * In the translation to integers, it is convenient to assume that certain - * bit-vector operators do not occur in the original formula (e.g., repeat). - * This function eliminates all these operators. - */ - Node eliminationPass(Node n); - - /** * Some bit-vector operators (e.g., bvadd, bvand) are binary, but allow more * than two arguments as a syntactic sugar. * For example, we can have a node for (bvand x y z), * that represents (bvand (x (bvand y z))). - * This function makes all such operators strictly binary. + * This function locally binarizes these operators. + * In the above example, this means that x,y,z + * are not handled recursively, but will require a separate + * call to the function. + * */ Node makeBinary(Node n); @@ -287,7 +284,7 @@ class IntBlaster * binary representation of n is the same as the * signed binary representation of m. */ - Node unsignedTosigned(Node n, uint64_t bvsize); + Node unsignedToSigned(Node n, uint64_t bvsize); /** * Performs the actual translation to integers for nodes @@ -308,8 +305,6 @@ class IntBlaster /** Caches for the different functions */ CDNodeMap d_binarizeCache; - CDNodeMap d_eliminationCache; - CDNodeMap d_rebuildCache; CDNodeMap d_intblastCache; /** Node manager that is used throughout the pass */ diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp index 22b05b026..3d7f11f6d 100644 --- a/src/theory/bv/theory_bv.cpp +++ b/src/theory/bv/theory_bv.cpp @@ -175,6 +175,11 @@ bool TheoryBV::needsCheckLastEffort() return d_internal->needsCheckLastEffort(); } +void TheoryBV::computeRelevantTerms(std::set<Node>& termSet) +{ + return d_internal->computeRelevantTerms(termSet); +} + bool TheoryBV::collectModelValues(TheoryModel* m, const std::set<Node>& termSet) { return d_internal->collectModelValues(m, termSet); diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h index 4b3a1f3b2..e884f621c 100644 --- a/src/theory/bv/theory_bv.h +++ b/src/theory/bv/theory_bv.h @@ -83,6 +83,8 @@ class TheoryBV : public Theory TrustNode explain(TNode n) override; + void computeRelevantTerms(std::set<Node>& termSet) override; + /** Collect model values in m based on the relevant terms given by termSet */ bool collectModelValues(TheoryModel* m, const std::set<Node>& termSet) override; diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp index dc57e4165..53f128286 100644 --- a/src/theory/datatypes/theory_datatypes.cpp +++ b/src/theory/datatypes/theory_datatypes.cpp @@ -94,6 +94,9 @@ bool TheoryDatatypes::needsEqualityEngine(EeSetupInfo& esi) { esi.d_notify = &d_notify; esi.d_name = "theory::datatypes::ee"; + // need notifications on new constructors, merging datatype eqcs + esi.d_notifyNewClass = true; + esi.d_notifyMerge = true; return true; } diff --git a/src/theory/ee_setup_info.h b/src/theory/ee_setup_info.h index f6139d109..130241c4a 100644 --- a/src/theory/ee_setup_info.h +++ b/src/theory/ee_setup_info.h @@ -39,7 +39,12 @@ class EqualityEngineNotify; struct EeSetupInfo { EeSetupInfo() - : d_notify(nullptr), d_constantsAreTriggers(true), d_useMaster(false) + : d_notify(nullptr), + d_constantsAreTriggers(true), + d_notifyNewClass(false), + d_notifyMerge(false), + d_notifyDisequal(false), + d_useMaster(false) { } /** The notification class of the theory */ @@ -48,11 +53,25 @@ struct EeSetupInfo std::string d_name; /** Constants are triggers */ bool d_constantsAreTriggers; + //-------------------------- fine grained notifications + /** Whether we need to be notified of new equivalence classes */ + bool d_notifyNewClass; + /** Whether we need to be notified of merged equivalence classes */ + bool d_notifyMerge; + /** Whether we need to be notified of disequal equivalence classes */ + bool d_notifyDisequal; + //-------------------------- end fine grained notifications /** * Whether we want our state to use the master equality engine. This should * be true exclusively for the theory of quantifiers. */ bool d_useMaster; + /** Does it need notifications when equivalence classes are created? */ + bool needsNotifyNewClass() const { return d_notifyNewClass; } + /** Does it need notifications when equivalence classes are merged? */ + bool needsNotifyMerge() const { return d_notifyMerge; } + /** Does it need notifications when disequalities are generated? */ + bool needsNotifyDisequal() const { return d_notifyDisequal; } }; } // namespace theory diff --git a/src/theory/fp/fp_converter.cpp b/src/theory/fp/fp_converter.cpp index 0d1b25549..0e196c0e0 100644 --- a/src/theory/fp/fp_converter.cpp +++ b/src/theory/fp/fp_converter.cpp @@ -23,7 +23,6 @@ #include "util/floatingpoint.h" #include "util/floatingpoint_literal_symfpu.h" -#ifdef CVC5_USE_SYMFPU #include "symfpu/core/add.h" #include "symfpu/core/classify.h" #include "symfpu/core/compare.h" @@ -38,9 +37,7 @@ #include "symfpu/core/sqrt.h" #include "symfpu/utils/numberOfRoundingModes.h" #include "symfpu/utils/properties.h" -#endif -#ifdef CVC5_USE_SYMFPU namespace symfpu { using namespace ::cvc5::theory::fp::symfpuSymbolic; @@ -143,11 +140,6 @@ void probabilityAnnotation<traits, traits::prop>(const traits::prop &p, return; } }; -#endif - -#ifndef CVC5_USE_SYMFPU -#define SYMFPU_NUMBER_OF_ROUNDING_MODES 5 -#endif namespace cvc5 { namespace theory { @@ -242,11 +234,7 @@ symbolicProposition symbolicProposition::operator^( bool symbolicRoundingMode::checkNodeType(const TNode n) { -#ifdef CVC5_USE_SYMFPU return n.getType(false).isBitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES); -#else - return false; -#endif } symbolicRoundingMode::symbolicRoundingMode(const Node n) : nodeWrapper(n) @@ -254,7 +242,6 @@ symbolicRoundingMode::symbolicRoundingMode(const Node n) : nodeWrapper(n) Assert(checkNodeType(*this)); } -#ifdef CVC5_USE_SYMFPU symbolicRoundingMode::symbolicRoundingMode(const unsigned v) : nodeWrapper(NodeManager::currentNM()->mkConst( BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, v))) @@ -262,14 +249,6 @@ symbolicRoundingMode::symbolicRoundingMode(const unsigned v) Assert((v & (v - 1)) == 0 && v != 0); // Exactly one bit set Assert(checkNodeType(*this)); } -#else -symbolicRoundingMode::symbolicRoundingMode(const unsigned v) - : nodeWrapper(NodeManager::currentNM()->mkConst( - BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, v))) -{ - Unreachable(); -} -#endif symbolicRoundingMode::symbolicRoundingMode(const symbolicRoundingMode &old) : nodeWrapper(old) @@ -755,20 +734,17 @@ TypeNode floatingPointTypeInfo::getTypeNode(void) const FpConverter::FpConverter(context::UserContext* user) : d_additionalAssertions(user) -#ifdef CVC5_USE_SYMFPU , d_fpMap(user), d_rmMap(user), d_boolMap(user), d_ubvMap(user), d_sbvMap(user) -#endif { } FpConverter::~FpConverter() {} -#ifdef CVC5_USE_SYMFPU Node FpConverter::ufToNode(const fpt &format, const uf &u) const { NodeManager *nm = NodeManager::currentNM(); @@ -843,7 +819,6 @@ FpConverter::uf FpConverter::buildComponents(TNode current) return tmp; } -#endif // Non-convertible things should only be added to the stack at the very start, // thus... @@ -851,7 +826,6 @@ FpConverter::uf FpConverter::buildComponents(TNode current) Node FpConverter::convert(TNode node) { -#ifdef CVC5_USE_SYMFPU std::vector<TNode> workStack; TNode result = node; @@ -1704,9 +1678,6 @@ Node FpConverter::convert(TNode node) } return result; -#else - Unimplemented() << "Conversion is dependent on SymFPU"; -#endif } #undef CVC5_FPCONV_PASSTHROUGH @@ -1715,7 +1686,6 @@ Node FpConverter::getValue(Valuation &val, TNode var) { Assert(Theory::isLeafOf(var, THEORY_FP)); -#ifdef CVC5_USE_SYMFPU TypeNode t(var.getType()); Assert(t.isRoundingMode() || t.isFloatingPoint()) @@ -1735,9 +1705,6 @@ Node FpConverter::getValue(Valuation &val, TNode var) Assert(i != d_fpMap.end()) << "Asking for the value of an unregistered expression"; return ufToNode(fpt(t), (*i).second); -#else - Unimplemented() << "Conversion is dependent on SymFPU"; -#endif } } // namespace fp diff --git a/src/theory/fp/fp_converter.h b/src/theory/fp/fp_converter.h index f1b7c8a83..9900c2987 100644 --- a/src/theory/fp/fp_converter.h +++ b/src/theory/fp/fp_converter.h @@ -33,9 +33,7 @@ #include "util/floatingpoint_size.h" #include "util/hash.h" -#ifdef CVC5_USE_SYMFPU #include "symfpu/core/unpackedFloat.h" -#endif #ifdef CVC5_SYM_SYMBOLIC_EVAL // This allows debugging of the cvc5 symbolic back-end. @@ -120,9 +118,7 @@ class symbolicProposition : public nodeWrapper protected: bool checkNodeType(const TNode node); -#ifdef CVC5_USE_SYMFPU friend ::symfpu::ite<symbolicProposition, symbolicProposition>; // For ITE -#endif public: symbolicProposition(const Node n); @@ -141,9 +137,7 @@ class symbolicRoundingMode : public nodeWrapper protected: bool checkNodeType(const TNode n); -#ifdef CVC5_USE_SYMFPU friend ::symfpu::ite<symbolicProposition, symbolicRoundingMode>; // For ITE -#endif public: symbolicRoundingMode(const Node n); @@ -183,10 +177,8 @@ class symbolicBitVector : public nodeWrapper bool checkNodeType(const TNode n); friend symbolicBitVector<!isSigned>; // To allow conversion between the types -#ifdef CVC5_USE_SYMFPU friend ::symfpu::ite<symbolicProposition, symbolicBitVector<isSigned> >; // For ITE -#endif public: symbolicBitVector(const Node n); @@ -314,7 +306,6 @@ class FpConverter context::CDList<Node> d_additionalAssertions; protected: -#ifdef CVC5_USE_SYMFPU typedef symfpuSymbolic::traits traits; typedef ::symfpu::unpackedFloat<symfpuSymbolic::traits> uf; typedef symfpuSymbolic::traits::rm rm; @@ -348,7 +339,6 @@ class FpConverter /* Creates the relevant components for a variable */ uf buildComponents(TNode current); -#endif }; } // namespace fp diff --git a/src/theory/fp/theory_fp.cpp b/src/theory/fp/theory_fp.cpp index 3d81a2995..77dba0724 100644 --- a/src/theory/fp/theory_fp.cpp +++ b/src/theory/fp/theory_fp.cpp @@ -661,7 +661,7 @@ bool TheoryFp::isRegistered(TNode node) { void TheoryFp::preRegisterTerm(TNode node) { - if (Configuration::isBuiltWithSymFPU() && !options::fpExp()) + if (!options::fpExp()) { TypeNode tn = node.getType(); if (tn.isFloatingPoint()) diff --git a/src/theory/fp/theory_fp_rewriter.cpp b/src/theory/fp/theory_fp_rewriter.cpp index 76f7d55cf..8bc7900de 100644 --- a/src/theory/fp/theory_fp_rewriter.cpp +++ b/src/theory/fp/theory_fp_rewriter.cpp @@ -1026,12 +1026,10 @@ RewriteResponse maxTotal(TNode node, bool isPreRewrite) bool result; switch (k) { -#ifdef CVC5_USE_SYMFPU case kind::FLOATINGPOINT_COMPONENT_NAN: result = arg0.isNaN(); break; case kind::FLOATINGPOINT_COMPONENT_INF: result = arg0.isInfinite(); break; case kind::FLOATINGPOINT_COMPONENT_ZERO: result = arg0.isZero(); break; case kind::FLOATINGPOINT_COMPONENT_SIGN: result = arg0.getSign(); break; -#endif default: Unreachable() << "Unknown kind used in componentFlag"; break; } @@ -1050,11 +1048,7 @@ RewriteResponse maxTotal(TNode node, bool isPreRewrite) // \todo Add a proper interface for this sort of thing to FloatingPoint #1915 return RewriteResponse( REWRITE_DONE, -#ifdef CVC5_USE_SYMFPU NodeManager::currentNM()->mkConst((BitVector)arg0.getExponent()) -#else - node -#endif ); } @@ -1066,11 +1060,7 @@ RewriteResponse maxTotal(TNode node, bool isPreRewrite) return RewriteResponse( REWRITE_DONE, -#ifdef CVC5_USE_SYMFPU NodeManager::currentNM()->mkConst((BitVector)arg0.getSignificand()) -#else - node -#endif ); } @@ -1080,7 +1070,6 @@ RewriteResponse maxTotal(TNode node, bool isPreRewrite) BitVector value; -#ifdef CVC5_USE_SYMFPU /* \todo fix the numbering of rounding modes so this doesn't need * to call symfpu at all and remove the dependency on fp_converter.h #1915 */ RoundingMode arg0(node[0].getConst<RoundingMode>()); @@ -1110,9 +1099,6 @@ RewriteResponse maxTotal(TNode node, bool isPreRewrite) Unreachable() << "Unknown rounding mode in roundingModeBitBlast"; break; } -#else - value = BitVector(5U, 0U); -#endif return RewriteResponse(REWRITE_DONE, NodeManager::currentNM()->mkConst(value)); } diff --git a/src/theory/fp/theory_fp_type_rules.cpp b/src/theory/fp/theory_fp_type_rules.cpp index b78ef24c7..77c1ef8f0 100644 --- a/src/theory/fp/theory_fp_type_rules.cpp +++ b/src/theory/fp/theory_fp_type_rules.cpp @@ -727,7 +727,6 @@ TypeNode FloatingPointComponentExponent::computeType(NodeManager* nodeManager, } } -#ifdef CVC5_USE_SYMFPU /* Need to create some symfpu objects as the size of bit-vector * that is needed for this component is dependent on the encoding * used (i.e. whether subnormals are forcibly normalised or not). @@ -735,9 +734,6 @@ TypeNode FloatingPointComponentExponent::computeType(NodeManager* nodeManager, * back-end but it should't make a difference. */ FloatingPointSize fps = operandType.getConst<FloatingPointSize>(); uint32_t bw = FloatingPoint::getUnpackedExponentWidth(fps); -#else - uint32_t bw = 2; -#endif return nodeManager->mkBitVectorType(bw); } @@ -767,13 +763,9 @@ TypeNode FloatingPointComponentSignificand::computeType( } } -#ifdef CVC5_USE_SYMFPU /* As before we need to use some of sympfu. */ FloatingPointSize fps = operandType.getConst<FloatingPointSize>(); uint32_t bw = FloatingPoint::getUnpackedSignificandWidth(fps); -#else - uint32_t bw = 1; -#endif return nodeManager->mkBitVectorType(bw); } diff --git a/src/theory/inference_id.cpp b/src/theory/inference_id.cpp index fe4ed4c22..778c842a6 100644 --- a/src/theory/inference_id.cpp +++ b/src/theory/inference_id.cpp @@ -75,6 +75,10 @@ const char* toString(InferenceId i) return "ARITH_NL_IAND_SUM_REFINE"; case InferenceId::ARITH_NL_IAND_BITWISE_REFINE: return "ARITH_NL_IAND_BITWISE_REFINE"; + case InferenceId::ARITH_NL_POW2_INIT_REFINE: + return "ARITH_NL_POW2_INIT_REFINE"; + case InferenceId::ARITH_NL_POW2_VALUE_REFINE: + return "ARITH_NL_POW2_VALUE_REFINE"; case InferenceId::ARITH_NL_CAD_CONFLICT: return "ARITH_NL_CAD_CONFLICT"; case InferenceId::ARITH_NL_CAD_EXCLUDED_INTERVAL: return "ARITH_NL_CAD_EXCLUDED_INTERVAL"; diff --git a/src/theory/inference_id.h b/src/theory/inference_id.h index 169992f41..6a87776d6 100644 --- a/src/theory/inference_id.h +++ b/src/theory/inference_id.h @@ -126,6 +126,11 @@ enum class InferenceId ARITH_NL_IAND_SUM_REFINE, // bitwise refinements (IAndSolver::checkFullRefine) ARITH_NL_IAND_BITWISE_REFINE, + //-------------------- nonlinear pow2 solver + // initial refinements (Pow2Solver::checkInitialRefine) + ARITH_NL_POW2_INIT_REFINE, + // value refinements (Pow2Solver::checkFullRefine) + ARITH_NL_POW2_VALUE_REFINE, //-------------------- nonlinear cad solver // conflict / infeasible subset obtained from cad ARITH_NL_CAD_CONFLICT, diff --git a/src/theory/logic_info.cpp b/src/theory/logic_info.cpp index 8ba43aa1a..d53b06151 100644 --- a/src/theory/logic_info.cpp +++ b/src/theory/logic_info.cpp @@ -44,10 +44,6 @@ LogicInfo::LogicInfo() { for (TheoryId id = THEORY_FIRST; id < THEORY_LAST; ++id) { - if (id == THEORY_FP && !Configuration::isBuiltWithSymFPU()) - { - continue; - } enableTheory(id); } } diff --git a/src/theory/quantifiers/fmf/full_model_check.cpp b/src/theory/quantifiers/fmf/full_model_check.cpp index 808db7aec..c6f38f298 100644 --- a/src/theory/quantifiers/fmf/full_model_check.cpp +++ b/src/theory/quantifiers/fmf/full_model_check.cpp @@ -941,8 +941,9 @@ void FullModelChecker::doCheck(FirstOrderModelFmc * fm, Node f, Def & d, Node n else if( n.getNumChildren()==0 ){ Node r = n; if( !n.isConst() ){ - if( !fm->hasTerm(n) ){ - r = getSomeDomainElement(fm, n.getType() ); + TypeNode tn = n.getType(); + if( !fm->hasTerm(n) && tn.isFirstClass() ){ + r = getSomeDomainElement(fm, tn ); } r = fm->getRepresentative( r ); } diff --git a/src/theory/quantifiers/instantiate.cpp b/src/theory/quantifiers/instantiate.cpp index 71f4028ec..0f82d8301 100644 --- a/src/theory/quantifiers/instantiate.cpp +++ b/src/theory/quantifiers/instantiate.cpp @@ -16,6 +16,7 @@ #include "theory/quantifiers/instantiate.h" #include "expr/node_algorithm.h" +#include "options/base_options.h" #include "options/printer_options.h" #include "options/quantifiers_options.h" #include "options/smt_options.h" diff --git a/src/theory/quantifiers/term_registry.cpp b/src/theory/quantifiers/term_registry.cpp index 5b7bd1552..31e5240df 100644 --- a/src/theory/quantifiers/term_registry.cpp +++ b/src/theory/quantifiers/term_registry.cpp @@ -15,6 +15,7 @@ #include "theory/quantifiers/term_registry.h" +#include "options/base_options.h" #include "options/quantifiers_options.h" #include "options/smt_options.h" #include "theory/quantifiers/first_order_model.h" diff --git a/src/theory/sep/theory_sep.cpp b/src/theory/sep/theory_sep.cpp index 6d1b9955a..efede77ba 100644 --- a/src/theory/sep/theory_sep.cpp +++ b/src/theory/sep/theory_sep.cpp @@ -95,6 +95,7 @@ bool TheorySep::needsEqualityEngine(EeSetupInfo& esi) { esi.d_notify = &d_notify; esi.d_name = "theory::sep::ee"; + esi.d_notifyMerge = true; return true; } diff --git a/src/theory/sets/theory_sets.cpp b/src/theory/sets/theory_sets.cpp index 4cca76057..439e9443d 100644 --- a/src/theory/sets/theory_sets.cpp +++ b/src/theory/sets/theory_sets.cpp @@ -60,6 +60,9 @@ bool TheorySets::needsEqualityEngine(EeSetupInfo& esi) { esi.d_notify = &d_notify; esi.d_name = "theory::sets::ee"; + esi.d_notifyNewClass = true; + esi.d_notifyMerge = true; + esi.d_notifyDisequal = true; return true; } diff --git a/src/theory/strings/regexp_entail.cpp b/src/theory/strings/regexp_entail.cpp index 3d4a2d143..be1646403 100644 --- a/src/theory/strings/regexp_entail.cpp +++ b/src/theory/strings/regexp_entail.cpp @@ -364,6 +364,10 @@ bool RegExpEntail::isConstRegExp(TNode t) } } } + else if (ck == ITE) + { + return false; + } else if (cur.isVar()) { return false; diff --git a/src/theory/strings/term_registry.cpp b/src/theory/strings/term_registry.cpp index aac9e9313..8c5805b37 100644 --- a/src/theory/strings/term_registry.cpp +++ b/src/theory/strings/term_registry.cpp @@ -249,7 +249,8 @@ void TermRegistry::preRegisterTerm(TNode n) // Concatenation terms do not need to be considered here because // their arguments have string type and do not introduce any shared // terms. - if (n.hasOperator() && ee->isFunctionKind(k) && k != STRING_CONCAT) + if (n.hasOperator() && ee->isFunctionKind(k) + && kindToTheoryId(k) == THEORY_STRINGS && k != STRING_CONCAT) { d_functionsTerms.push_back(n); } diff --git a/src/theory/strings/theory_strings.cpp b/src/theory/strings/theory_strings.cpp index f4daed85d..f0763e153 100644 --- a/src/theory/strings/theory_strings.cpp +++ b/src/theory/strings/theory_strings.cpp @@ -103,6 +103,9 @@ bool TheoryStrings::needsEqualityEngine(EeSetupInfo& esi) { esi.d_notify = &d_notify; esi.d_name = "theory::strings::ee"; + esi.d_notifyNewClass = true; + esi.d_notifyMerge = true; + esi.d_notifyDisequal = true; return true; } diff --git a/src/theory/theory.cpp b/src/theory/theory.cpp index d6ad4cd41..b9dc1ba42 100644 --- a/src/theory/theory.cpp +++ b/src/theory/theory.cpp @@ -330,12 +330,18 @@ bool Theory::isLegalElimination(TNode x, TNode val) { return false; } - if (!options::produceModels()) + if (!options::produceModels() && !d_logicInfo.isQuantified()) { - // don't care about the model, we are fine + // Don't care about the model and logic is not quantified, we can eliminate. return true; } - // if there is a model object + // If models are enabled, then it depends on whether the term contains any + // unevaluable operators like FORALL, SINE, etc. Having such operators makes + // model construction contain non-constant values for variables, which is + // not ideal from a user perspective. + // We also insist on this check since the term to eliminate should never + // contain quantifiers, or else variable shadowing issues may arise. + // there should be a model object TheoryModel* tm = d_valuation.getModel(); Assert(tm != nullptr); return tm->isLegalElimination(x, val); diff --git a/src/theory/theory_model.cpp b/src/theory/theory_model.cpp index 8eec7f911..3e902463c 100644 --- a/src/theory/theory_model.cpp +++ b/src/theory/theory_model.cpp @@ -142,8 +142,22 @@ Node TheoryModel::getValue(TNode n) const Debug("model-getvalue-debug") << "[model-getvalue] getValue : substitute " << n << " to " << nn << std::endl; //get value in model nn = getModelValue(nn); - if (nn.isNull()) return nn; - if(options::condenseFunctionValues() || nn.getKind() != kind::LAMBDA) { + if (nn.isNull()) + { + return nn; + } + else if (nn.getKind() == kind::LAMBDA) + { + if (options::condenseFunctionValues()) + { + // normalize the body. Do not normalize the entire node, which + // involves array normalization. + NodeManager* nm = NodeManager::currentNM(); + nn = nm->mkNode(kind::LAMBDA, nn[0], Rewriter::rewrite(nn[1])); + } + } + else + { //normalize nn = Rewriter::rewrite(nn); } diff --git a/src/theory/uf/equality_engine.cpp b/src/theory/uf/equality_engine.cpp index 8885abe6b..338076e78 100644 --- a/src/theory/uf/equality_engine.cpp +++ b/src/theory/uf/equality_engine.cpp @@ -88,10 +88,6 @@ void EqualityEngine::init() { d_triggerDatabaseAllocatedSize = 100000; d_triggerDatabase = (char*) malloc(d_triggerDatabaseAllocatedSize); - //We can't notify during the initialization because it notifies - // QuantifiersEngine.AddTermToDatabase that try to access to the uf - // instantiator that currently doesn't exist. - ScopedBool sb(d_performNotify, false); addTermInternal(d_true); addTermInternal(d_false); @@ -111,7 +107,6 @@ EqualityEngine::EqualityEngine(context::Context* context, d_masterEqualityEngine(0), d_context(context), d_done(context, false), - d_performNotify(true), d_notify(s_notifyNone), d_applicationLookupsCount(context, 0), d_nodesCount(context, 0), @@ -141,7 +136,6 @@ EqualityEngine::EqualityEngine(EqualityEngineNotify& notify, d_masterEqualityEngine(0), d_context(context), d_done(context, false), - d_performNotify(true), d_notify(notify), d_applicationLookupsCount(context, 0), d_nodesCount(context, 0), @@ -381,10 +375,7 @@ void EqualityEngine::addTermInternal(TNode t, bool isOperator) { { // Notify e.g. the theory that owns this equality engine that there is a // new equivalence class. - if (d_performNotify) - { - d_notify.eqNotifyNewClass(t); - } + d_notify.eqNotifyNewClass(t); if (d_constantsAreTriggers && d_isConstant[result]) { // Non-Boolean constants are trigger terms for all tags @@ -506,9 +497,7 @@ bool EqualityEngine::assertEquality(TNode eq, } // notify the theory - if (d_performNotify) { - d_notify.eqNotifyDisequal(eq[0], eq[1], reason); - } + d_notify.eqNotifyDisequal(eq[0], eq[1], reason); Debug("equality::trigger") << d_name << "::eq::addEquality(" << eq << "," << (polarity ? "true" : "false") << ")" << std::endl; @@ -608,7 +597,7 @@ bool EqualityEngine::merge(EqualityNode& class1, EqualityNode& class2, std::vect // Determine if we should notify the owner of this class of this merge. // The second part of this check is needed due to the internal implementation // of this class. It ensures that we are merging terms and not operators. - if (d_performNotify && class1Id == cc1.getFind() && class2Id == cc2.getFind()) + if (class1Id == cc1.getFind() && class2Id == cc2.getFind()) { doNotify = true; } @@ -797,11 +786,11 @@ bool EqualityEngine::merge(EqualityNode& class1, EqualityNode& class2, std::vect EqualityNodeId tag1id = newSetTriggers[newSetTriggersSize++] = class1triggers.d_triggers[i1++]; // since they are both tagged notify of merge - if (d_performNotify) { - EqualityNodeId tag2id = class2triggers.d_triggers[i2++]; - if (!d_notify.eqNotifyTriggerTermEquality(tag1, d_nodes[tag1id], d_nodes[tag2id], true)) { - return false; - } + EqualityNodeId tag2id = class2triggers.d_triggers[i2++]; + if (!d_notify.eqNotifyTriggerTermEquality( + tag1, d_nodes[tag1id], d_nodes[tag2id], true)) + { + return false; } // Next tags tag1 = TheoryIdSetUtil::setPop(tags1); @@ -1934,9 +1923,8 @@ void EqualityEngine::propagate() { d_assertedEqualities.push_back(Equality(null_id, null_id)); d_assertedEqualitiesCount = d_assertedEqualitiesCount + 1; // Notify - if (d_performNotify) { - d_notify.eqNotifyConstantTermMerge(d_nodes[t1classId], d_nodes[t2classId]); - } + d_notify.eqNotifyConstantTermMerge(d_nodes[t1classId], + d_nodes[t2classId]); // Empty the queue and exit continue; } @@ -1995,7 +1983,8 @@ void EqualityEngine::propagate() { } // Notify the triggers - if (d_performNotify && !d_done) { + if (!d_done) + { for (size_t trigger_i = 0, trigger_end = triggers.size(); trigger_i < trigger_end && !d_done; ++ trigger_i) { const TriggerInfo& triggerInfo = d_equalityTriggersOriginal[triggers[trigger_i]]; if (triggerInfo.d_trigger.getKind() == kind::EQUAL) @@ -2217,12 +2206,16 @@ void EqualityEngine::addTriggerTerm(TNode t, TheoryId tag) TriggerTermSetRef triggerSetRef = d_nodeIndividualTrigger[classId]; if (triggerSetRef != +null_set_id && getTriggerTermSet(triggerSetRef).hasTrigger(tag)) { // If the term already is in the equivalence class that a tagged representative, just notify - if (d_performNotify) { - EqualityNodeId triggerId = getTriggerTermSet(triggerSetRef).getTrigger(tag); - Debug("equality::trigger") << d_name << "::eq::addTriggerTerm(" << t << ", " << tag << "): already have this trigger in class with " << d_nodes[triggerId] << std::endl; - if (eqNodeId != triggerId && !d_notify.eqNotifyTriggerTermEquality(tag, t, d_nodes[triggerId], true)) { - d_done = true; - } + EqualityNodeId triggerId = getTriggerTermSet(triggerSetRef).getTrigger(tag); + Debug("equality::trigger") + << d_name << "::eq::addTriggerTerm(" << t << ", " << tag + << "): already have this trigger in class with " << d_nodes[triggerId] + << std::endl; + if (eqNodeId != triggerId + && !d_notify.eqNotifyTriggerTermEquality( + tag, t, d_nodes[triggerId], true)) + { + d_done = true; } } else { @@ -2602,10 +2595,10 @@ bool EqualityEngine::propagateTriggerTermDisequalities( // Store the propagation storePropagatedDisequality(currentTag, myRep, tagRep); // Notify - if (d_performNotify) { - if (!d_notify.eqNotifyTriggerTermEquality(currentTag, d_nodes[myRep], d_nodes[tagRep], false)) { - d_done = true; - } + if (!d_notify.eqNotifyTriggerTermEquality( + currentTag, d_nodes[myRep], d_nodes[tagRep], false)) + { + d_done = true; } } } diff --git a/src/theory/uf/equality_engine.h b/src/theory/uf/equality_engine.h index 024774593..c0e7b3478 100644 --- a/src/theory/uf/equality_engine.h +++ b/src/theory/uf/equality_engine.h @@ -120,9 +120,6 @@ private: /** If we are done, we don't except any new assertions */ context::CDO<bool> d_done; - /** Whether to notify or not (temporarily disabled on equality checks) */ - bool d_performNotify; - /** The class to notify when a representative changes for a term */ EqualityEngineNotify& d_notify; diff --git a/src/theory/uf/theory_uf.cpp b/src/theory/uf/theory_uf.cpp index 36b05b145..f1adde143 100644 --- a/src/theory/uf/theory_uf.cpp +++ b/src/theory/uf/theory_uf.cpp @@ -73,6 +73,14 @@ bool TheoryUF::needsEqualityEngine(EeSetupInfo& esi) { esi.d_notify = &d_notify; esi.d_name = d_instanceName + "theory::uf::ee"; + if (options::finiteModelFind() + && options::ufssMode() != options::UfssMode::NONE) + { + // need notifications about sorts + esi.d_notifyNewClass = true; + esi.d_notifyMerge = true; + esi.d_notifyDisequal = true; + } return true; } diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 2938ddcca..71742dfce 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -13,9 +13,6 @@ # The build system configuration. ## -configure_file(floatingpoint_literal_symfpu.h.in floatingpoint_literal_symfpu.h) -configure_file(floatingpoint_literal_symfpu_traits.h.in - floatingpoint_literal_symfpu_traits.h) configure_file(rational.h.in rational.h) configure_file(integer.h.in integer.h) configure_file(real_algebraic_number.h.in real_algebraic_number.h) diff --git a/src/util/floatingpoint_literal_symfpu.cpp b/src/util/floatingpoint_literal_symfpu.cpp index c2c3fe77b..dc3dce6b9 100644 --- a/src/util/floatingpoint_literal_symfpu.cpp +++ b/src/util/floatingpoint_literal_symfpu.cpp @@ -16,7 +16,6 @@ #include "base/check.h" -#ifdef CVC5_USE_SYMFPU #include "symfpu/core/add.h" #include "symfpu/core/classify.h" #include "symfpu/core/compare.h" @@ -31,11 +30,9 @@ #include "symfpu/core/sqrt.h" #include "symfpu/utils/numberOfRoundingModes.h" #include "symfpu/utils/properties.h" -#endif /* -------------------------------------------------------------------------- */ -#ifdef CVC5_USE_SYMFPU namespace symfpu { #define CVC5_LIT_ITE_DFN(T) \ @@ -57,7 +54,6 @@ CVC5_LIT_ITE_DFN(::cvc5::symfpuLiteral::traits::ubv); #undef CVC5_LIT_ITE_DFN } // namespace symfpu -#endif /* -------------------------------------------------------------------------- */ @@ -65,44 +61,30 @@ namespace cvc5 { uint32_t FloatingPointLiteral::getUnpackedExponentWidth(FloatingPointSize& size) { -#ifdef CVC5_USE_SYMFPU return SymFPUUnpackedFloatLiteral::exponentWidth(size); -#else - unimplemented(); - return 2; -#endif } uint32_t FloatingPointLiteral::getUnpackedSignificandWidth( FloatingPointSize& size) { -#ifdef CVC5_USE_SYMFPU return SymFPUUnpackedFloatLiteral::significandWidth(size); -#else - unimplemented(); - return 2; -#endif } FloatingPointLiteral::FloatingPointLiteral(uint32_t exp_size, uint32_t sig_size, const BitVector& bv) : d_fp_size(exp_size, sig_size) -#ifdef CVC5_USE_SYMFPU , d_symuf(symfpu::unpack<symfpuLiteral::traits>( symfpuLiteral::Cvc5FPSize(exp_size, sig_size), bv)) -#endif { } FloatingPointLiteral::FloatingPointLiteral( const FloatingPointSize& size, FloatingPointLiteral::SpecialConstKind kind) : d_fp_size(size) -#ifdef CVC5_USE_SYMFPU , d_symuf(SymFPUUnpackedFloatLiteral::makeNaN(size)) -#endif { Assert(kind == FloatingPointLiteral::SpecialConstKind::FPNAN); } @@ -112,12 +94,10 @@ FloatingPointLiteral::FloatingPointLiteral( FloatingPointLiteral::SpecialConstKind kind, bool sign) : d_fp_size(size) -#ifdef CVC5_USE_SYMFPU , d_symuf(kind == FloatingPointLiteral::SpecialConstKind::FPINF ? SymFPUUnpackedFloatLiteral::makeInf(size, sign) : SymFPUUnpackedFloatLiteral::makeZero(size, sign)) -#endif { Assert(kind == FloatingPointLiteral::SpecialConstKind::FPINF || kind == FloatingPointLiteral::SpecialConstKind::FPZERO); @@ -126,10 +106,8 @@ FloatingPointLiteral::FloatingPointLiteral( FloatingPointLiteral::FloatingPointLiteral(const FloatingPointSize& size, const BitVector& bv) : d_fp_size(size) -#ifdef CVC5_USE_SYMFPU , d_symuf(symfpu::unpack<symfpuLiteral::traits>(size, bv)) -#endif { } @@ -138,7 +116,6 @@ FloatingPointLiteral::FloatingPointLiteral(const FloatingPointSize& size, const BitVector& bv, bool signedBV) : d_fp_size(size) -#ifdef CVC5_USE_SYMFPU , d_symuf(signedBV ? symfpu::convertSBVToFloat<symfpuLiteral::traits>( symfpuLiteral::Cvc5FPSize(size), @@ -148,97 +125,61 @@ FloatingPointLiteral::FloatingPointLiteral(const FloatingPointSize& size, symfpuLiteral::Cvc5FPSize(size), symfpuLiteral::Cvc5RM(rm), symfpuLiteral::Cvc5UnsignedBitVector(bv))) -#endif { } BitVector FloatingPointLiteral::pack(void) const { -#ifdef CVC5_USE_SYMFPU BitVector bv(symfpu::pack<symfpuLiteral::traits>(d_fp_size, d_symuf)); -#else - unimplemented(); - BitVector bv(4u, 0u); -#endif return bv; } FloatingPointLiteral FloatingPointLiteral::absolute(void) const { -#ifdef CVC5_USE_SYMFPU return FloatingPointLiteral( d_fp_size, symfpu::absolute<symfpuLiteral::traits>(d_fp_size, d_symuf)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::negate(void) const { -#ifdef CVC5_USE_SYMFPU return FloatingPointLiteral( d_fp_size, symfpu::negate<symfpuLiteral::traits>(d_fp_size, d_symuf)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::add( const RoundingMode& rm, const FloatingPointLiteral& arg) const { -#ifdef CVC5_USE_SYMFPU Assert(d_fp_size == arg.d_fp_size); return FloatingPointLiteral(d_fp_size, symfpu::add<symfpuLiteral::traits>( d_fp_size, rm, d_symuf, arg.d_symuf, true)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::sub( const RoundingMode& rm, const FloatingPointLiteral& arg) const { -#ifdef CVC5_USE_SYMFPU Assert(d_fp_size == arg.d_fp_size); return FloatingPointLiteral(d_fp_size, symfpu::add<symfpuLiteral::traits>( d_fp_size, rm, d_symuf, arg.d_symuf, false)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::mult( const RoundingMode& rm, const FloatingPointLiteral& arg) const { -#ifdef CVC5_USE_SYMFPU Assert(d_fp_size == arg.d_fp_size); return FloatingPointLiteral(d_fp_size, symfpu::multiply<symfpuLiteral::traits>( d_fp_size, rm, d_symuf, arg.d_symuf)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::div( const RoundingMode& rm, const FloatingPointLiteral& arg) const { -#ifdef CVC5_USE_SYMFPU Assert(d_fp_size == arg.d_fp_size); return FloatingPointLiteral(d_fp_size, symfpu::divide<symfpuLiteral::traits>( d_fp_size, rm, d_symuf, arg.d_symuf)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::fma( @@ -246,276 +187,150 @@ FloatingPointLiteral FloatingPointLiteral::fma( const FloatingPointLiteral& arg1, const FloatingPointLiteral& arg2) const { -#ifdef CVC5_USE_SYMFPU Assert(d_fp_size == arg1.d_fp_size); Assert(d_fp_size == arg2.d_fp_size); return FloatingPointLiteral( d_fp_size, symfpu::fma<symfpuLiteral::traits>( d_fp_size, rm, d_symuf, arg1.d_symuf, arg2.d_symuf)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::sqrt(const RoundingMode& rm) const { -#ifdef CVC5_USE_SYMFPU return FloatingPointLiteral( d_fp_size, symfpu::sqrt<symfpuLiteral::traits>(d_fp_size, rm, d_symuf)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::rti(const RoundingMode& rm) const { -#ifdef CVC5_USE_SYMFPU return FloatingPointLiteral( d_fp_size, symfpu::roundToIntegral<symfpuLiteral::traits>(d_fp_size, rm, d_symuf)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::rem( const FloatingPointLiteral& arg) const { -#ifdef CVC5_USE_SYMFPU Assert(d_fp_size == arg.d_fp_size); return FloatingPointLiteral(d_fp_size, symfpu::remainder<symfpuLiteral::traits>( d_fp_size, d_symuf, arg.d_symuf)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::maxTotal( const FloatingPointLiteral& arg, bool zeroCaseLeft) const { -#ifdef CVC5_USE_SYMFPU Assert(d_fp_size == arg.d_fp_size); return FloatingPointLiteral( d_fp_size, symfpu::max<symfpuLiteral::traits>( d_fp_size, d_symuf, arg.d_symuf, zeroCaseLeft)); -#else - unimplemented(); - return *this; -#endif } FloatingPointLiteral FloatingPointLiteral::minTotal( const FloatingPointLiteral& arg, bool zeroCaseLeft) const { -#ifdef CVC5_USE_SYMFPU Assert(d_fp_size == arg.d_fp_size); return FloatingPointLiteral( d_fp_size, symfpu::min<symfpuLiteral::traits>( d_fp_size, d_symuf, arg.d_symuf, zeroCaseLeft)); -#else - unimplemented(); - return *this; -#endif } bool FloatingPointLiteral::operator==(const FloatingPointLiteral& fp) const { -#ifdef CVC5_USE_SYMFPU return ((d_fp_size == fp.d_fp_size) && symfpu::smtlibEqual<symfpuLiteral::traits>( d_fp_size, d_symuf, fp.d_symuf)); -#else - unimplemented(); - return ((d_fp_size == fp.d_fp_size)); -#endif } bool FloatingPointLiteral::operator<=(const FloatingPointLiteral& arg) const { -#ifdef CVC5_USE_SYMFPU Assert(d_fp_size == arg.d_fp_size); return symfpu::lessThanOrEqual<symfpuLiteral::traits>( d_fp_size, d_symuf, arg.d_symuf); -#else - unimplemented(); - return false; -#endif } bool FloatingPointLiteral::operator<(const FloatingPointLiteral& arg) const { -#ifdef CVC5_USE_SYMFPU Assert(d_fp_size == arg.d_fp_size); return symfpu::lessThan<symfpuLiteral::traits>( d_fp_size, d_symuf, arg.d_symuf); -#else - unimplemented(); - return false; -#endif } BitVector FloatingPointLiteral::getExponent() const { -#ifdef CVC5_USE_SYMFPU return d_symuf.exponent; -#else - unimplemented(); - Unreachable() << "no concrete implementation of FloatingPointLiteral"; - return BitVector(); -#endif } BitVector FloatingPointLiteral::getSignificand() const { -#ifdef CVC5_USE_SYMFPU return d_symuf.significand; -#else - unimplemented(); - Unreachable() << "no concrete implementation of FloatingPointLiteral"; - return BitVector(); -#endif } bool FloatingPointLiteral::getSign() const { -#ifdef CVC5_USE_SYMFPU return d_symuf.sign; -#else - unimplemented(); - Unreachable() << "no concrete implementation of FloatingPointLiteral"; - return false; -#endif } bool FloatingPointLiteral::isNormal(void) const { -#ifdef CVC5_USE_SYMFPU return symfpu::isNormal<symfpuLiteral::traits>(d_fp_size, d_symuf); -#else - unimplemented(); - return false; -#endif } bool FloatingPointLiteral::isSubnormal(void) const { -#ifdef CVC5_USE_SYMFPU return symfpu::isSubnormal<symfpuLiteral::traits>(d_fp_size, d_symuf); -#else - unimplemented(); - return false; -#endif } bool FloatingPointLiteral::isZero(void) const { -#ifdef CVC5_USE_SYMFPU return symfpu::isZero<symfpuLiteral::traits>(d_fp_size, d_symuf); -#else - unimplemented(); - return false; -#endif } bool FloatingPointLiteral::isInfinite(void) const { -#ifdef CVC5_USE_SYMFPU return symfpu::isInfinite<symfpuLiteral::traits>(d_fp_size, d_symuf); -#else - unimplemented(); - return false; -#endif } bool FloatingPointLiteral::isNaN(void) const { -#ifdef CVC5_USE_SYMFPU return symfpu::isNaN<symfpuLiteral::traits>(d_fp_size, d_symuf); -#else - unimplemented(); - return false; -#endif } bool FloatingPointLiteral::isNegative(void) const { -#ifdef CVC5_USE_SYMFPU return symfpu::isNegative<symfpuLiteral::traits>(d_fp_size, d_symuf); -#else - unimplemented(); - return false; -#endif } bool FloatingPointLiteral::isPositive(void) const { -#ifdef CVC5_USE_SYMFPU return symfpu::isPositive<symfpuLiteral::traits>(d_fp_size, d_symuf); -#else - unimplemented(); - return false; -#endif } FloatingPointLiteral FloatingPointLiteral::convert( const FloatingPointSize& target, const RoundingMode& rm) const { -#ifdef CVC5_USE_SYMFPU return FloatingPointLiteral( target, symfpu::convertFloatToFloat<symfpuLiteral::traits>( d_fp_size, target, rm, d_symuf)); -#else - unimplemented(); - return *this; -#endif } BitVector FloatingPointLiteral::convertToSBVTotal(BitVectorSize width, const RoundingMode& rm, BitVector undefinedCase) const { -#ifdef CVC5_USE_SYMFPU return symfpu::convertFloatToSBV<symfpuLiteral::traits>( d_fp_size, rm, d_symuf, width, undefinedCase); -#else - unimplemented(); - return undefinedCase; -#endif } BitVector FloatingPointLiteral::convertToUBVTotal(BitVectorSize width, const RoundingMode& rm, BitVector undefinedCase) const { -#ifdef CVC5_USE_SYMFPU return symfpu::convertFloatToUBV<symfpuLiteral::traits>( d_fp_size, rm, d_symuf, width, undefinedCase); -#else - unimplemented(); - return undefinedCase; -#endif } -#ifndef CVC5_USE_SYMFPU -void FloatingPointLiteral::unimplemented(void) -{ - Unimplemented() << "no concrete implementation of FloatingPointLiteral"; -} - -size_t FloatingPointLiteral::hash(void) const -{ - unimplemented(); - return 23; -} -#endif - } // namespace cvc5 diff --git a/src/util/floatingpoint_literal_symfpu.h.in b/src/util/floatingpoint_literal_symfpu.h index 54827a308..5b2b0f7c8 100644 --- a/src/util/floatingpoint_literal_symfpu.h.in +++ b/src/util/floatingpoint_literal_symfpu.h @@ -20,20 +20,16 @@ #define CVC5__UTIL__FLOATINGPOINT_LITERAL_SYMFPU_H #include "util/bitvector.h" -#include "util/floatingpoint_size.h" #include "util/floatingpoint_literal_symfpu_traits.h" +#include "util/floatingpoint_size.h" #include "util/roundingmode.h" /* -------------------------------------------------------------------------- */ namespace cvc5 { -// clang-format off -#if @CVC5_USE_SYMFPU@ -// clang-format on using SymFPUUnpackedFloatLiteral = ::symfpu::unpackedFloat<symfpuLiteral::traits>; -#endif class FloatingPointLiteral { @@ -65,13 +61,6 @@ class FloatingPointLiteral */ static uint32_t getUnpackedSignificandWidth(FloatingPointSize& size); -// clang-format off -#if !@CVC5_USE_SYMFPU@ - // clang-format on - /** Catch-all for unimplemented functions. */ - static void unimplemented(void); -#endif - /** Constructors. */ /** Create a FP literal from its IEEE bit-vector representation. */ @@ -197,18 +186,10 @@ class FloatingPointLiteral BitVector convertToUBVTotal(BitVectorSize width, const RoundingMode& rm, BitVector undefinedCase) const; -// clang-format off -#if @CVC5_USE_SYMFPU@ - // clang-format on /** Return wrapped floating-point literal. */ const SymFPUUnpackedFloatLiteral& getSymUF() const { return d_symuf; } -#else - /** Dummy hash function. */ - size_t hash(void) const; -#endif private: - /** * Create a FP literal from unpacked representation. * @@ -223,34 +204,19 @@ class FloatingPointLiteral const bool sign, const BitVector& exp, const BitVector& sig) - : d_fp_size(size) -// clang-format off -#if @CVC5_USE_SYMFPU@ - // clang-format on - , - d_symuf(SymFPUUnpackedFloatLiteral(sign, exp, sig)) -#endif + : d_fp_size(size), d_symuf(SymFPUUnpackedFloatLiteral(sign, exp, sig)) { } -// clang-format off -#if @CVC5_USE_SYMFPU@ - // clang-format on - /** Create a FP literal from a symFPU unpacked float. */ FloatingPointLiteral(const FloatingPointSize& size, SymFPUUnpackedFloatLiteral symuf) : d_fp_size(size), d_symuf(symuf){}; -#endif /** The floating-point size of this floating-point literal. */ FloatingPointSize d_fp_size; -// clang-format off -#if @CVC5_USE_SYMFPU@ - // clang-format on /** The actual floating-point value, a SymFPU unpackedFloat. */ SymFPUUnpackedFloatLiteral d_symuf; -#endif }; /* -------------------------------------------------------------------------- */ diff --git a/src/util/floatingpoint_literal_symfpu_traits.cpp b/src/util/floatingpoint_literal_symfpu_traits.cpp index 071b69912..0f46708b0 100644 --- a/src/util/floatingpoint_literal_symfpu_traits.cpp +++ b/src/util/floatingpoint_literal_symfpu_traits.cpp @@ -13,8 +13,6 @@ * SymFPU glue code for floating-point values. */ -#if CVC5_USE_SYMFPU - #include "util/floatingpoint_literal_symfpu_traits.h" #include "base/check.h" @@ -413,4 +411,3 @@ void traits::invariant(const traits::prop& p) } } // namespace symfpuLiteral } // namespace cvc5 -#endif diff --git a/src/util/floatingpoint_literal_symfpu_traits.h.in b/src/util/floatingpoint_literal_symfpu_traits.h index 76d2f47e2..bc5caaf88 100644 --- a/src/util/floatingpoint_literal_symfpu_traits.h.in +++ b/src/util/floatingpoint_literal_symfpu_traits.h @@ -25,16 +25,12 @@ #ifndef CVC5__UTIL__FLOATINGPOINT_LITERAL_SYMFPU_TRAITS_H #define CVC5__UTIL__FLOATINGPOINT_LITERAL_SYMFPU_TRAITS_H -// clang-format off -#if @CVC5_USE_SYMFPU@ -// clang-format on +#include <symfpu/core/unpackedFloat.h> #include "util/bitvector.h" #include "util/floatingpoint_size.h" #include "util/roundingmode.h" -#include <symfpu/core/unpackedFloat.h> - /* -------------------------------------------------------------------------- */ namespace cvc5 { @@ -258,7 +254,6 @@ class wrappedBitVector : public BitVector Cvc5BitWidth lower) const; }; } // namespace symfpuLiteral -} +} // namespace cvc5 #endif -#endif diff --git a/src/util/resource_manager.cpp b/src/util/resource_manager.cpp index f0cc78789..c4a94dfa2 100644 --- a/src/util/resource_manager.cpp +++ b/src/util/resource_manager.cpp @@ -22,9 +22,9 @@ #include "base/check.h" #include "base/listener.h" #include "base/output.h" +#include "options/base_options.h" #include "options/option_exception.h" #include "options/options.h" -#include "options/resource_manager_options.h" #include "util/statistics_registry.h" using namespace std; @@ -164,7 +164,7 @@ ResourceManager::ResourceManager(StatisticsRegistry& stats, d_infidWeights.fill(1); d_resourceWeights.fill(1); - for (const auto& opt : d_options.resman.resourceWeightHolder) + for (const auto& opt : d_options.base.resourceWeightHolder) { std::string name; uint64_t weight; @@ -189,9 +189,9 @@ uint64_t ResourceManager::getTimeUsage() const { return d_cumulativeTimeUsed; } uint64_t ResourceManager::getResourceRemaining() const { - if (d_options.resman.cumulativeResourceLimit <= d_cumulativeResourceUsed) + if (d_options.base.cumulativeResourceLimit <= d_cumulativeResourceUsed) return 0; - return d_options.resman.cumulativeResourceLimit - d_cumulativeResourceUsed; + return d_options.base.cumulativeResourceLimit - d_cumulativeResourceUsed; } void ResourceManager::spendResource(uint64_t amount) @@ -237,21 +237,21 @@ void ResourceManager::spendResource(theory::InferenceId iid) void ResourceManager::beginCall() { - d_perCallTimer.set(d_options.resman.perCallMillisecondLimit); + d_perCallTimer.set(d_options.base.perCallMillisecondLimit); d_thisCallResourceUsed = 0; - if (d_options.resman.cumulativeResourceLimit > 0) + if (d_options.base.cumulativeResourceLimit > 0) { // Compute remaining cumulative resource budget d_thisCallResourceBudget = - d_options.resman.cumulativeResourceLimit - d_cumulativeResourceUsed; + d_options.base.cumulativeResourceLimit - d_cumulativeResourceUsed; } - if (d_options.resman.perCallResourceLimit > 0) + if (d_options.base.perCallResourceLimit > 0) { // Check if per-call resource budget is even smaller - if (d_options.resman.perCallResourceLimit < d_thisCallResourceBudget) + if (d_options.base.perCallResourceLimit < d_thisCallResourceBudget) { - d_thisCallResourceBudget = d_options.resman.perCallResourceLimit; + d_thisCallResourceBudget = d_options.base.perCallResourceLimit; } } } @@ -265,25 +265,25 @@ void ResourceManager::endCall() bool ResourceManager::limitOn() const { - return (d_options.resman.cumulativeResourceLimit > 0) - || (d_options.resman.perCallMillisecondLimit > 0) - || (d_options.resman.perCallResourceLimit > 0); + return (d_options.base.cumulativeResourceLimit > 0) + || (d_options.base.perCallMillisecondLimit > 0) + || (d_options.base.perCallResourceLimit > 0); } bool ResourceManager::outOfResources() const { - if (d_options.resman.perCallResourceLimit > 0) + if (d_options.base.perCallResourceLimit > 0) { // Check if per-call resources are exhausted - if (d_thisCallResourceUsed >= d_options.resman.perCallResourceLimit) + if (d_thisCallResourceUsed >= d_options.base.perCallResourceLimit) { return true; } } - if (d_options.resman.cumulativeResourceLimit > 0) + if (d_options.base.cumulativeResourceLimit > 0) { // Check if cumulative resources are exhausted - if (d_cumulativeResourceUsed >= d_options.resman.cumulativeResourceLimit) + if (d_cumulativeResourceUsed >= d_options.base.cumulativeResourceLimit) { return true; } @@ -293,7 +293,7 @@ bool ResourceManager::outOfResources() const bool ResourceManager::outOfTime() const { - if (d_options.resman.perCallMillisecondLimit == 0) return false; + if (d_options.base.perCallMillisecondLimit == 0) return false; return d_perCallTimer.expired(); } diff --git a/test/api/CMakeLists.txt b/test/api/CMakeLists.txt index e9fd47261..4811cca1b 100644 --- a/test/api/CMakeLists.txt +++ b/test/api/CMakeLists.txt @@ -51,6 +51,7 @@ cvc5_add_api_test(smt2_compliance) cvc5_add_api_test(two_solvers) cvc5_add_api_test(issue5074) cvc5_add_api_test(issue4889) +cvc5_add_api_test(issue6111) # if we've built using libedit, then we want the interactive shell tests if (USE_EDITLINE) diff --git a/test/api/issue4889.cpp b/test/api/issue4889.cpp index f84d99f42..8e0853682 100644 --- a/test/api/issue4889.cpp +++ b/test/api/issue4889.cpp @@ -19,7 +19,6 @@ using namespace cvc5::api; int main() { -#ifdef CVC5_USE_SYMFPU Solver slv; Sort sort_int = slv.getIntegerSort(); Sort sort_array = slv.mkArraySort(sort_int, sort_int); @@ -33,6 +32,5 @@ int main() Term rem = slv.mkTerm(FLOATINGPOINT_REM, ite, const1); Term isnan = slv.mkTerm(FLOATINGPOINT_ISNAN, rem); slv.checkSatAssuming(isnan); -#endif return 0; } diff --git a/test/api/issue6111.cpp b/test/api/issue6111.cpp new file mode 100644 index 000000000..bd7be2ad0 --- /dev/null +++ b/test/api/issue6111.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * Top contributors (to current version): + * Mathias Preiner + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * Test for issue #6111 + * + */ +#include <iostream> +#include <vector> + +#include "api/cpp/cvc5.h" + +using namespace cvc5::api; +using namespace std; + +int main() +{ + Solver solver; + solver.setLogic("QF_BV"); + Sort bvsort12979 = solver.mkBitVectorSort(12979); + Term input2_1 = solver.mkConst(bvsort12979, "intpu2_1"); + Term zero = solver.mkBitVector(bvsort12979.getBVSize(), "0", 10); + + vector<Term> args1; + args1.push_back(zero); + args1.push_back(input2_1); + Term bvult_res = solver.mkTerm(BITVECTOR_ULT, args1); + solver.assertFormula(bvult_res); + + Sort bvsort4 = solver.mkBitVectorSort(4); + Term concat_result_42 = solver.mkConst(bvsort4, "concat_result_42"); + Sort bvsort8 = solver.mkBitVectorSort(8); + Term concat_result_43 = solver.mkConst(bvsort8, "concat_result_43"); + + vector<Term> args2; + args2.push_back(concat_result_42); + args2.push_back( + solver.mkTerm(solver.mkOp(BITVECTOR_EXTRACT, 7, 4), {concat_result_43})); + solver.assertFormula(solver.mkTerm(EQUAL, args2)); + + vector<Term> args3; + args3.push_back(concat_result_42); + args3.push_back( + solver.mkTerm(solver.mkOp(BITVECTOR_EXTRACT, 3, 0), {concat_result_43})); + solver.assertFormula(solver.mkTerm(EQUAL, args3)); + + cout << solver.checkSat() << endl; + + return 0; +} diff --git a/test/api/smt2_compliance.cpp b/test/api/smt2_compliance.cpp index 9794888b2..ee58b7ad4 100644 --- a/test/api/smt2_compliance.cpp +++ b/test/api/smt2_compliance.cpp @@ -18,6 +18,7 @@ #include <sstream> #include "api/cpp/cvc5.h" +#include "options/base_options.h" #include "options/options.h" #include "options/options_public.h" #include "options/set_language.h" @@ -35,8 +36,8 @@ void testGetInfo(api::Solver* solver, const char* s); int main() { Options opts; - options::setInputLanguage(language::input::LANG_SMTLIB_V2, opts); - options::setOutputLanguage(language::output::LANG_SMTLIB_V2, opts); + opts.base.inputLanguage = language::input::LANG_SMTLIB_V2; + opts.base.outputLanguage = language::output::LANG_SMTLIB_V2; cout << language::SetLanguage(language::output::LANG_SMTLIB_V2); diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index 54134b510..5b681ca36 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -33,3 +33,5 @@ cvc5_add_python_api_test(pytest_term unit/api/test_term.py) cvc5_add_python_api_test(pytest_datatype_api unit/api/test_datatype_api.py) cvc5_add_python_api_test(pytest_grammar unit/api/test_grammar.py) cvc5_add_python_api_test(pytest_to_python_obj unit/api/test_to_python_obj.py) +cvc5_add_python_api_test(pytest_op unit/api/test_op.py) +cvc5_add_python_api_test(pytest_result unit/api/test_result.py) diff --git a/test/python/unit/api/test_op.py b/test/python/unit/api/test_op.py new file mode 100644 index 000000000..07a57a5c6 --- /dev/null +++ b/test/python/unit/api/test_op.py @@ -0,0 +1,178 @@ +############################################################################### +# Top contributors (to current version): +# Yoni Zohar +# +# This file is part of the cvc5 project. +# +# Copyright (c) 2009-2021 by the authors listed in the file AUTHORS +# in the top-level source directory and their institutional affiliations. +# All rights reserved. See the file COPYING in the top-level source +# directory for licensing information. +# ############################################################################# +# +# Unit tests for op API. +# +# Obtained by translating test/unit/api/op_black.cpp +## + +import pytest +import pycvc5 +from pycvc5 import kinds +from pycvc5 import Sort +from pycvc5 import Op + + +@pytest.fixture +def solver(): + return pycvc5.Solver() + + +def test_get_kind(solver): + x = solver.mkOp(kinds.BVExtract, 31, 1) + x.getKind() + + +def test_is_null(solver): + x = Op(solver) + assert x.isNull() + x = solver.mkOp(kinds.BVExtract, 31, 1) + assert not x.isNull() + + +def test_op_from_kind(solver): + solver.mkOp(kinds.Plus) + with pytest.raises(RuntimeError): + solver.mkOp(kinds.BVExtract) + + +def test_get_num_indices(solver): + plus = solver.mkOp(kinds.Plus) + divisible = solver.mkOp(kinds.Divisible, 4) + bitvector_repeat = solver.mkOp(kinds.BVRepeat, 5) + bitvector_zero_extend = solver.mkOp(kinds.BVZeroExtend, 6) + bitvector_sign_extend = solver.mkOp(kinds.BVSignExtend, 7) + bitvector_rotate_left = solver.mkOp(kinds.BVRotateLeft, 8) + bitvector_rotate_right = solver.mkOp(kinds.BVRotateRight, 9) + int_to_bitvector = solver.mkOp(kinds.IntToBV, 10) + iand = solver.mkOp(kinds.Iand, 3) + floatingpoint_to_ubv = solver.mkOp(kinds.FPToUbv, 11) + floatingopint_to_sbv = solver.mkOp(kinds.FPToSbv, 13) + floatingpoint_to_fp_ieee_bitvector = solver.mkOp(kinds.FPToFpIeeeBV, 4, 25) + floatingpoint_to_fp_floatingpoint = solver.mkOp(kinds.FPToFpFP, 4, 25) + floatingpoint_to_fp_real = solver.mkOp(kinds.FPToFpReal, 4, 25) + floatingpoint_to_fp_signed_bitvector = solver.mkOp(kinds.FPToFpSignedBV, 4, + 25) + floatingpoint_to_fp_unsigned_bitvector = solver.mkOp( + kinds.FPToFpUnsignedBV, 4, 25) + floatingpoint_to_fp_generic = solver.mkOp(kinds.FPToFpGeneric, 4, 25) + regexp_loop = solver.mkOp(kinds.RegexpLoop, 2, 3) + + assert 0 == plus.getNumIndices() + assert 1 == divisible.getNumIndices() + assert 1 == bitvector_repeat.getNumIndices() + assert 1 == bitvector_zero_extend.getNumIndices() + assert 1 == bitvector_sign_extend.getNumIndices() + assert 1 == bitvector_rotate_left.getNumIndices() + assert 1 == bitvector_rotate_right.getNumIndices() + assert 1 == int_to_bitvector.getNumIndices() + assert 1 == iand.getNumIndices() + assert 1 == floatingpoint_to_ubv.getNumIndices() + assert 1 == floatingopint_to_sbv.getNumIndices() + assert 2 == floatingpoint_to_fp_ieee_bitvector.getNumIndices() + assert 2 == floatingpoint_to_fp_floatingpoint.getNumIndices() + assert 2 == floatingpoint_to_fp_real.getNumIndices() + assert 2 == floatingpoint_to_fp_signed_bitvector.getNumIndices() + assert 2 == floatingpoint_to_fp_unsigned_bitvector.getNumIndices() + assert 2 == floatingpoint_to_fp_generic.getNumIndices() + assert 2 == regexp_loop.getNumIndices() + + +def test_get_indices_string(solver): + x = Op(solver) + with pytest.raises(RuntimeError): + x.getIndices() + + divisible_ot = solver.mkOp(kinds.Divisible, 4) + assert divisible_ot.isIndexed() + divisible_idx = divisible_ot.getIndices() + assert divisible_idx == "4" + + +def test_get_indices_uint(solver): + bitvector_repeat_ot = solver.mkOp(kinds.BVRepeat, 5) + assert bitvector_repeat_ot.isIndexed() + bitvector_repeat_idx = bitvector_repeat_ot.getIndices() + assert bitvector_repeat_idx == 5 + + bitvector_zero_extend_ot = solver.mkOp(kinds.BVZeroExtend, 6) + bitvector_zero_extend_idx = bitvector_zero_extend_ot.getIndices() + assert bitvector_zero_extend_idx == 6 + + bitvector_sign_extend_ot = solver.mkOp(kinds.BVSignExtend, 7) + bitvector_sign_extend_idx = bitvector_sign_extend_ot.getIndices() + assert bitvector_sign_extend_idx == 7 + + bitvector_rotate_left_ot = solver.mkOp(kinds.BVRotateLeft, 8) + bitvector_rotate_left_idx = bitvector_rotate_left_ot.getIndices() + assert bitvector_rotate_left_idx == 8 + + bitvector_rotate_right_ot = solver.mkOp(kinds.BVRotateRight, 9) + bitvector_rotate_right_idx = bitvector_rotate_right_ot.getIndices() + assert bitvector_rotate_right_idx == 9 + + int_to_bitvector_ot = solver.mkOp(kinds.IntToBV, 10) + int_to_bitvector_idx = int_to_bitvector_ot.getIndices() + assert int_to_bitvector_idx == 10 + + floatingpoint_to_ubv_ot = solver.mkOp(kinds.FPToUbv, 11) + floatingpoint_to_ubv_idx = floatingpoint_to_ubv_ot.getIndices() + assert floatingpoint_to_ubv_idx == 11 + + floatingpoint_to_sbv_ot = solver.mkOp(kinds.FPToSbv, 13) + floatingpoint_to_sbv_idx = floatingpoint_to_sbv_ot.getIndices() + assert floatingpoint_to_sbv_idx == 13 + + +def test_get_indices_pair_uint(solver): + bitvector_extract_ot = solver.mkOp(kinds.BVExtract, 4, 0) + assert bitvector_extract_ot.isIndexed() + bitvector_extract_indices = bitvector_extract_ot.getIndices() + assert bitvector_extract_indices == (4, 0) + + floatingpoint_to_fp_ieee_bitvector_ot = solver.mkOp( + kinds.FPToFpIeeeBV, 4, 25) + floatingpoint_to_fp_ieee_bitvector_indices = floatingpoint_to_fp_ieee_bitvector_ot.getIndices( + ) + assert floatingpoint_to_fp_ieee_bitvector_indices == (4, 25) + + floatingpoint_to_fp_floatingpoint_ot = solver.mkOp(kinds.FPToFpFP, 4, 25) + floatingpoint_to_fp_floatingpoint_indices = floatingpoint_to_fp_floatingpoint_ot.getIndices( + ) + assert floatingpoint_to_fp_floatingpoint_indices == (4, 25) + + floatingpoint_to_fp_real_ot = solver.mkOp(kinds.FPToFpReal, 4, 25) + floatingpoint_to_fp_real_indices = floatingpoint_to_fp_real_ot.getIndices() + assert floatingpoint_to_fp_real_indices == (4, 25) + + floatingpoint_to_fp_signed_bitvector_ot = solver.mkOp( + kinds.FPToFpSignedBV, 4, 25) + floatingpoint_to_fp_signed_bitvector_indices = floatingpoint_to_fp_signed_bitvector_ot.getIndices( + ) + assert floatingpoint_to_fp_signed_bitvector_indices == (4, 25) + + floatingpoint_to_fp_unsigned_bitvector_ot = solver.mkOp( + kinds.FPToFpUnsignedBV, 4, 25) + floatingpoint_to_fp_unsigned_bitvector_indices = floatingpoint_to_fp_unsigned_bitvector_ot.getIndices( + ) + assert floatingpoint_to_fp_unsigned_bitvector_indices == (4, 25) + + floatingpoint_to_fp_generic_ot = solver.mkOp(kinds.FPToFpGeneric, 4, 25) + floatingpoint_to_fp_generic_indices = floatingpoint_to_fp_generic_ot.getIndices( + ) + assert floatingpoint_to_fp_generic_indices == (4, 25) + + +def test_op_scoping_to_string(solver): + bitvector_repeat_ot = solver.mkOp(kinds.BVRepeat, 5) + op_repr = str(bitvector_repeat_ot) + assert str(bitvector_repeat_ot) == op_repr diff --git a/test/python/unit/api/test_result.py b/test/python/unit/api/test_result.py new file mode 100644 index 000000000..bd97646f9 --- /dev/null +++ b/test/python/unit/api/test_result.py @@ -0,0 +1,115 @@ +############################################################################### +# Top contributors (to current version): +# Yoni Zohar +# +# This file is part of the cvc5 project. +# +# Copyright (c) 2009-2021 by the authors listed in the file AUTHORS +# in the top-level source directory and their institutional affiliations. +# All rights reserved. See the file COPYING in the top-level source +# directory for licensing information. +# ############################################################################# +# +# Unit tests for result API. +# +# Obtained by translating test/unit/api/result_black.cpp +## + +import pytest +import pycvc5 +from pycvc5 import kinds +from pycvc5 import Result +from pycvc5 import UnknownExplanation + + +@pytest.fixture +def solver(): + return pycvc5.Solver() + + +def test_is_null(solver): + res_null = Result(solver) + assert res_null.isNull() + assert not res_null.isSat() + assert not res_null.isUnsat() + assert not res_null.isSatUnknown() + assert not res_null.isEntailed() + assert not res_null.isNotEntailed() + assert not res_null.isEntailmentUnknown() + u_sort = solver.mkUninterpretedSort("u") + x = solver.mkVar(u_sort, "x") + solver.assertFormula(x.eqTerm(x)) + res = solver.checkSat() + assert not res.isNull() + + +def test_eq(solver): + u_sort = solver.mkUninterpretedSort("u") + x = solver.mkVar(u_sort, "x") + solver.assertFormula(x.eqTerm(x)) + res2 = solver.checkSat() + res3 = solver.checkSat() + res = res2 + assert res == res2 + assert res3 == res2 + + +def test_is_sat(solver): + u_sort = solver.mkUninterpretedSort("u") + x = solver.mkVar(u_sort, "x") + solver.assertFormula(x.eqTerm(x)) + res = solver.checkSat() + assert res.isSat() + assert not res.isSatUnknown() + + +def test_is_unsat(solver): + u_sort = solver.mkUninterpretedSort("u") + x = solver.mkVar(u_sort, "x") + solver.assertFormula(x.eqTerm(x).notTerm()) + res = solver.checkSat() + assert res.isUnsat() + assert not res.isSatUnknown() + + +def test_is_sat_unknown(solver): + solver.setLogic("QF_NIA") + solver.setOption("incremental", "false") + solver.setOption("solve-int-as-bv", "32") + int_sort = solver.getIntegerSort() + x = solver.mkVar(int_sort, "x") + solver.assertFormula(x.eqTerm(x).notTerm()) + res = solver.checkSat() + assert not res.isSat() + assert res.isSatUnknown() + + +def test_is_entailed(solver): + solver.setOption("incremental", "true") + u_sort = solver.mkUninterpretedSort("u") + x = solver.mkConst(u_sort, "x") + y = solver.mkConst(u_sort, "y") + a = x.eqTerm(y).notTerm() + b = x.eqTerm(y) + solver.assertFormula(a) + entailed = solver.checkEntailed(a) + assert entailed.isEntailed() + assert not entailed.isEntailmentUnknown() + not_entailed = solver.checkEntailed(b) + assert not_entailed.isNotEntailed() + assert not not_entailed.isEntailmentUnknown() + + +def test_is_entailment_unknown(solver): + solver.setLogic("QF_NIA") + solver.setOption("incremental", "false") + solver.setOption("solve-int-as-bv", "32") + int_sort = solver.getIntegerSort() + x = solver.mkVar(int_sort, "x") + solver.assertFormula(x.eqTerm(x).notTerm()) + res = solver.checkEntailed(x.eqTerm(x)) + assert not res.isEntailed() + assert res.isEntailmentUnknown() + print(type(pycvc5.RoundTowardZero)) + print(type(pycvc5.UnknownReason)) + assert res.getUnknownExplanation() == pycvc5.UnknownReason diff --git a/test/python/unit/api/test_solver.py b/test/python/unit/api/test_solver.py index 44ce684dd..8b3ce944e 100644 --- a/test/python/unit/api/test_solver.py +++ b/test/python/unit/api/test_solver.py @@ -32,11 +32,7 @@ def test_recoverable_exception(solver): def test_supports_floating_point(solver): - if solver.supportsFloatingPoint(): - solver.mkRoundingMode(pycvc5.RoundNearestTiesToEven) - else: - with pytest.raises(RuntimeError): - solver.mkRoundingMode(pycvc5.RoundNearestTiesToEven) + solver.mkRoundingMode(pycvc5.RoundNearestTiesToEven) def test_get_boolean_sort(solver): @@ -47,6 +43,10 @@ def test_get_integer_sort(solver): solver.getIntegerSort() +def test_get_null_sort(solver): + solver.getNullSort() + + def test_get_real_sort(solver): solver.getRealSort() @@ -60,11 +60,7 @@ def test_get_string_sort(solver): def test_get_rounding_mode_sort(solver): - if solver.supportsFloatingPoint(): - solver.getRoundingModeSort() - else: - with pytest.raises(RuntimeError): - solver.getRoundingModeSort() + solver.getRoundingModeSort() def test_mk_array_sort(solver): @@ -79,10 +75,9 @@ def test_mk_array_sort(solver): solver.mkArraySort(boolSort, intSort) solver.mkArraySort(realSort, bvSort) - if (solver.supportsFloatingPoint()): - fpSort = solver.mkFloatingPointSort(3, 5) - solver.mkArraySort(fpSort, fpSort) - solver.mkArraySort(bvSort, fpSort) + fpSort = solver.mkFloatingPointSort(3, 5) + solver.mkArraySort(fpSort, fpSort) + solver.mkArraySort(bvSort, fpSort) slv = pycvc5.Solver() with pytest.raises(RuntimeError): @@ -96,15 +91,11 @@ def test_mk_bit_vector_sort(solver): def test_mk_floating_point_sort(solver): - if solver.supportsFloatingPoint(): - solver.mkFloatingPointSort(4, 8) - with pytest.raises(RuntimeError): - solver.mkFloatingPointSort(0, 8) - with pytest.raises(RuntimeError): - solver.mkFloatingPointSort(4, 0) - else: - with pytest.raises(RuntimeError): - solver.mkFloatingPointSort(4, 8) + solver.mkFloatingPointSort(4, 8) + with pytest.raises(RuntimeError): + solver.mkFloatingPointSort(0, 8) + with pytest.raises(RuntimeError): + solver.mkFloatingPointSort(4, 0) def test_mk_datatype_sort(solver): @@ -257,6 +248,15 @@ def test_mk_set_sort(solver): slv.mkSetSort(solver.mkBitVectorSort(4)) +def test_mk_bag_sort(solver): + solver.mkBagSort(solver.getBooleanSort()) + solver.mkBagSort(solver.getIntegerSort()) + solver.mkBagSort(solver.mkBitVectorSort(4)) + slv = pycvc5.Solver() + with pytest.raises(RuntimeError): + slv.mkBagSort(solver.mkBitVectorSort(4)) + + def test_mk_sequence_sort(solver): solver.mkSequenceSort(solver.getBooleanSort()) solver.mkSequenceSort(\ @@ -290,6 +290,42 @@ def test_mk_tuple_sort(solver): slv.mkTupleSort([solver.getIntegerSort()]) +def test_mk_bit_vector(solver): + size0 = 0 + size1 = 8 + size2 = 32 + val1 = 2 + val2 = 2 + solver.mkBitVector(size1, val1) + solver.mkBitVector(size2, val2) + solver.mkBitVector("1010", 2) + solver.mkBitVector("1010", 10) + solver.mkBitVector("1234", 10) + solver.mkBitVector("1010", 16) + solver.mkBitVector("a09f", 16) + solver.mkBitVector(8, "-127", 10) + with pytest.raises(RuntimeError): + solver.mkBitVector(size0, val1) + with pytest.raises(RuntimeError): + solver.mkBitVector(size0, val2) + with pytest.raises(RuntimeError): + solver.mkBitVector("", 2) + with pytest.raises(RuntimeError): + solver.mkBitVector("10", 3) + with pytest.raises(RuntimeError): + solver.mkBitVector("20", 2) + with pytest.raises(RuntimeError): + solver.mkBitVector(8, "101010101", 2) + with pytest.raises(RuntimeError): + solver.mkBitVector(8, "-256", 10) + assert solver.mkBitVector("1010", 2) == solver.mkBitVector("10", 10) + assert solver.mkBitVector("1010", 2) == solver.mkBitVector("a", 16) + assert str(solver.mkBitVector(8, "01010101", 2)) == "#b01010101" + assert str(solver.mkBitVector(8, "F", 16)) == "#b00001111" + assert solver.mkBitVector(8, "-1", 10) ==\ + solver.mkBitVector(8, "FF", 16) + + def test_mk_var(solver): boolSort = solver.getBooleanSort() intSort = solver.getIntegerSort() @@ -313,11 +349,7 @@ def test_mk_boolean(solver): def test_mk_rounding_mode(solver): - if solver.supportsFloatingPoint(): - solver.mkRoundingMode(pycvc5.RoundTowardZero) - else: - with pytest.raises(RuntimeError): - solver.mkRoundingMode(pycvc5.RoundTowardZero) + solver.mkRoundingMode(pycvc5.RoundTowardZero) def test_mk_uninterpreted_const(solver): @@ -329,15 +361,31 @@ def test_mk_uninterpreted_const(solver): slv.mkUninterpretedConst(solver.getBooleanSort(), 1) +def test_mk_abstract_value(solver): + solver.mkAbstractValue("1") + with pytest.raises(ValueError): + solver.mkAbstractValue("0") + with pytest.raises(ValueError): + solver.mkAbstractValue("-1") + with pytest.raises(ValueError): + solver.mkAbstractValue("1.2") + with pytest.raises(ValueError): + solver.mkAbstractValue("1/2") + with pytest.raises(ValueError): + solver.mkAbstractValue("asdf") + + solver.mkAbstractValue(1) + with pytest.raises(ValueError): + solver.mkAbstractValue(-1) + with pytest.raises(ValueError): + solver.mkAbstractValue(0) + + def test_mk_floating_point(solver): t1 = solver.mkBitVector(8) t2 = solver.mkBitVector(4) t3 = solver.mkInteger(2) - if (solver.supportsFloatingPoint()): - solver.mkFloatingPoint(3, 5, t1) - else: - with pytest.raises(RuntimeError): - solver.mkFloatingPoint(3, 5, t1) + solver.mkFloatingPoint(3, 5, t1) with pytest.raises(RuntimeError): solver.mkFloatingPoint(0, 5, pycvc5.Term(solver)) @@ -350,10 +398,9 @@ def test_mk_floating_point(solver): with pytest.raises(RuntimeError): solver.mkFloatingPoint(3, 5, t2) - if (solver.supportsFloatingPoint()): - slv = pycvc5.Solver() - with pytest.raises(RuntimeError): - slv.mkFloatingPoint(3, 5, t1) + slv = pycvc5.Solver() + with pytest.raises(RuntimeError): + slv.mkFloatingPoint(3, 5, t1) def test_mk_empty_set(solver): @@ -367,6 +414,17 @@ def test_mk_empty_set(solver): slv.mkEmptySet(s) +def test_mk_empty_bag(solver): + slv = pycvc5.Solver() + s = solver.mkBagSort(solver.getBooleanSort()) + solver.mkEmptyBag(pycvc5.Sort(solver)) + solver.mkEmptyBag(s) + with pytest.raises(RuntimeError): + solver.mkEmptyBag(solver.getBooleanSort()) + with pytest.raises(RuntimeError): + slv.mkEmptyBag(s) + + def test_mk_empty_sequence(solver): slv = pycvc5.Solver() s = solver.mkSequenceSort(solver.getBooleanSort()) @@ -382,43 +440,50 @@ def test_mk_false(solver): def test_mk_nan(solver): - if (solver.supportsFloatingPoint()): - solver.mkNaN(3, 5) - else: - with pytest.raises(RuntimeError): - solver.mkNaN(3, 5) + solver.mkNaN(3, 5) def test_mk_neg_zero(solver): - if (solver.supportsFloatingPoint()): - solver.mkNegZero(3, 5) - else: - with pytest.raises(RuntimeError): - solver.mkNegZero(3, 5) + solver.mkNegZero(3, 5) def test_mk_neg_inf(solver): - if (solver.supportsFloatingPoint()): - solver.mkNegInf(3, 5) - else: - with pytest.raises(RuntimeError): - solver.mkNegInf(3, 5) + solver.mkNegInf(3, 5) def test_mk_pos_inf(solver): - if (solver.supportsFloatingPoint()): - solver.mkPosInf(3, 5) - else: - with pytest.raises(RuntimeError): - solver.mkPosInf(3, 5) + solver.mkPosInf(3, 5) def test_mk_pos_zero(solver): - if (solver.supportsFloatingPoint()): - solver.mkPosZero(3, 5) - else: - with pytest.raises(RuntimeError): - solver.mkPosZero(3, 5) + solver.mkPosZero(3, 5) + + +def test_mk_op(solver): + # mkOp(Kind kind, Kind k) + with pytest.raises(ValueError): + solver.mkOp(kinds.BVExtract, kinds.Equal) + + # mkOp(Kind kind, const std::string& arg) + solver.mkOp(kinds.Divisible, "2147483648") + with pytest.raises(RuntimeError): + solver.mkOp(kinds.BVExtract, "asdf") + + # mkOp(Kind kind, uint32_t arg) + solver.mkOp(kinds.Divisible, 1) + solver.mkOp(kinds.BVRotateLeft, 1) + solver.mkOp(kinds.BVRotateRight, 1) + with pytest.raises(RuntimeError): + solver.mkOp(kinds.BVExtract, 1) + + # mkOp(Kind kind, uint32_t arg1, uint32_t arg2) + solver.mkOp(kinds.BVExtract, 1, 1) + with pytest.raises(RuntimeError): + solver.mkOp(kinds.Divisible, 1, 2) + + # mkOp(Kind kind, std::vector<uint32_t> args) + args = [1, 2, 2] + solver.mkOp(kinds.TupleProject, args) def test_mk_pi(solver): @@ -568,11 +633,210 @@ def test_mk_sep_nil(solver): slv.mkSepNil(solver.getIntegerSort()) +def test_mk_string(solver): + solver.mkString("") + solver.mkString("asdfasdf") + str(solver.mkString("asdf\\nasdf")) == "\"asdf\\u{5c}nasdf\"" + str(solver.mkString("asdf\\u{005c}nasdf", True)) ==\ + "\"asdf\\u{5c}nasdf\"" + + +def test_mk_term(solver): + bv32 = solver.mkBitVectorSort(32) + a = solver.mkConst(bv32, "a") + b = solver.mkConst(bv32, "b") + v1 = [a, b] + v2 = [a, pycvc5.Term(solver)] + v3 = [a, solver.mkTrue()] + v4 = [solver.mkInteger(1), solver.mkInteger(2)] + v5 = [solver.mkInteger(1), pycvc5.Term(solver)] + v6 = [] + slv = pycvc5.Solver() + + # mkTerm(Kind kind) const + solver.mkPi() + solver.mkTerm(kinds.RegexpEmpty) + solver.mkTerm(kinds.RegexpSigma) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.ConstBV) + + # mkTerm(Kind kind, Term child) const + solver.mkTerm(kinds.Not, solver.mkTrue()) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Not, pycvc5.Term(solver)) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Not, a) + with pytest.raises(RuntimeError): + slv.mkTerm(kinds.Not, solver.mkTrue()) + + # mkTerm(Kind kind, Term child1, Term child2) const + solver.mkTerm(kinds.Equal, a, b) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Equal, pycvc5.Term(solver), b) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Equal, a, pycvc5.Term(solver)) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Equal, a, solver.mkTrue()) + with pytest.raises(RuntimeError): + slv.mkTerm(kinds.Equal, a, b) + + # mkTerm(Kind kind, Term child1, Term child2, Term child3) const + solver.mkTerm(kinds.Ite, solver.mkTrue(), solver.mkTrue(), solver.mkTrue()) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Ite, pycvc5.Term(solver), solver.mkTrue(), + solver.mkTrue()) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Ite, solver.mkTrue(), pycvc5.Term(solver), + solver.mkTrue()) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Ite, solver.mkTrue(), solver.mkTrue(), + pycvc5.Term(solver)) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Ite, solver.mkTrue(), solver.mkTrue(), b) + with pytest.raises(RuntimeError): + slv.mkTerm(kinds.Ite, solver.mkTrue(), solver.mkTrue(), + solver.mkTrue()) + + # mkTerm(Kind kind, const std::vector<Term>& children) const + solver.mkTerm(kinds.Equal, v1) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Equal, v2) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Equal, v3) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.Distinct, v6) + + +def test_mk_term_from_op(solver): + bv32 = solver.mkBitVectorSort(32) + a = solver.mkConst(bv32, "a") + b = solver.mkConst(bv32, "b") + v1 = [solver.mkInteger(1), solver.mkInteger(2)] + v2 = [solver.mkInteger(1), pycvc5.Term(solver)] + v3 = [] + v4 = [solver.mkInteger(5)] + slv = pycvc5.Solver() + + # simple operator terms + opterm1 = solver.mkOp(kinds.BVExtract, 2, 1) + opterm2 = solver.mkOp(kinds.Divisible, 1) + + # list datatype + sort = solver.mkParamSort("T") + listDecl = solver.mkDatatypeDecl("paramlist", sort) + cons = solver.mkDatatypeConstructorDecl("cons") + nil = solver.mkDatatypeConstructorDecl("nil") + cons.addSelector("head", sort) + cons.addSelectorSelf("tail") + listDecl.addConstructor(cons) + listDecl.addConstructor(nil) + listSort = solver.mkDatatypeSort(listDecl) + intListSort =\ + listSort.instantiate([solver.getIntegerSort()]) + c = solver.mkConst(intListSort, "c") + lis = listSort.getDatatype() + + # list datatype constructor and selector operator terms + consTerm1 = lis.getConstructorTerm("cons") + consTerm2 = lis.getConstructor("cons").getConstructorTerm() + nilTerm1 = lis.getConstructorTerm("nil") + nilTerm2 = lis.getConstructor("nil").getConstructorTerm() + headTerm1 = lis["cons"].getSelectorTerm("head") + headTerm2 = lis["cons"].getSelector("head").getSelectorTerm() + tailTerm1 = lis["cons"].getSelectorTerm("tail") + tailTerm2 = lis["cons"]["tail"].getSelectorTerm() + + # mkTerm(Op op, Term term) const + solver.mkTerm(kinds.ApplyConstructor, nilTerm1) + solver.mkTerm(kinds.ApplyConstructor, nilTerm2) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.ApplySelector, nilTerm1) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.ApplySelector, consTerm1) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.ApplyConstructor, consTerm2) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm1) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.ApplySelector, headTerm1) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm1) + with pytest.raises(RuntimeError): + slv.mkTerm(kinds.ApplyConstructor, nilTerm1) + + # mkTerm(Op op, Term child) const + solver.mkTerm(opterm1, a) + solver.mkTerm(opterm2, solver.mkInteger(1)) + solver.mkTerm(kinds.ApplySelector, headTerm1, c) + solver.mkTerm(kinds.ApplySelector, tailTerm2, c) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm2, a) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm1, pycvc5.Term(solver)) + with pytest.raises(RuntimeError): + solver.mkTerm(kinds.ApplyConstructor, consTerm1, solver.mkInteger(0)) + with pytest.raises(RuntimeError): + slv.mkTerm(opterm1, a) + + # mkTerm(Op op, Term child1, Term child2) const + solver.mkTerm(kinds.ApplyConstructor, consTerm1, solver.mkInteger(0), + solver.mkTerm(kinds.ApplyConstructor, nilTerm1)) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm2, solver.mkInteger(1), solver.mkInteger(2)) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm1, a, b) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm2, solver.mkInteger(1), pycvc5.Term(solver)) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm2, pycvc5.Term(solver), solver.mkInteger(1)) + with pytest.raises(RuntimeError): + slv.mkTerm(kinds.ApplyConstructor,\ + consTerm1,\ + solver.mkInteger(0),\ + solver.mkTerm(kinds.ApplyConstructor, nilTerm1)) + + # mkTerm(Op op, Term child1, Term child2, Term child3) const + with pytest.raises(RuntimeError): + solver.mkTerm(opterm1, a, b, a) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm2, solver.mkInteger(1), solver.mkInteger(1), + pycvc5.Term(solver)) + + # mkTerm(Op op, const std::vector<Term>& children) const + solver.mkTerm(opterm2, v4) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm2, v1) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm2, v2) + with pytest.raises(RuntimeError): + solver.mkTerm(opterm2, v3) + with pytest.raises(RuntimeError): + slv.mkTerm(opterm2, v4) + + def test_mk_true(solver): solver.mkTrue() solver.mkTrue() +def test_mk_tuple(solver): + solver.mkTuple([solver.mkBitVectorSort(3)], [solver.mkBitVector("101", 2)]) + solver.mkTuple([solver.getRealSort()], [solver.mkInteger("5")]) + + with pytest.raises(RuntimeError): + solver.mkTuple([], [solver.mkBitVector("101", 2)]) + with pytest.raises(RuntimeError): + solver.mkTuple([solver.mkBitVectorSort(4)], + [solver.mkBitVector("101", 2)]) + with pytest.raises(RuntimeError): + solver.mkTuple([solver.getIntegerSort()], [solver.mkReal("5.3")]) + slv = pycvc5.Solver() + with pytest.raises(RuntimeError): + slv.mkTuple([solver.mkBitVectorSort(3)], [slv.mkBitVector("101", 2)]) + with pytest.raises(RuntimeError): + slv.mkTuple([slv.mkBitVectorSort(3)], [solver.mkBitVector("101", 2)]) + + def test_mk_universe_set(solver): solver.mkUniverseSet(solver.getBooleanSort()) with pytest.raises(RuntimeError): diff --git a/test/python/unit/api/test_sort.py b/test/python/unit/api/test_sort.py index 5e86382ee..def539cf4 100644 --- a/test/python/unit/api/test_sort.py +++ b/test/python/unit/api/test_sort.py @@ -89,9 +89,8 @@ def test_is_reg_exp(solver): def test_is_rounding_mode(solver): - if solver.supportsFloatingPoint(): - assert solver.getRoundingModeSort().isRoundingMode() - Sort(solver).isRoundingMode() + assert solver.getRoundingModeSort().isRoundingMode() + Sort(solver).isRoundingMode() def test_is_bit_vector(solver): @@ -100,9 +99,8 @@ def test_is_bit_vector(solver): def test_is_floating_point(solver): - if solver.supportsFloatingPoint(): - assert solver.mkFloatingPointSort(8, 24).isFloatingPoint() - Sort(solver).isFloatingPoint() + assert solver.mkFloatingPointSort(8, 24).isFloatingPoint() + Sort(solver).isFloatingPoint() def test_is_datatype(solver): @@ -447,21 +445,19 @@ def test_get_bv_size(solver): def test_get_fp_exponent_size(solver): - if solver.supportsFloatingPoint(): - fpSort = solver.mkFloatingPointSort(4, 8) - fpSort.getFPExponentSize() - setSort = solver.mkSetSort(solver.getIntegerSort()) - with pytest.raises(RuntimeError): - setSort.getFPExponentSize() + fpSort = solver.mkFloatingPointSort(4, 8) + fpSort.getFPExponentSize() + setSort = solver.mkSetSort(solver.getIntegerSort()) + with pytest.raises(RuntimeError): + setSort.getFPExponentSize() def test_get_fp_significand_size(solver): - if solver.supportsFloatingPoint(): - fpSort = solver.mkFloatingPointSort(4, 8) - fpSort.getFPSignificandSize() - setSort = solver.mkSetSort(solver.getIntegerSort()) - with pytest.raises(RuntimeError): - setSort.getFPSignificandSize() + fpSort = solver.mkFloatingPointSort(4, 8) + fpSort.getFPSignificandSize() + setSort = solver.mkSetSort(solver.getIntegerSort()) + with pytest.raises(RuntimeError): + setSort.getFPSignificandSize() def test_get_datatype_paramsorts(solver): diff --git a/test/regress/CMakeLists.txt b/test/regress/CMakeLists.txt index 9ad4f7e8a..6706ed4f6 100644 --- a/test/regress/CMakeLists.txt +++ b/test/regress/CMakeLists.txt @@ -670,6 +670,7 @@ set(regress_0_tests regress0/issue5743.smt2 regress0/issue5947.smt2 regress0/issue6605-2-abd-triv.smt2 + regress0/issue6741.smt2 regress0/ite_arith.smt2 regress0/ite_real_int_type.smtv1.smt2 regress0/ite_real_valid.smtv1.smt2 @@ -1589,6 +1590,7 @@ set(regress_1_tests regress1/fmf/issue4068-si-qf.smt2 regress1/fmf/issue4225-univ-fun.smt2 regress1/fmf/issue5738-dt-interp-finite.smt2 + regress1/fmf/issue6690-re-enum.smt2 regress1/fmf/issue916-fmf-or.smt2 regress1/fmf/jasmin-cdt-crash.smt2 regress1/fmf/loopy_coda.smt2 @@ -1612,13 +1614,10 @@ set(regress_1_tests regress1/ho/issue4065-no-rep.smt2 regress1/ho/issue4092-sinf.smt2 regress1/ho/issue4134-sinf.smt2 - regress1/ho/nested_lambdas-AGT034^2.smt2 - regress1/ho/nested_lambdas-sat-SYO056^1-delta.smt2 regress1/ho/NUM638^1.smt2 regress1/ho/NUM925^1.p regress1/ho/soundness_fmf_SYO362^5-delta.p regress1/ho/store-ax-min.p - regress1/ho/SYO056^1.p regress1/hole6.cvc regress1/ite5.smt2 regress1/issue3970-nl-ext-purify.smt2 @@ -1847,6 +1846,7 @@ set(regress_1_tests regress1/quantifiers/issue5658-qe.smt2 regress1/quantifiers/issue5766-wrong-sel-trigger.smt2 regress1/quantifiers/issue5899-qe.smt2 + regress1/quantifiers/issue6699-nc-shadow.smt2 regress1/quantifiers/issue993.smt2 regress1/quantifiers/javafe.ast.StmtVec.009.smt2 regress1/quantifiers/lia-witness-div-pp.smt2 @@ -2630,6 +2630,10 @@ set(regression_disabled_tests regress1/fmf/ko-bound-set.cvc # results in an assertion failure (see issue #1650). regress1/ho/hoa0102.smt2 + # after disallowing solving for terms with quantifiers + regress1/ho/nested_lambdas-AGT034^2.smt2 + regress1/ho/nested_lambdas-sat-SYO056^1-delta.smt2 + regress1/ho/SYO056^1.p # slow on some builds after changes to tangent planes regress1/nl/approx-sqrt-unsat.smt2 # times out after update to circuit propagator diff --git a/test/regress/README.md b/test/regress/README.md index efd79472b..ca6fc30ab 100644 --- a/test/regress/README.md +++ b/test/regress/README.md @@ -115,11 +115,11 @@ configurations. The `REQUIRES` directive can be used to only run a given benchmark when a feature is supported. For example: ``` -; REQUIRES: symfpu +; REQUIRES: cryptominisat ``` -This benchmark is only run when symfpu has been configured. Multiple +This benchmark is only run when CryptoMiniSat has been configured. Multiple `REQUIRES` directives are supported. For a list of features that can be listed as a requirement, refer to cvc5's `--show-config` output. Features can also be -excluded by adding the `no-` prefix, e.g. `no-symfpu` means that the test is -not valid for builds that include symfpu support. +excluded by adding the `no-` prefix, e.g. `no-cryptominisat` means that the +test is not valid for builds that include CryptoMiniSat support. diff --git a/test/regress/regress0/bv/eager-inc-cadical.smt2 b/test/regress/regress0/bv/eager-inc-cadical.smt2 index 01840dffa..34007f6aa 100644 --- a/test/regress/regress0/bv/eager-inc-cadical.smt2 +++ b/test/regress/regress0/bv/eager-inc-cadical.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: cadical ; COMMAND-LINE: --incremental --bv-sat-solver=cadical --bitblast=eager (set-logic QF_BV) (set-option :incremental true) diff --git a/test/regress/regress0/define-fun-model.smt2 b/test/regress/regress0/define-fun-model.smt2 index c6ca206fc..8f197cd04 100644 --- a/test/regress/regress0/define-fun-model.smt2 +++ b/test/regress/regress0/define-fun-model.smt2 @@ -1,8 +1,8 @@ -; SCRUBBER: sed -e 's/BOUND_VARIABLE_[0-9]*/BOUND_VARIABLE/' +; SCRUBBER: sed -e 's/BOUND_VARIABLE_[0-9]*/V/; s/_arg_[0-9]*/V/' ; EXPECT: sat ; EXPECT: (((f 4) 7)) -; EXPECT: ((g (lambda ((BOUND_VARIABLE Int)) 7))) -; EXPECT: ((f (lambda ((BOUND_VARIABLE Int)) 7))) +; EXPECT: ((g (lambda ((V Int)) 7))) +; EXPECT: ((f (lambda ((V Int)) 7))) (set-logic UFLIA) (set-option :produce-models true) (define-fun f ((x Int)) Int 7) diff --git a/test/regress/regress0/fp/abs-unsound.smt2 b/test/regress/regress0/fp/abs-unsound.smt2 index b5aa0452e..ae7117047 100644 --- a/test/regress/regress0/fp/abs-unsound.smt2 +++ b/test/regress/regress0/fp/abs-unsound.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --fp-exp ; EXPECT: sat (set-logic QF_FP) diff --git a/test/regress/regress0/fp/abs-unsound2.smt2 b/test/regress/regress0/fp/abs-unsound2.smt2 index ad603f8c9..3040f9ba9 100644 --- a/test/regress/regress0/fp/abs-unsound2.smt2 +++ b/test/regress/regress0/fp/abs-unsound2.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --fp-exp ; EXPECT: unsat (set-logic QF_FP) diff --git a/test/regress/regress0/fp/down-cast-RNA.smt2 b/test/regress/regress0/fp/down-cast-RNA.smt2 index dc99ff144..62314f284 100644 --- a/test/regress/regress0/fp/down-cast-RNA.smt2 +++ b/test/regress/regress0/fp/down-cast-RNA.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --fp-exp ; EXPECT: unsat diff --git a/test/regress/regress0/fp/ext-rew-test.smt2 b/test/regress/regress0/fp/ext-rew-test.smt2 index 726487e18..3fb3a9e53 100644 --- a/test/regress/regress0/fp/ext-rew-test.smt2 +++ b/test/regress/regress0/fp/ext-rew-test.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --ext-rew-prep --ext-rew-prep-agg ; EXPECT: unsat (set-info :smt-lib-version 2.6) diff --git a/test/regress/regress0/fp/from_sbv.smt2 b/test/regress/regress0/fp/from_sbv.smt2 index 3211339d6..226d6589c 100644 --- a/test/regress/regress0/fp/from_sbv.smt2 +++ b/test/regress/regress0/fp/from_sbv.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --fp-exp ; EXPECT: unsat (set-logic QF_BVFP) diff --git a/test/regress/regress0/fp/from_ubv.smt2 b/test/regress/regress0/fp/from_ubv.smt2 index c02f8d304..6939e478a 100644 --- a/test/regress/regress0/fp/from_ubv.smt2 +++ b/test/regress/regress0/fp/from_ubv.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; EXPECT: unsat (set-logic QF_FP) (declare-const r RoundingMode) diff --git a/test/regress/regress0/fp/issue-5524.smt2 b/test/regress/regress0/fp/issue-5524.smt2 index 8c361163c..741d77a19 100644 --- a/test/regress/regress0/fp/issue-5524.smt2 +++ b/test/regress/regress0/fp/issue-5524.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; EXPECT: unsat (set-logic QF_FP) (declare-fun fpv5 () Float32) diff --git a/test/regress/regress0/fp/issue3536.smt2 b/test/regress/regress0/fp/issue3536.smt2 index 68a17347e..6a58b371f 100644 --- a/test/regress/regress0/fp/issue3536.smt2 +++ b/test/regress/regress0/fp/issue3536.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: -q ; EXPECT: sat (set-logic QF_FP) diff --git a/test/regress/regress0/fp/issue3582.smt2 b/test/regress/regress0/fp/issue3582.smt2 index 2de76b680..c06cdb110 100644 --- a/test/regress/regress0/fp/issue3582.smt2 +++ b/test/regress/regress0/fp/issue3582.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; EXPECT: unsat (set-logic QF_FP) (declare-fun bv () (_ BitVec 1)) diff --git a/test/regress/regress0/fp/issue3619.smt2 b/test/regress/regress0/fp/issue3619.smt2 index 3e0858035..ab3c781bb 100644 --- a/test/regress/regress0/fp/issue3619.smt2 +++ b/test/regress/regress0/fp/issue3619.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: -q ; EXPECT: sat (set-logic QF_FPLRA) diff --git a/test/regress/regress0/fp/issue4277-assign-func.smt2 b/test/regress/regress0/fp/issue4277-assign-func.smt2 index c42bad235..d1fbc73d2 100644 --- a/test/regress/regress0/fp/issue4277-assign-func.smt2 +++ b/test/regress/regress0/fp/issue4277-assign-func.smt2 @@ -1,6 +1,5 @@ ; COMMAND-LINE: -q ; EXPECT: sat -; REQUIRES: symfpu (set-logic HO_ALL) (set-option :assign-function-values false) (set-info :status sat) diff --git a/test/regress/regress0/fp/issue5511.smt2 b/test/regress/regress0/fp/issue5511.smt2 index d4393486c..911db54ee 100644 --- a/test/regress/regress0/fp/issue5511.smt2 +++ b/test/regress/regress0/fp/issue5511.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; EXPECT: sat (set-logic QF_FP) (declare-fun a () (_ FloatingPoint 53 11)) diff --git a/test/regress/regress0/fp/issue5734.smt2 b/test/regress/regress0/fp/issue5734.smt2 index 2ad9ac921..d66e6aec7 100644 --- a/test/regress/regress0/fp/issue5734.smt2 +++ b/test/regress/regress0/fp/issue5734.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; EXPECT: sat (set-logic QF_FP) (declare-fun a () RoundingMode) diff --git a/test/regress/regress0/fp/issue6164.smt2 b/test/regress/regress0/fp/issue6164.smt2 index 056a98afc..3ec9f1594 100644 --- a/test/regress/regress0/fp/issue6164.smt2 +++ b/test/regress/regress0/fp/issue6164.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; EXPECT: sat ; EXPECT: ((((_ to_fp 5 11) roundNearestTiesToAway (/ 1 10)) (fp #b0 #b01011 #b1001100110))) (set-logic ALL) diff --git a/test/regress/regress0/fp/rti_3_5_bug.smt2 b/test/regress/regress0/fp/rti_3_5_bug.smt2 index 2c837b415..724e08b8c 100644 --- a/test/regress/regress0/fp/rti_3_5_bug.smt2 +++ b/test/regress/regress0/fp/rti_3_5_bug.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu
; COMMAND-LINE: --fp-exp
; EXPECT: unsat
diff --git a/test/regress/regress0/fp/simple.smt2 b/test/regress/regress0/fp/simple.smt2 index 0b4a11f08..754186943 100644 --- a/test/regress/regress0/fp/simple.smt2 +++ b/test/regress/regress0/fp/simple.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; EXPECT: unsat (set-logic QF_FP) (declare-const x Float32) diff --git a/test/regress/regress0/fp/wrong-model.smt2 b/test/regress/regress0/fp/wrong-model.smt2 index 7694d8a35..298c21b18 100644 --- a/test/regress/regress0/fp/wrong-model.smt2 +++ b/test/regress/regress0/fp/wrong-model.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --fp-exp ; EXPECT: sat diff --git a/test/regress/regress0/issue5370.smt2 b/test/regress/regress0/issue5370.smt2 index 848567e2c..971602e14 100644 --- a/test/regress/regress0/issue5370.smt2 +++ b/test/regress/regress0/issue5370.smt2 @@ -1,5 +1,4 @@ ; COMMAND-LINE: --bv-to-bool -; REQUIRES: symfpu (set-logic ALL) (set-info :status sat) (declare-fun c () (Array (_ BitVec 2) (_ BitVec 1))) diff --git a/test/regress/regress0/issue6741.smt2 b/test/regress/regress0/issue6741.smt2 new file mode 100644 index 000000000..0fbf4edeb --- /dev/null +++ b/test/regress/regress0/issue6741.smt2 @@ -0,0 +1,8 @@ +; COMMAND-LINE: --bv-solver=bitblast --bitblast=eager --check-models +(set-logic QF_BV) +(set-info :status sat) +(declare-fun x () (_ BitVec 1)) +(declare-fun y () (_ BitVec 1)) +(assert (= y (ite (= x (_ bv1 1)) (_ bv1 1) (_ bv0 1)))) +(assert (= y (_ bv1 1))) +(check-sat) diff --git a/test/regress/regress0/nl/issue3003.smt2 b/test/regress/regress0/nl/issue3003.smt2 index f28a1fd77..3247a941a 100644 --- a/test/regress/regress0/nl/issue3003.smt2 +++ b/test/regress/regress0/nl/issue3003.smt2 @@ -1,4 +1,4 @@ -; COMMAND-LINE: --nl-ext=none +; COMMAND-LINE: --nl-ext=none --no-check-models ; EXPECT: sat (set-logic QF_NRA) (set-info :status sat) diff --git a/test/regress/regress0/parser/to_fp.smt2 b/test/regress/regress0/parser/to_fp.smt2 index 277209ff8..1cd83816a 100644 --- a/test/regress/regress0/parser/to_fp.smt2 +++ b/test/regress/regress0/parser/to_fp.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --strict-parsing -q ; EXPECT: sat (set-logic QF_FP) diff --git a/test/regress/regress1/fmf/issue6690-re-enum.smt2 b/test/regress/regress1/fmf/issue6690-re-enum.smt2 new file mode 100644 index 000000000..35c8eabc7 --- /dev/null +++ b/test/regress/regress1/fmf/issue6690-re-enum.smt2 @@ -0,0 +1,5 @@ +(set-logic ALL) +(set-info :status unsat) +(set-option :finite-model-find true) +(assert (forall ((a String)) (forall ((b String)) (str.in_re a (re.++ re.allchar (str.to_re b)))))) +(check-sat) diff --git a/test/regress/regress1/fp/rti_3_5_bug_report.smt2 b/test/regress/regress1/fp/rti_3_5_bug_report.smt2 index 3e94e6e05..6c0b68c95 100644 --- a/test/regress/regress1/fp/rti_3_5_bug_report.smt2 +++ b/test/regress/regress1/fp/rti_3_5_bug_report.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --fp-exp ; EXPECT: unsat diff --git a/test/regress/regress1/quantifiers/fp-cegqi-unsat.smt2 b/test/regress/regress1/quantifiers/fp-cegqi-unsat.smt2 index 1ee8e6c11..3ab7495ea 100644 --- a/test/regress/regress1/quantifiers/fp-cegqi-unsat.smt2 +++ b/test/regress/regress1/quantifiers/fp-cegqi-unsat.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu (set-info :smt-lib-version 2.6) (set-logic FP) (set-info :status unsat) diff --git a/test/regress/regress1/quantifiers/issue4420-order-sensitive.smt2 b/test/regress/regress1/quantifiers/issue4420-order-sensitive.smt2 index 796d7e753..d30bd563d 100644 --- a/test/regress/regress1/quantifiers/issue4420-order-sensitive.smt2 +++ b/test/regress/regress1/quantifiers/issue4420-order-sensitive.smt2 @@ -1,5 +1,4 @@ ; COMMAND-LINE: --no-jh-rlv-order -; REQUIRES: symfpu ; EXPECT: unsat (set-logic AUFBVFPDTNIRA) (set-info :status unsat) diff --git a/test/regress/regress1/quantifiers/issue6699-nc-shadow.smt2 b/test/regress/regress1/quantifiers/issue6699-nc-shadow.smt2 new file mode 100644 index 000000000..e1e0cdbe8 --- /dev/null +++ b/test/regress/regress1/quantifiers/issue6699-nc-shadow.smt2 @@ -0,0 +1,9 @@ +; COMMAND-LINE: -i +; EXPECT: unsat +(set-logic ALL) +(declare-fun v1 () Bool) +(declare-fun v4 () Bool) +(declare-fun v7 () Bool) +(assert (distinct v7 v1 (and v4 (exists ((q1 Int)) (= (= 0 q1) (and v7 v1)))))) +(push) +(check-sat) diff --git a/test/regress/regress1/rr-verify/fp-arith.sy b/test/regress/regress1/rr-verify/fp-arith.sy index 30828ca76..2970fd0de 100644 --- a/test/regress/regress1/rr-verify/fp-arith.sy +++ b/test/regress/regress1/rr-verify/fp-arith.sy @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --lang=sygus2 --sygus-rr --sygus-samples=0 --sygus-rr-synth-check --sygus-abort-size=1 --sygus-rr-verify-abort --no-sygus-sym-break --fp-exp ; EXPECT: (error "Maximum term size (1) for enumerative SyGuS exceeded.") ; SCRUBBER: grep -v -E '(\(define-fun|\(rewrite)' diff --git a/test/regress/regress1/rr-verify/fp-bool.sy b/test/regress/regress1/rr-verify/fp-bool.sy index 6704198c3..e4b3a0fac 100644 --- a/test/regress/regress1/rr-verify/fp-bool.sy +++ b/test/regress/regress1/rr-verify/fp-bool.sy @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --lang=sygus2 --sygus-rr --sygus-samples=0 --sygus-rr-synth-check --sygus-abort-size=1 --sygus-rr-verify-abort --no-sygus-sym-break --fp-exp ; EXPECT: (error "Maximum term size (1) for enumerative SyGuS exceeded.") ; SCRUBBER: grep -v -E '(\(define-fun|\(rewrite)' diff --git a/test/regress/regress1/sygus/temp_input_to_synth_ic-error-121418.sy b/test/regress/regress1/sygus/temp_input_to_synth_ic-error-121418.sy index fa8bdc2d7..385ade07f 100644 --- a/test/regress/regress1/sygus/temp_input_to_synth_ic-error-121418.sy +++ b/test/regress/regress1/sygus/temp_input_to_synth_ic-error-121418.sy @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; EXPECT: unsat ; COMMAND-LINE: --lang=sygus2 --sygus-out=status (set-logic ALL) diff --git a/test/regress/regress1/wrong-qfabvfp-smtcomp2018.smt2 b/test/regress/regress1/wrong-qfabvfp-smtcomp2018.smt2 index c674c4039..4648c327a 100644 --- a/test/regress/regress1/wrong-qfabvfp-smtcomp2018.smt2 +++ b/test/regress/regress1/wrong-qfabvfp-smtcomp2018.smt2 @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; COMMAND-LINE: --decision=internal -q ; COMMAND-LINE: --decision=justification -q ; EXPECT: sat diff --git a/test/regress/regress2/sygus/min_IC_1.sy b/test/regress/regress2/sygus/min_IC_1.sy index c0cae0025..8c0e2d82b 100644 --- a/test/regress/regress2/sygus/min_IC_1.sy +++ b/test/regress/regress2/sygus/min_IC_1.sy @@ -1,4 +1,3 @@ -; REQUIRES: symfpu ; EXPECT: unsat ; COMMAND-LINE: --lang=sygus2 --sygus-out=status --fp-exp (set-logic ALL) diff --git a/test/unit/api/java/cvc5/GrammarTest.java b/test/unit/api/java/cvc5/GrammarTest.java new file mode 100644 index 000000000..76a80f55e --- /dev/null +++ b/test/unit/api/java/cvc5/GrammarTest.java @@ -0,0 +1,137 @@ +/****************************************************************************** + * Top contributors (to current version): + * Aina Niemetz, Abdalrhman Mohamed, Mudathir Mohamed + * + * This file is part of the cvc5 project. + * + * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS + * in the top-level source directory and their institutional affiliations. + * All rights reserved. See the file COPYING in the top-level source + * directory for licensing information. + * **************************************************************************** + * + * Black box testing of the guards of the Java API functions. + */ + +package cvc5; + +import static cvc5.Kind.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Arrays; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class GrammarTest { + private Solver d_solver; + + @BeforeEach + void setUp() { + d_solver = new Solver(); + } + + @Test + void addRule() { + Sort bool = d_solver.getBooleanSort(); + Sort integer = d_solver.getIntegerSort(); + + Term nullTerm = d_solver.getNullTerm(); + Term start = d_solver.mkVar(bool); + Term nts = d_solver.mkVar(bool); + + Grammar g = d_solver.mkSygusGrammar(new Term[] {}, new Term[] {start}); + + assertDoesNotThrow(() -> g.addRule(start, d_solver.mkBoolean(false))); + + assertThrows(CVC5ApiException.class, + () -> g.addRule(nullTerm, d_solver.mkBoolean(false))); + assertThrows(CVC5ApiException.class, () -> g.addRule(start, nullTerm)); + assertThrows(CVC5ApiException.class, + () -> g.addRule(nts, d_solver.mkBoolean(false))); + assertThrows( + CVC5ApiException.class, () -> g.addRule(start, d_solver.mkInteger(0))); + assertThrows(CVC5ApiException.class, () -> g.addRule(start, nts)); + + d_solver.synthFun("f", new Term[] {}, bool, g); + + assertThrows(CVC5ApiException.class, + () -> g.addRule(start, d_solver.mkBoolean(false))); + } + + @Test + void addRules() { + Sort bool = d_solver.getBooleanSort(); + Sort integer = d_solver.getIntegerSort(); + + Term nullTerm = d_solver.getNullTerm(); + Term start = d_solver.mkVar(bool); + Term nts = d_solver.mkVar(bool); + + Grammar g = d_solver.mkSygusGrammar(new Term[] {}, new Term[] {start}); + + assertDoesNotThrow( + () -> g.addRules(start, new Term[] {d_solver.mkBoolean(false)})); + + assertThrows(CVC5ApiException.class, + () -> g.addRules(nullTerm, new Term[] {d_solver.mkBoolean(false)})); + assertThrows( + CVC5ApiException.class, () -> g.addRules(start, new Term[] {nullTerm})); + assertThrows(CVC5ApiException.class, + () -> g.addRules(nts, new Term[] {d_solver.mkBoolean(false)})); + assertThrows(CVC5ApiException.class, + () -> g.addRules(start, new Term[] {d_solver.mkInteger(0)})); + assertThrows( + CVC5ApiException.class, () -> g.addRules(start, new Term[] {nts})); + + d_solver.synthFun("f", new Term[] {}, bool, g); + + assertThrows(CVC5ApiException.class, + () -> g.addRules(start, new Term[] {d_solver.mkBoolean(false)})); + } + + @Test + void addAnyConstant() { + Sort bool = d_solver.getBooleanSort(); + + Term nullTerm = d_solver.getNullTerm(); + Term start = d_solver.mkVar(bool); + Term nts = d_solver.mkVar(bool); + + Grammar g = d_solver.mkSygusGrammar(new Term[] {}, new Term[] {start}); + + assertDoesNotThrow(() -> g.addAnyConstant(start)); + assertDoesNotThrow(() -> g.addAnyConstant(start)); + + assertThrows(CVC5ApiException.class, () -> g.addAnyConstant(nullTerm)); + assertThrows(CVC5ApiException.class, () -> g.addAnyConstant(nts)); + + d_solver.synthFun("f", new Term[] {}, bool, g); + + assertThrows(CVC5ApiException.class, () -> g.addAnyConstant(start)); + } + + @Test + void addAnyVariable() { + Sort bool = d_solver.getBooleanSort(); + + Term nullTerm = d_solver.getNullTerm(); + Term x = d_solver.mkVar(bool); + Term start = d_solver.mkVar(bool); + Term nts = d_solver.mkVar(bool); + + Grammar g1 = d_solver.mkSygusGrammar(new Term[] {x}, new Term[] {start}); + Grammar g2 = d_solver.mkSygusGrammar(new Term[] {}, new Term[] {start}); + + assertDoesNotThrow(() -> g1.addAnyVariable(start)); + assertDoesNotThrow(() -> g1.addAnyVariable(start)); + assertDoesNotThrow(() -> g2.addAnyVariable(start)); + + assertThrows(CVC5ApiException.class, () -> g1.addAnyVariable(nullTerm)); + assertThrows(CVC5ApiException.class, () -> g1.addAnyVariable(nts)); + + d_solver.synthFun("f", new Term[] {}, bool, g1); + + assertThrows(CVC5ApiException.class, () -> g1.addAnyVariable(start)); + } +} diff --git a/test/unit/api/solver_black.cpp b/test/unit/api/solver_black.cpp index 018207293..20e0977f8 100644 --- a/test/unit/api/solver_black.cpp +++ b/test/unit/api/solver_black.cpp @@ -35,15 +35,7 @@ TEST_F(TestApiBlackSolver, recoverableException) TEST_F(TestApiBlackSolver, supportsFloatingPoint) { - if (d_solver.supportsFloatingPoint()) - { - ASSERT_NO_THROW(d_solver.mkRoundingMode(ROUND_NEAREST_TIES_TO_EVEN)); - } - else - { - ASSERT_THROW(d_solver.mkRoundingMode(ROUND_NEAREST_TIES_TO_EVEN), - CVC5ApiException); - } + ASSERT_NO_THROW(d_solver.mkRoundingMode(ROUND_NEAREST_TIES_TO_EVEN)); } TEST_F(TestApiBlackSolver, getBooleanSort) @@ -78,14 +70,7 @@ TEST_F(TestApiBlackSolver, getStringSort) TEST_F(TestApiBlackSolver, getRoundingModeSort) { - if (d_solver.supportsFloatingPoint()) - { - ASSERT_NO_THROW(d_solver.getRoundingModeSort()); - } - else - { - ASSERT_THROW(d_solver.getRoundingModeSort(), CVC5ApiException); - } + ASSERT_NO_THROW(d_solver.getRoundingModeSort()); } TEST_F(TestApiBlackSolver, mkArraySort) @@ -101,12 +86,9 @@ TEST_F(TestApiBlackSolver, mkArraySort) ASSERT_NO_THROW(d_solver.mkArraySort(boolSort, intSort)); ASSERT_NO_THROW(d_solver.mkArraySort(realSort, bvSort)); - if (d_solver.supportsFloatingPoint()) - { - Sort fpSort = d_solver.mkFloatingPointSort(3, 5); - ASSERT_NO_THROW(d_solver.mkArraySort(fpSort, fpSort)); - ASSERT_NO_THROW(d_solver.mkArraySort(bvSort, fpSort)); - } + Sort fpSort = d_solver.mkFloatingPointSort(3, 5); + ASSERT_NO_THROW(d_solver.mkArraySort(fpSort, fpSort)); + ASSERT_NO_THROW(d_solver.mkArraySort(bvSort, fpSort)); Solver slv; ASSERT_THROW(slv.mkArraySort(boolSort, boolSort), CVC5ApiException); @@ -120,16 +102,9 @@ TEST_F(TestApiBlackSolver, mkBitVectorSort) TEST_F(TestApiBlackSolver, mkFloatingPointSort) { - if (d_solver.supportsFloatingPoint()) - { - ASSERT_NO_THROW(d_solver.mkFloatingPointSort(4, 8)); - ASSERT_THROW(d_solver.mkFloatingPointSort(0, 8), CVC5ApiException); - ASSERT_THROW(d_solver.mkFloatingPointSort(4, 0), CVC5ApiException); - } - else - { - ASSERT_THROW(d_solver.mkFloatingPointSort(4, 8), CVC5ApiException); - } + ASSERT_NO_THROW(d_solver.mkFloatingPointSort(4, 8)); + ASSERT_THROW(d_solver.mkFloatingPointSort(0, 8), CVC5ApiException); + ASSERT_THROW(d_solver.mkFloatingPointSort(4, 0), CVC5ApiException); } TEST_F(TestApiBlackSolver, mkDatatypeSort) @@ -377,15 +352,7 @@ TEST_F(TestApiBlackSolver, mkBoolean) TEST_F(TestApiBlackSolver, mkRoundingMode) { - if (d_solver.supportsFloatingPoint()) - { - ASSERT_NO_THROW(d_solver.mkRoundingMode(RoundingMode::ROUND_TOWARD_ZERO)); - } - else - { - ASSERT_THROW(d_solver.mkRoundingMode(RoundingMode::ROUND_TOWARD_ZERO), - CVC5ApiException); - } + ASSERT_NO_THROW(d_solver.mkRoundingMode(RoundingMode::ROUND_TOWARD_ZERO)); } TEST_F(TestApiBlackSolver, mkUninterpretedConst) @@ -420,25 +387,15 @@ TEST_F(TestApiBlackSolver, mkFloatingPoint) Term t1 = d_solver.mkBitVector(8); Term t2 = d_solver.mkBitVector(4); Term t3 = d_solver.mkInteger(2); - if (d_solver.supportsFloatingPoint()) - { - ASSERT_NO_THROW(d_solver.mkFloatingPoint(3, 5, t1)); - } - else - { - ASSERT_THROW(d_solver.mkFloatingPoint(3, 5, t1), CVC5ApiException); - } + ASSERT_NO_THROW(d_solver.mkFloatingPoint(3, 5, t1)); ASSERT_THROW(d_solver.mkFloatingPoint(0, 5, Term()), CVC5ApiException); ASSERT_THROW(d_solver.mkFloatingPoint(0, 5, t1), CVC5ApiException); ASSERT_THROW(d_solver.mkFloatingPoint(3, 0, t1), CVC5ApiException); ASSERT_THROW(d_solver.mkFloatingPoint(3, 5, t2), CVC5ApiException); ASSERT_THROW(d_solver.mkFloatingPoint(3, 5, t2), CVC5ApiException); - if (d_solver.supportsFloatingPoint()) - { - Solver slv; - ASSERT_THROW(slv.mkFloatingPoint(3, 5, t1), CVC5ApiException); - } + Solver slv; + ASSERT_THROW(slv.mkFloatingPoint(3, 5, t1), CVC5ApiException); } TEST_F(TestApiBlackSolver, mkEmptySet) @@ -478,64 +435,26 @@ TEST_F(TestApiBlackSolver, mkFalse) ASSERT_NO_THROW(d_solver.mkFalse()); } -TEST_F(TestApiBlackSolver, mkNaN) -{ - if (d_solver.supportsFloatingPoint()) - { - ASSERT_NO_THROW(d_solver.mkNaN(3, 5)); - } - else - { - ASSERT_THROW(d_solver.mkNaN(3, 5), CVC5ApiException); - } -} +TEST_F(TestApiBlackSolver, mkNaN) { ASSERT_NO_THROW(d_solver.mkNaN(3, 5)); } TEST_F(TestApiBlackSolver, mkNegZero) { - if (d_solver.supportsFloatingPoint()) - { - ASSERT_NO_THROW(d_solver.mkNegZero(3, 5)); - } - else - { - ASSERT_THROW(d_solver.mkNegZero(3, 5), CVC5ApiException); - } + ASSERT_NO_THROW(d_solver.mkNegZero(3, 5)); } TEST_F(TestApiBlackSolver, mkNegInf) { - if (d_solver.supportsFloatingPoint()) - { - ASSERT_NO_THROW(d_solver.mkNegInf(3, 5)); - } - else - { - ASSERT_THROW(d_solver.mkNegInf(3, 5), CVC5ApiException); - } + ASSERT_NO_THROW(d_solver.mkNegInf(3, 5)); } TEST_F(TestApiBlackSolver, mkPosInf) { - if (d_solver.supportsFloatingPoint()) - { - ASSERT_NO_THROW(d_solver.mkPosInf(3, 5)); - } - else - { - ASSERT_THROW(d_solver.mkPosInf(3, 5), CVC5ApiException); - } + ASSERT_NO_THROW(d_solver.mkPosInf(3, 5)); } TEST_F(TestApiBlackSolver, mkPosZero) { - if (d_solver.supportsFloatingPoint()) - { - ASSERT_NO_THROW(d_solver.mkPosZero(3, 5)); - } - else - { - ASSERT_THROW(d_solver.mkPosZero(3, 5), CVC5ApiException); - } + ASSERT_NO_THROW(d_solver.mkPosZero(3, 5)); } TEST_F(TestApiBlackSolver, mkOp) diff --git a/test/unit/api/sort_black.cpp b/test/unit/api/sort_black.cpp index d1b096bda..757bacad6 100644 --- a/test/unit/api/sort_black.cpp +++ b/test/unit/api/sort_black.cpp @@ -95,11 +95,8 @@ TEST_F(TestApiBlackSort, isRegExp) TEST_F(TestApiBlackSort, isRoundingMode) { - if (d_solver.supportsFloatingPoint()) - { - ASSERT_TRUE(d_solver.getRoundingModeSort().isRoundingMode()); - ASSERT_NO_THROW(Sort().isRoundingMode()); - } + ASSERT_TRUE(d_solver.getRoundingModeSort().isRoundingMode()); + ASSERT_NO_THROW(Sort().isRoundingMode()); } TEST_F(TestApiBlackSort, isBitVector) @@ -110,11 +107,8 @@ TEST_F(TestApiBlackSort, isBitVector) TEST_F(TestApiBlackSort, isFloatingPoint) { - if (d_solver.supportsFloatingPoint()) - { - ASSERT_TRUE(d_solver.mkFloatingPointSort(8, 24).isFloatingPoint()); - ASSERT_NO_THROW(Sort().isFloatingPoint()); - } + ASSERT_TRUE(d_solver.mkFloatingPointSort(8, 24).isFloatingPoint()); + ASSERT_NO_THROW(Sort().isFloatingPoint()); } TEST_F(TestApiBlackSort, isDatatype) @@ -486,24 +480,18 @@ TEST_F(TestApiBlackSort, getBVSize) TEST_F(TestApiBlackSort, getFPExponentSize) { - if (d_solver.supportsFloatingPoint()) - { - Sort fpSort = d_solver.mkFloatingPointSort(4, 8); - ASSERT_NO_THROW(fpSort.getFPExponentSize()); - Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort()); - ASSERT_THROW(setSort.getFPExponentSize(), CVC5ApiException); - } + Sort fpSort = d_solver.mkFloatingPointSort(4, 8); + ASSERT_NO_THROW(fpSort.getFPExponentSize()); + Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort()); + ASSERT_THROW(setSort.getFPExponentSize(), CVC5ApiException); } TEST_F(TestApiBlackSort, getFPSignificandSize) { - if (d_solver.supportsFloatingPoint()) - { - Sort fpSort = d_solver.mkFloatingPointSort(4, 8); - ASSERT_NO_THROW(fpSort.getFPSignificandSize()); - Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort()); - ASSERT_THROW(setSort.getFPSignificandSize(), CVC5ApiException); - } + Sort fpSort = d_solver.mkFloatingPointSort(4, 8); + ASSERT_NO_THROW(fpSort.getFPSignificandSize()); + Sort setSort = d_solver.mkSetSort(d_solver.getIntegerSort()); + ASSERT_THROW(setSort.getFPSignificandSize(), CVC5ApiException); } TEST_F(TestApiBlackSort, getDatatypeParamSorts) diff --git a/test/unit/node/attribute_white.cpp b/test/unit/node/attribute_white.cpp index fe74130d1..4b0f1892f 100644 --- a/test/unit/node/attribute_white.cpp +++ b/test/unit/node/attribute_white.cpp @@ -78,7 +78,7 @@ TEST_F(TestNodeWhiteAttribute, attribute_ids) // and that the next ID to be assigned is strictly greater than // those that have already been assigned. - unsigned lastId = attr::LastAttributeId<std::string, false>::getId(); + unsigned lastId = attr::LastAttributeId<std::string>::getId(); ASSERT_LT(VarNameAttr::s_id, lastId); ASSERT_LT(TestStringAttr1::s_id, lastId); ASSERT_LT(TestStringAttr2::s_id, lastId); @@ -87,7 +87,7 @@ TEST_F(TestNodeWhiteAttribute, attribute_ids) ASSERT_NE(VarNameAttr::s_id, TestStringAttr2::s_id); ASSERT_NE(TestStringAttr1::s_id, TestStringAttr2::s_id); - lastId = attr::LastAttributeId<bool, false>::getId(); + lastId = attr::LastAttributeId<bool>::getId(); ASSERT_LT(TestFlag1::s_id, lastId); ASSERT_LT(TestFlag2::s_id, lastId); ASSERT_LT(TestFlag3::s_id, lastId); @@ -104,7 +104,7 @@ TEST_F(TestNodeWhiteAttribute, attribute_ids) ASSERT_NE(TestFlag3::s_id, TestFlag5::s_id); ASSERT_NE(TestFlag4::s_id, TestFlag5::s_id); - lastId = attr::LastAttributeId<TypeNode, false>::getId(); + lastId = attr::LastAttributeId<TypeNode>::getId(); ASSERT_LT(TypeAttr::s_id, lastId); } diff --git a/test/unit/theory/logic_info_white.cpp b/test/unit/theory/logic_info_white.cpp index 7a6e34abb..e999297fd 100644 --- a/test/unit/theory/logic_info_white.cpp +++ b/test/unit/theory/logic_info_white.cpp @@ -616,28 +616,14 @@ TEST_F(TestTheoryWhiteLogicInfo, default_logic) info.arithOnlyLinear(); info.disableIntegers(); info.lock(); - if (cvc5::Configuration::isBuiltWithSymFPU()) - { - ASSERT_EQ(info.getLogicString(), "SEP_AUFBVFPDTLRA"); - } - else - { - ASSERT_EQ(info.getLogicString(), "SEP_AUFBVDTLRA"); - } + ASSERT_EQ(info.getLogicString(), "SEP_AUFBVFPDTLRA"); info = info.getUnlockedCopy(); ASSERT_FALSE(info.isLocked()); info.disableQuantifiers(); info.disableTheory(THEORY_BAGS); info.lock(); - if (cvc5::Configuration::isBuiltWithSymFPU()) - { - ASSERT_EQ(info.getLogicString(), "QF_SEP_AUFBVFPDTLRA"); - } - else - { - ASSERT_EQ(info.getLogicString(), "QF_SEP_AUFBVDTLRA"); - } + ASSERT_EQ(info.getLogicString(), "QF_SEP_AUFBVFPDTLRA"); info = info.getUnlockedCopy(); ASSERT_FALSE(info.isLocked()); @@ -647,14 +633,7 @@ TEST_F(TestTheoryWhiteLogicInfo, default_logic) info.enableIntegers(); info.disableReals(); info.lock(); - if (cvc5::Configuration::isBuiltWithSymFPU()) - { - ASSERT_EQ(info.getLogicString(), "QF_SEP_AUFFPLIA"); - } - else - { - ASSERT_EQ(info.getLogicString(), "QF_SEP_AUFLIA"); - } + ASSERT_EQ(info.getLogicString(), "QF_SEP_AUFFPLIA"); info = info.getUnlockedCopy(); ASSERT_FALSE(info.isLocked()); diff --git a/test/unit/theory/theory_bv_opt_white.cpp b/test/unit/theory/theory_bv_opt_white.cpp index c23ce79dd..5cd29878e 100644 --- a/test/unit/theory/theory_bv_opt_white.cpp +++ b/test/unit/theory/theory_bv_opt_white.cpp @@ -57,9 +57,9 @@ TEST_F(TestTheoryWhiteBVOpt, unsigned_min) d_optslv->addObjective(x, OptimizationObjective::MINIMIZE, false); - OptimizationResult::ResultType r = d_optslv->checkOpt(); + Result r = d_optslv->checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<BitVector>(), BitVector(32u, (uint32_t)0x3FFFFFA1)); @@ -78,9 +78,9 @@ TEST_F(TestTheoryWhiteBVOpt, signed_min) d_optslv->addObjective(x, OptimizationObjective::MINIMIZE, true); - OptimizationResult::ResultType r = d_optslv->checkOpt(); + Result r = d_optslv->checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); BitVector val = d_optslv->getValues()[0].getValue().getConst<BitVector>(); std::cout << "opt value is: " << val << std::endl; @@ -105,9 +105,9 @@ TEST_F(TestTheoryWhiteBVOpt, unsigned_max) d_optslv->addObjective(x, OptimizationObjective::MAXIMIZE, false); - OptimizationResult::ResultType r = d_optslv->checkOpt(); + Result r = d_optslv->checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); BitVector val = d_optslv->getValues()[0].getValue().getConst<BitVector>(); std::cout << "opt value is: " << val << std::endl; @@ -130,9 +130,9 @@ TEST_F(TestTheoryWhiteBVOpt, signed_max) d_optslv->addObjective(x, OptimizationObjective::MAXIMIZE, true); - OptimizationResult::ResultType r = d_optslv->checkOpt(); + Result r = d_optslv->checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); // expect the maxmum x = ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<BitVector>(), @@ -154,9 +154,9 @@ TEST_F(TestTheoryWhiteBVOpt, min_boundary) d_optslv->addObjective(x, OptimizationObjective::MINIMIZE, false); - OptimizationResult::ResultType r = d_optslv->checkOpt(); + Result r = d_optslv->checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); // expect the maximum x = 18 ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<BitVector>(), diff --git a/test/unit/theory/theory_int_opt_white.cpp b/test/unit/theory/theory_int_opt_white.cpp index cf0434ddc..583f908e7 100644 --- a/test/unit/theory/theory_int_opt_white.cpp +++ b/test/unit/theory/theory_int_opt_white.cpp @@ -62,9 +62,9 @@ TEST_F(TestTheoryWhiteIntOpt, max) // We activate our objective so the subsolver knows to optimize it d_optslv->addObjective(max_cost, OptimizationObjective::MAXIMIZE); - OptimizationResult::ResultType r = d_optslv->checkOpt(); + Result r = d_optslv->checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); // We expect max_cost == 99 ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<Rational>(), @@ -93,9 +93,9 @@ TEST_F(TestTheoryWhiteIntOpt, min) // We activate our objective so the subsolver knows to optimize it d_optslv->addObjective(max_cost, OptimizationObjective::MINIMIZE); - OptimizationResult::ResultType r = d_optslv->checkOpt(); + Result r = d_optslv->checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); // We expect max_cost == 99 ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<Rational>(), @@ -125,10 +125,10 @@ TEST_F(TestTheoryWhiteIntOpt, result) d_optslv->addObjective(max_cost, OptimizationObjective::MAXIMIZE); // This should return OPT_UNSAT since 0 > x > 100 is impossible. - OptimizationResult::ResultType r = d_optslv->checkOpt(); + Result r = d_optslv->checkOpt(); // We expect our check to have returned UNSAT - ASSERT_EQ(r, OptimizationResult::UNSAT); + ASSERT_EQ(r.isSat(), Result::UNSAT); d_smtEngine->resetAssertions(); } @@ -157,9 +157,9 @@ TEST_F(TestTheoryWhiteIntOpt, open_interval) d_optslv->addObjective(cost3, OptimizationObjective::MINIMIZE); - OptimizationResult::ResultType r = d_optslv->checkOpt(); + Result r = d_optslv->checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); // expect the minimum result of cost3 = cost1 + cost2 to be 1 + 111 = 112 ASSERT_EQ(d_optslv->getValues()[0].getValue().getConst<Rational>(), diff --git a/test/unit/theory/theory_opt_multigoal_white.cpp b/test/unit/theory/theory_opt_multigoal_white.cpp index 73c6d9e7e..9a091fb3b 100644 --- a/test/unit/theory/theory_opt_multigoal_white.cpp +++ b/test/unit/theory/theory_opt_multigoal_white.cpp @@ -54,11 +54,8 @@ TEST_F(TestTheoryWhiteOptMultigoal, box) // y <= x d_smtEngine->assertFormula(d_nodeManager->mkNode(kind::BITVECTOR_SLE, y, x)); - // Box optimization OptimizationSolver optSolver(d_smtEngine.get()); - optSolver.setObjectiveCombination(OptimizationSolver::BOX); - // minimize x optSolver.addObjective(x, OptimizationObjective::MINIMIZE, false); // maximize y with `signed` comparison over bit-vectors. @@ -66,9 +63,10 @@ TEST_F(TestTheoryWhiteOptMultigoal, box) // maximize z optSolver.addObjective(z, OptimizationObjective::MAXIMIZE, false); - OptimizationResult::ResultType r = optSolver.checkOpt(); + // Box optimization + Result r = optSolver.checkOpt(OptimizationSolver::BOX); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); std::vector<OptimizationResult> results = optSolver.getValues(); @@ -100,8 +98,6 @@ TEST_F(TestTheoryWhiteOptMultigoal, lex) OptimizationSolver optSolver(d_smtEngine.get()); - optSolver.setObjectiveCombination(OptimizationSolver::LEXICOGRAPHIC); - // minimize x optSolver.addObjective(x, OptimizationObjective::MINIMIZE, false); // maximize y with `signed` comparison over bit-vectors. @@ -109,9 +105,9 @@ TEST_F(TestTheoryWhiteOptMultigoal, lex) // maximize z optSolver.addObjective(z, OptimizationObjective::MAXIMIZE, false); - OptimizationResult::ResultType r = optSolver.checkOpt(); + Result r = optSolver.checkOpt(OptimizationSolver::LEXICOGRAPHIC); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); std::vector<OptimizationResult> results = optSolver.getValues(); @@ -180,18 +176,17 @@ TEST_F(TestTheoryWhiteOptMultigoal, pareto) (maximize b) */ OptimizationSolver optSolver(d_smtEngine.get()); - optSolver.setObjectiveCombination(OptimizationSolver::PARETO); optSolver.addObjective(a, OptimizationObjective::MAXIMIZE); optSolver.addObjective(b, OptimizationObjective::MAXIMIZE); - OptimizationResult::ResultType r; + Result r; // all possible result pairs <a, b> std::set<std::pair<uint32_t, uint32_t>> possibleResults = { {1, 3}, {2, 2}, {3, 1}}; - r = optSolver.checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + r = optSolver.checkOpt(OptimizationSolver::PARETO); + ASSERT_EQ(r.isSat(), Result::SAT); std::vector<OptimizationResult> results = optSolver.getValues(); std::pair<uint32_t, uint32_t> res = { results[0].getValue().getConst<BitVector>().toInteger().toUnsignedInt(), @@ -205,8 +200,8 @@ TEST_F(TestTheoryWhiteOptMultigoal, pareto) ASSERT_EQ(possibleResults.count(res), 1); possibleResults.erase(res); - r = optSolver.checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + r = optSolver.checkOpt(OptimizationSolver::PARETO); + ASSERT_EQ(r.isSat(), Result::SAT); results = optSolver.getValues(); res = { results[0].getValue().getConst<BitVector>().toInteger().toUnsignedInt(), @@ -220,8 +215,8 @@ TEST_F(TestTheoryWhiteOptMultigoal, pareto) ASSERT_EQ(possibleResults.count(res), 1); possibleResults.erase(res); - r = optSolver.checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + r = optSolver.checkOpt(OptimizationSolver::PARETO); + ASSERT_EQ(r.isSat(), Result::SAT); results = optSolver.getValues(); res = { results[0].getValue().getConst<BitVector>().toInteger().toUnsignedInt(), @@ -235,8 +230,8 @@ TEST_F(TestTheoryWhiteOptMultigoal, pareto) ASSERT_EQ(possibleResults.count(res), 1); possibleResults.erase(res); - r = optSolver.checkOpt(); - ASSERT_EQ(r, OptimizationResult::UNSAT); + r = optSolver.checkOpt(OptimizationSolver::PARETO); + ASSERT_EQ(r.isSat(), Result::UNSAT); ASSERT_EQ(possibleResults.size(), 0); } @@ -254,11 +249,8 @@ TEST_F(TestTheoryWhiteOptMultigoal, pushpop) // y <= x d_smtEngine->assertFormula(d_nodeManager->mkNode(kind::BITVECTOR_SLE, y, x)); - // Lexico optimization OptimizationSolver optSolver(d_smtEngine.get()); - optSolver.setObjectiveCombination(OptimizationSolver::LEXICOGRAPHIC); - // minimize x optSolver.addObjective(x, OptimizationObjective::MINIMIZE, false); @@ -270,9 +262,10 @@ TEST_F(TestTheoryWhiteOptMultigoal, pushpop) // maximize z optSolver.addObjective(z, OptimizationObjective::MAXIMIZE, false); - OptimizationResult::ResultType r = optSolver.checkOpt(); + // Lexico optimization + Result r = optSolver.checkOpt(OptimizationSolver::LEXICOGRAPHIC); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + ASSERT_EQ(r.isSat(), Result::SAT); std::vector<OptimizationResult> results = optSolver.getValues(); @@ -290,16 +283,16 @@ TEST_F(TestTheoryWhiteOptMultigoal, pushpop) d_smtEngine->pop(); // now we only have one objective: (minimize x) - r = optSolver.checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + r = optSolver.checkOpt(OptimizationSolver::LEXICOGRAPHIC); + ASSERT_EQ(r.isSat(), Result::SAT); results = optSolver.getValues(); ASSERT_EQ(results.size(), 1); ASSERT_EQ(results[0].getValue().getConst<BitVector>(), BitVector(32u, 18u)); // resetting the assertions also resets the optimization objectives d_smtEngine->resetAssertions(); - r = optSolver.checkOpt(); - ASSERT_EQ(r, OptimizationResult::OPTIMAL); + r = optSolver.checkOpt(OptimizationSolver::LEXICOGRAPHIC); + ASSERT_EQ(r.isSat(), Result::SAT); results = optSolver.getValues(); ASSERT_EQ(results.size(), 0); } diff --git a/test/unit/util/CMakeLists.txt b/test/unit/util/CMakeLists.txt index 26ab40614..c1630a203 100644 --- a/test/unit/util/CMakeLists.txt +++ b/test/unit/util/CMakeLists.txt @@ -24,9 +24,7 @@ cvc5_add_unit_test_white(check_white util) cvc5_add_unit_test_black(configuration_black util) cvc5_add_unit_test_black(datatype_black util) cvc5_add_unit_test_black(exception_black util) -if(CVC5_USE_SYMFPU) cvc5_add_unit_test_black(floatingpoint_black util) -endif() cvc5_add_unit_test_black(integer_black util) cvc5_add_unit_test_white(integer_white util) cvc5_add_unit_test_black(output_black util) |