diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..e85dae524 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +**/*.swp +**/*.pyc +.git +**/*.Dockerfile diff --git a/.gitignore b/.gitignore index cc1c2a754..b7e4a0186 100644 --- a/.gitignore +++ b/.gitignore @@ -75,14 +75,3 @@ src/api/ml/z3.mllib *.bak doc/api doc/code - -# CMake files copied over by the ``contrib/cmake/boostrap.py`` script -# See #461 -examples/CMakeLists.txt -examples/*/CMakeLists.txt -src/CMakeLists.txt -src/*/CMakeLists.txt -src/*/*/CMakeLists.txt -src/*/*/*/CMakeLists.txt -src/api/dotnet/cmake_install_gac.cmake.in -src/api/dotnet/cmake_uninstall_gac.cmake.in diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..e8e207466 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,68 @@ +cache: + # This persistent cache is used to cache the building of + # docker base images. + directories: + - $DOCKER_TRAVIS_CI_CACHE_DIR +sudo: required +language: cpp +services: + - docker +env: + global: + # This environment variable tells the `travis_ci_linux_entry_point.sh` + # script to look for a cached Docker image. + - DOCKER_TRAVIS_CI_CACHE_DIR=$HOME/.cache/docker + # Configurations + matrix: +############################################################################### +# Ubuntu 16.04 LTS +############################################################################### + # 64-bit GCC 5.4 RelWithDebInfo + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo + # 64-bit Clang 3.9 RelWithDebInfo + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo + + # 64-bit GCC 5.4 Debug + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug + # 64-bit Clang Debug + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug + + # 32-bit GCC 5.4 RelWithDebInfo + - LINUX_BASE=ubuntu32_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=i686 Z3_BUILD_TYPE=RelWithDebInfo + + # Both of the two configurations below build the docs because the current + # implementation uses python as part of the building process. + # TODO: Teach one of the configurations to upload built docs somewhere. + # Test with Python 3 and API docs + - LINUX_BASE=ubuntu_16.04 PYTHON_EXECUTABLE=/usr/bin/python3 BUILD_DOCS=1 + # Test with LibGMP and API docs + - LINUX_BASE=ubuntu_16.04 TARGET_ARCH=x86_64 USE_LIBGMP=1 BUILD_DOCS=1 PYTHON_EXECUTABLE=/usr/bin/python2.7 + + # Test without OpenMP + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo USE_OPENMP=0 + + # Unix Makefile generator build + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_CMAKE_GENERATOR="Unix Makefiles" + + # LTO build + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 USE_LTO=1 + + # Static build. Note we have disable building the bindings because they won't work with a static libz3 + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_STATIC_BUILD=1 DOTNET_BINDINGS=0 JAVA_BINDINGS=0 PYTHON_BINDINGS=0 + +############################################################################### +# Ubuntu 14.04 LTS +############################################################################### + # GCC 4.8 + # 64-bit GCC 4.8 RelWithDebInfo + - LINUX_BASE=ubuntu_14.04 C_COMPILER=/usr/bin/gcc-4.8 CXX_COMPILER=/usr/bin/g++-4.8 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo + # 64-bit GCC 4.8 Debug + - LINUX_BASE=ubuntu_14.04 C_COMPILER=/usr/bin/gcc-4.8 CXX_COMPILER=/usr/bin/g++-4.8 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug + +# TODO: OSX support +#matrix: +# include: +# - os: osx +# osx_image: xcode 8.2 +script: + - contrib/ci/scripts/travis_ci_entry_point.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d188d0b0..ad29a6a57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,19 +14,21 @@ if (POLICY CMP0054) cmake_policy(SET CMP0054 OLD) endif() -# Provide a friendly message if the user hasn't run the bootstrap script -# to copy all the CMake files into their correct location. -# It is unfortunate that we have to do this, see #461 for the discussion -# on this. -if (NOT (EXISTS "${CMAKE_SOURCE_DIR}/src/CMakeLists.txt")) - message(FATAL_ERROR "Cannot find \"${CMAKE_SOURCE_DIR}/src/CMakeLists.txt\"" - ". This probably means you need to run" - "``python contrib/cmake/bootstrap.py create``") +if (POLICY CMP0042) + # Enable `MACOSX_RPATH` by default. + cmake_policy(SET CMP0042 NEW) endif() set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake") project(Z3 CXX) +if ("${CMAKE_VERSION}" VERSION_LESS "3.4") + # FIXME: Drop this when we upgrade to newer CMake versions. + # HACK: Although we don't need C language support if it is not + # enabled CMake's `FindThreads` module fails in old CMake versions. + enable_language(C) +endif() + ################################################################################ # Project version ################################################################################ @@ -108,7 +110,7 @@ if (EXISTS "${GIT_DIR}") endif() message(STATUS "Using Git hash in version output: ${Z3GITHASH}") # This mimics the behaviour of the old build system. - string(APPEND Z3_FULL_VERSION_STR " ${Z3GITHASH}") + set(Z3_FULL_VERSION_STR "${Z3_FULL_VERSION_STR} ${Z3GITHASH}") else() message(STATUS "Not using Git hash in version output") unset(Z3GITHASH) # Used in configure_file() @@ -121,7 +123,7 @@ if (EXISTS "${GIT_DIR}") endif() message(STATUS "Using Git description in version output: ${Z3_GIT_DESCRIPTION}") # This mimics the behaviour of the old build system. - string(APPEND Z3_FULL_VERSION_STR " ${Z3_GIT_DESCRIPTION}") + set(Z3_FULL_VERSION_STR "${Z3_FULL_VERSION_STR} ${Z3_GIT_DESCRIPTION}") else() message(STATUS "Not including git descrption in version") endif() @@ -410,6 +412,38 @@ endif() ################################################################################ include(${CMAKE_SOURCE_DIR}/cmake/compiler_lto.cmake) +################################################################################ +# Control flow integrity +################################################################################ +option(ENABLE_CFI "Enable control flow integrity checking" OFF) +if (ENABLE_CFI) + set(build_types_with_cfi "RELEASE" "RELWITHDEBINFO") + if (NOT LINK_TIME_OPTIMIZATION) + message(FATAL_ERROR "Cannot enable control flow integrity checking without link-time optimization." + "You should set LINK_TIME_OPTIMIZATION to ON or ENABLE_CFI to OFF.") + endif() + if (DEFINED CMAKE_CONFIGURATION_TYPES) + # Multi configuration generator + message(STATUS "Note CFI is only enabled for the following configurations: ${build_types_with_cfi}") + # No need for else because this is the same as the set that LTO requires. + endif() + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + z3_add_cxx_flag("-fsanitize=cfi" REQUIRED) + z3_add_cxx_flag("-fsanitize-cfi-cross-dso" REQUIRED) + elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") + z3_add_cxx_flag("/guard:cf" REQUIRED) + message(STATUS "Enabling CFI for MSVC") + foreach (_build_type ${build_types_with_cfi}) + message(STATUS "Enabling CFI for MSVC") + string(APPEND CMAKE_EXE_LINKER_FLAGS_${_build_type} " /GUARD:CF") + string(APPEND CMAKE_SHARED_LINKER_FLAGS_${_build_type} " /GUARD:CF") + endforeach() + else() + message(FATAL_ERROR "Can't enable control flow integrity for compiler \"${CMAKE_CXX_COMPILER_ID}\"." + "You should set ENABLE_CFI to OFF or use Clang or MSVC to compile.") + endif() +endif() + ################################################################################ # MSVC specific flags inherited from old build system ################################################################################ @@ -523,10 +557,18 @@ add_subdirectory(src) # use Z3 via CMake. ################################################################################ include(CMakePackageConfigHelpers) -export(EXPORT Z3_EXPORTED_TARGETS - NAMESPACE z3:: - FILE "${CMAKE_BINARY_DIR}/Z3Targets.cmake" -) +if ("${CMAKE_VERSION}" VERSION_LESS "3.0") + # FIXME: Remove this once we drop support for CMake 2.8.12 + export(TARGETS libz3 + NAMESPACE z3:: + FILE "${CMAKE_BINARY_DIR}/Z3Targets.cmake" + ) +else() + export(EXPORT Z3_EXPORTED_TARGETS + NAMESPACE z3:: + FILE "${CMAKE_BINARY_DIR}/Z3Targets.cmake" + ) +endif() set(Z3_FIRST_PACKAGE_INCLUDE_DIR "${CMAKE_BINARY_DIR}/src/api") set(Z3_SECOND_PACKAGE_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/src/api") set(Z3_CXX_PACKAGE_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/src/api/c++") @@ -539,7 +581,6 @@ configure_package_config_file("${CMAKE_SOURCE_DIR}/cmake/Z3Config.cmake.in" Z3_FIRST_PACKAGE_INCLUDE_DIR Z3_SECOND_PACKAGE_INCLUDE_DIR Z3_CXX_PACKAGE_INCLUDE_DIR - INSTALL_PREFIX "${CMAKE_BINARY_DIR}" ) unset(Z3_FIRST_PACKAGE_INCLUDE_DIR) unset(Z3_SECOND_PACKAGE_INCLUDE_DIR) diff --git a/README-CMake.md b/README-CMake.md index 1b7d89542..605c14818 100644 --- a/README-CMake.md +++ b/README-CMake.md @@ -33,34 +33,6 @@ git clean -fx src which will remove the generated source files. -### Bootstrapping - -Most of Z3's CMake files do not live in their correct location. Instead those -files live in the ``contrib/cmake`` folder and a script is provided that will -copy (or hard link) the files into their correct location. - -To copy the files run - -``` -python contrib/cmake/bootstrap.py create -``` - -in the root of the repository. Once you have done this you can now build Z3 using CMake. -Make sure you remember to rerun this command if you pull down new code/rebase/change branch so -that the copied CMake files are up to date. - -To remove the copied files run - -``` -python contrib/cmake/bootstrap.py remove -``` - -Note if you plan to do development on Z3 you should read the developer -notes on bootstrapping in this document. - -What follows is a brief walk through of how to build Z3 using some -of the more commonly used CMake generators. - ### Unix Makefiles Run the following in the top level directory of the Z3 repository. @@ -293,7 +265,11 @@ The following useful options can be passed to CMake whilst configuring. * ``ALWAYS_BUILD_DOCS`` - BOOL. If set to ``TRUE`` and ``BUILD_DOCUMENTATION`` is ``TRUE`` then documentation for API bindings will always be built. Disabling this is useful for faster incremental builds. The documentation can be manually built by invoking the ``api_docs`` target. * ``LINK_TIME_OPTIMIZATION`` - BOOL. If set to ``TRUE`` link time optimization will be enabled. +* ``ENABLE_CFI`` - BOOL. If set to ``TRUE`` will enable Control Flow Integrity security checks. This is only supported by MSVC and Clang and will + fail on other compilers. This requires LINK_TIME_OPTIMIZATION to also be enabled. * ``API_LOG_SYNC`` - BOOL. If set to ``TRUE`` will enable experimental API log sync feature. +* ``WARNINGS_AS_ERRORS`` - STRING. If set to ``TRUE`` compiler warnings will be treated as errors. If set to ``False`` compiler warnings will not be treated as errors. + If set to ``SERIOUS_ONLY`` a subset of compiler warnings will be treated as errors. On the command line these can be passed to ``cmake`` using the ``-D`` option. In ``ccmake`` and ``cmake-gui`` these can be set in the user interface. @@ -328,44 +304,6 @@ link is not created when building under Windows. These notes are help developers and packagers of Z3. -### Boostrapping the CMake build - -Z3's CMake system is experimental and not officially supported. Consequently -Z3's developers have decided that they do not want the CMake files in the -``src/`` and ``examples/`` folders. Instead the ``contrib/cmake/bootstrap.py`` -script copies or hard links them into the correct locations. For context -on this decision see https://github.com/Z3Prover/z3/pull/461 . - -The ``contrib/cmake/bootstrap.py create`` command just copies over files which makes -development harder because you have to copy your modifications over to the -files in ``contrib/cmake`` for your changes to committed to git. If you are on a UNIX like -platform you can create hard links instead by running - -``` -contrib/cmake/boostrap.py create --hard-link -``` - -Using hard links means that modifying any of the "copied" files also modifies the -file under version control. Using hard links also means that the file modification time -will appear correct (i.e. the hard-linked "copies" have the same file modification time -as the corresponding file under version control) which means CMake will correctly reconfigure -when invoked. This is why using symbolic links is not an option because the file modification -time of a symbolic link is not the same as the file modification of the file being pointed to. - -Unfortunately a downside to using hard links (or just plain copies) is that if -you pull down new code (i.e. ``git pull``) then some of the CMake files under -version control may change but the corresponding hard-linked "copies" will not. - -This mean that (regardless of whether or not you use hard links) every time you -pull down new code or change branch or do an interactive rebase you must run -(with or without ``--hard-link``): - -``` -contrb/cmake/boostrap.py create -``` - -in order to be sure that the copied CMake files are not out of date. - ### Install/Uninstall Install and uninstall targets are supported. Use ``CMAKE_INSTALL_PREFIX`` to @@ -447,3 +385,13 @@ It is tempting use file-globbing in ``CMakeLists.txt`` to find a set for files m use them as the sources to build a target. This however is a bad idea because it prevents CMake from knowing when it needs to rerun itself. This is why source file names are explicitly listed in the ``CMakeLists.txt`` so that when changes are made the source files used to build a target automatically triggers a rerun of CMake. Long story short. Don't use file globbing. + +### Serious warning flags + +By default the `WARNINGS_AS_ERRORS` flag is set to `SERIOUS_ONLY` which means +some warnings will be treated as errors. These warnings are controlled by the +relevant `*_WARNINGS_AS_ERRORS` list defined in +`cmake/compiler_warnings.cmake`. + +Additional warnings should only be added here if the warnings has no false +positives. diff --git a/README.md b/README.md index f92a5389a..197928877 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z ## Build status -| Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | -| ----------- | ----------- | ---------- | ---------- | ---------- | --- | -![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge) +| Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | TravisCI | +| ----------- | ----------- | ---------- | ---------- | ---------- | --- | -------- | +[![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=4) | [![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=7) | [![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=3) | [![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=6) | [![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=5) | [![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) [1]: #building-z3-on-windows-using-visual-studio-command-prompt [2]: #building-z3-using-make-and-gccclang diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 357c17e78..ec05160da 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,5 +1,15 @@ RELEASE NOTES +Version 4.5.x +============= +- New features (including): + - A new string solver from University of Waterloo + - A new linear real arithmetic solver + - Changed behavior for optimization commands from the SMT2 command-line interface. + Objective values are no longer printed by default. They can be retrieved by + issuing the command (get-objectives). Pareto front objectives are accessed by + issuing multiple (check-sat) calls until it returns unsat. + Version 4.5.0 ============= diff --git a/contrib/cmake/cmake/Z3Config.cmake.in b/cmake/Z3Config.cmake.in similarity index 100% rename from contrib/cmake/cmake/Z3Config.cmake.in rename to cmake/Z3Config.cmake.in diff --git a/contrib/cmake/cmake/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in similarity index 100% rename from contrib/cmake/cmake/cmake_uninstall.cmake.in rename to cmake/cmake_uninstall.cmake.in diff --git a/contrib/cmake/cmake/compiler_lto.cmake b/cmake/compiler_lto.cmake similarity index 100% rename from contrib/cmake/cmake/compiler_lto.cmake rename to cmake/compiler_lto.cmake diff --git a/cmake/compiler_warnings.cmake b/cmake/compiler_warnings.cmake new file mode 100644 index 000000000..183f490dd --- /dev/null +++ b/cmake/compiler_warnings.cmake @@ -0,0 +1,140 @@ +################################################################################ +# Compiler warning flags +################################################################################ +# These are passed to relevant compiler provided they are supported +set(GCC_AND_CLANG_WARNINGS + "-Wall" +) +set(GCC_ONLY_WARNINGS "") +set(CLANG_ONLY_WARNINGS "") +set(MSVC_WARNINGS "/W3") + +################################################################################ +# Serious warnings +################################################################################ +# This declares the flags that are passed to the compiler when +# `WARNINGS_AS_ERRORS` is set to `SERIOUS_ONLY`. Only flags that are supported +# by the compiler are used. +# +# In effect this a "whitelist" approach where we explicitly tell the compiler +# which warnings we want to be treated as errors. The alternative would be a +# "blacklist" approach where we ask the compiler to treat all warnings are +# treated as errors but then we explicitly list which warnings which should be +# allowed. +# +# The "whitelist" approach seems simpiler because we can incrementally add +# warnings we "think are serious". + +# TODO: Add more warnings that are considered serious enough that we should +# treat them as errors. +set(GCC_AND_CLANG_WARNINGS_AS_ERRORS + # https://clang.llvm.org/docs/DiagnosticsReference.html#wodr + "-Werror=odr" +) +set(GCC_WARNINGS_AS_ERRORS + "" +) +set(CLANG_WARNINGS_AS_ERRORS + # https://clang.llvm.org/docs/DiagnosticsReference.html#wdelete-non-virtual-dtor + "-Werror=delete-non-virtual-dtor" + # https://clang.llvm.org/docs/DiagnosticsReference.html#woverloaded-virtual + "-Werror=overloaded-virtual" +) + +################################################################################ +# Test warning/error flags +################################################################################ +set(WARNING_FLAGS_TO_CHECK "") +set(WARNING_AS_ERROR_FLAGS_TO_CHECK "") +if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS}) + list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_ONLY_WARNINGS}) + list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS_AS_ERRORS}) + list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_WARNINGS_AS_ERRORS}) +elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS}) + list(APPEND WARNING_FLAGS_TO_CHECK ${CLANG_ONLY_WARNINGS}) + list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS_AS_ERRORS}) + list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${CLANG_WARNINGS_AS_ERRORS}) + # FIXME: Remove "x.." when CMP0054 is set to NEW +elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") + list(APPEND WARNING_FLAGS_TO_CHECK ${MSVC_WARNINGS}) + + # CMake's default flags include /W3 already so remove them if + # they already exist. + if ("${CMAKE_CXX_FLAGS}" MATCHES "/W3") + string(REPLACE "/W3" "" _cmake_cxx_flags_remove_w3 "${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "${_cmake_cxx_flags_remove_w3}" CACHE STRING "" FORCE) + endif() +else() + message(AUTHOR_WARNING "Unknown compiler") +endif() + +# Loop through flags and use the ones which the compiler supports +foreach (flag ${WARNING_FLAGS_TO_CHECK}) + z3_add_cxx_flag("${flag}") +endforeach() + +# TODO: Remove this eventually. +# Detect legacy `WARNINGS_AS_ERRORS` boolean option and covert to new +# to new option type. +get_property( + WARNINGS_AS_ERRORS_CACHE_VAR_TYPE + CACHE + WARNINGS_AS_ERRORS + PROPERTY + TYPE +) +if ("${WARNINGS_AS_ERRORS_CACHE_VAR_TYPE}" STREQUAL "BOOL") + message(WARNING "Detected legacy WARNINGS_AS_ERRORS option. Upgrading") + set(WARNINGS_AS_ERRORS_DEFAULT "${WARNINGS_AS_ERRORS}") + # Delete old entry + unset(WARNINGS_AS_ERRORS CACHE) +else() + set(WARNINGS_AS_ERRORS_DEFAULT "SERIOUS_ONLY") +endif() + +set(WARNINGS_AS_ERRORS + ${WARNINGS_AS_ERRORS_DEFAULT} + CACHE STRING + "Treat warnings as errors. ON, OFF, or SERIOUS_ONLY" +) + # Set GUI options +set_property( + CACHE + WARNINGS_AS_ERRORS + PROPERTY STRINGS + "ON;OFF;SERIOUS_ONLY" +) + +if ("${WARNINGS_AS_ERRORS}" STREQUAL "ON") + message(STATUS "Treating compiler warnings as errors") + if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")) + list(APPEND Z3_COMPONENT_CXX_FLAGS "-Werror") + # FIXME: Remove "x.." when CMP0054 is set to NEW + elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") + list(APPEND Z3_COMPONENT_CXX_FLAGS "/WX") + else() + message(AUTHOR_WARNING "Unknown compiler") + endif() +elseif ("${WARNINGS_AS_ERRORS}" STREQUAL "SERIOUS_ONLY") + message(STATUS "Treating only serious compiler warnings as errors") + # Loop through the flags + foreach (flag ${WARNING_AS_ERROR_FLAGS_TO_CHECK}) + # Add globally because some flags need to be passed at link time. + z3_add_cxx_flag("${flag}" GLOBAL) + endforeach() +elseif ("${WARNINGS_AS_ERRORS}" STREQUAL "OFF") + message(STATUS "Not treating compiler warnings as errors") + # FIXME: Remove "x.." when CMP0054 is set to NEW + if ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") + # Warnings as errors is off by default for MSVC so setting this + # is not necessary but this duplicates the behaviour of the old + # build system. + list(APPEND Z3_COMPONENT_CXX_FLAGS "/WX-") + endif() +else() + message(FATAL_ERROR + "WARNINGS_AS_ERRORS set to unsupported value \"${WARNINGS_AS_ERRORS}\"" + ) +endif() diff --git a/contrib/cmake/cmake/cxx_compiler_flags_overrides.cmake b/cmake/cxx_compiler_flags_overrides.cmake similarity index 100% rename from contrib/cmake/cmake/cxx_compiler_flags_overrides.cmake rename to cmake/cxx_compiler_flags_overrides.cmake diff --git a/contrib/cmake/cmake/git_utils.cmake b/cmake/git_utils.cmake similarity index 96% rename from contrib/cmake/cmake/git_utils.cmake rename to cmake/git_utils.cmake index aa7f38825..f98aca205 100644 --- a/contrib/cmake/cmake/git_utils.cmake +++ b/cmake/git_utils.cmake @@ -99,7 +99,9 @@ function(get_git_head_hash GIT_DIR OUTPUT_VAR) message(FATAL_ERROR \""${GIT_DIR}\" is not an absolute path") endif() find_package(Git) - if (NOT Git_FOUND) + # NOTE: Use `GIT_FOUND` rather than `Git_FOUND` which was only + # available in CMake >= 3.5 + if (NOT GIT_FOUND) set(${OUTPUT_VAR} "GIT-NOTFOUND" PARENT_SCOPE) return() endif() @@ -146,7 +148,9 @@ function(get_git_head_describe GIT_DIR OUTPUT_VAR) message(FATAL_ERROR \""${GIT_DIR}\" is not an absolute path") endif() find_package(Git) - if (NOT Git_FOUND) + # NOTE: Use `GIT_FOUND` rather than `Git_FOUND` which was only + # available in CMake >= 3.5 + if (NOT GIT_FOUND) set(${OUTPUT_VAR} "GIT-NOTFOUND" PARENT_SCOPE) return() endif() diff --git a/contrib/cmake/cmake/modules/FindDotNetToolchain.cmake b/cmake/modules/FindDotNetToolchain.cmake similarity index 100% rename from contrib/cmake/cmake/modules/FindDotNetToolchain.cmake rename to cmake/modules/FindDotNetToolchain.cmake diff --git a/contrib/cmake/cmake/modules/FindGMP.cmake b/cmake/modules/FindGMP.cmake similarity index 100% rename from contrib/cmake/cmake/modules/FindGMP.cmake rename to cmake/modules/FindGMP.cmake diff --git a/contrib/cmake/cmake/msvc_legacy_quirks.cmake b/cmake/msvc_legacy_quirks.cmake similarity index 97% rename from contrib/cmake/cmake/msvc_legacy_quirks.cmake rename to cmake/msvc_legacy_quirks.cmake index 2ca20277c..36fe82bb3 100644 --- a/contrib/cmake/cmake/msvc_legacy_quirks.cmake +++ b/cmake/msvc_legacy_quirks.cmake @@ -184,7 +184,12 @@ foreach (_build_type ${_build_types_as_upper}) # Address space layout randomization # See https://msdn.microsoft.com/en-us/library/bb384887.aspx string(APPEND CMAKE_EXE_LINKER_FLAGS_${_build_type} " /DYNAMICBASE") - string(APPEND CMAKE_SHARED_LINKER_FLAGS_${_build_type} " /DYNAMICBASE:NO") + if(ENABLE_CFI) + # CFI requires /DYNAMICBASE to be enabled. + string(APPEND CMAKE_SHARED_LINKER_FLAGS_${_build_type} " /DYNAMICBASE") + else() + string(APPEND CMAKE_SHARED_LINKER_FLAGS_${_build_type} " /DYNAMICBASE:NO") + endif() # FIXME: This is not necessary. This is MSVC's default. # Indicate that the executable is compatible with DEP diff --git a/contrib/cmake/cmake/target_arch_detect.cmake b/cmake/target_arch_detect.cmake similarity index 100% rename from contrib/cmake/cmake/target_arch_detect.cmake rename to cmake/target_arch_detect.cmake diff --git a/contrib/cmake/cmake/target_arch_detect.cpp b/cmake/target_arch_detect.cpp similarity index 100% rename from contrib/cmake/cmake/target_arch_detect.cpp rename to cmake/target_arch_detect.cpp diff --git a/contrib/cmake/cmake/z3_add_component.cmake b/cmake/z3_add_component.cmake similarity index 68% rename from contrib/cmake/cmake/z3_add_component.cmake rename to cmake/z3_add_component.cmake index b90aa2fe7..b70838750 100644 --- a/contrib/cmake/cmake/z3_add_component.cmake +++ b/cmake/z3_add_component.cmake @@ -55,6 +55,9 @@ endfunction() # SOURCES source1 [source2...] # [COMPONENT_DEPENDENCIES component1 [component2...]] # [PYG_FILES pygfile1 [pygfile2...]] +# [TACTIC_HEADERS header_file1 [header_file2...]] +# [EXTRA_REGISTER_MODULE_HEADERS header_file1 [header_file2...]] +# [MEMORY_INIT_FINALIZER_HEADERS header_file1 [header_file2...]] # ) # # Declares a Z3 component (as a CMake "object library") with target name @@ -80,14 +83,32 @@ endfunction() # The optional ``PYG_FILES`` keyword should be followed by a list of one or # more ``.pyg`` files that should used to be generate # ``_params.hpp`` header files used by the ``component_name``. +# This generated file will automatically be scanned for the register module +# declarations (i.e. ``REG_PARAMS()``, ``REG_MODULE_PARAMS()``, and +# ``REG_MODULE_DESCRIPTION()``). # +# The optional ``TACTIC_HEADERS`` keyword should be followed by a list of one or +# more header files that declare a tactic and/or a probe that is part of this +# component (see ``ADD_TACTIC()`` and ``ADD_PROBE()``). +# +# The optional ``EXTRA_REGISTER_MODULE_HEADERS`` keyword should be followed by a list +# of one or more header files that contain module registration declarations. +# NOTE: The header files generated from ``.pyg`` files don't need to be included. +# +# The optional ``MEMORY_INIT_FINALIZER_HEADERS`` keyword should be followed by a list +# of one or more header files that contain memory initializer/finalizer declarations +# (i.e. ``ADD_INITIALIZER()`` or ``ADD_FINALIZER()``). macro(z3_add_component component_name) - CMAKE_PARSE_ARGUMENTS("Z3_MOD" "NOT_LIBZ3_COMPONENT" "" "SOURCES;COMPONENT_DEPENDENCIES;PYG_FILES" ${ARGN}) + CMAKE_PARSE_ARGUMENTS("Z3_MOD" + "NOT_LIBZ3_COMPONENT" + "" + "SOURCES;COMPONENT_DEPENDENCIES;PYG_FILES;TACTIC_HEADERS;EXTRA_REGISTER_MODULE_HEADERS;MEMORY_INIT_FINALIZER_HEADERS" ${ARGN}) message(STATUS "Adding component ${component_name}") # Note: We don't check the sources exist here because # they might be generated files that don't exist yet. set(_list_generated_headers "") + set_property(GLOBAL PROPERTY Z3_${component_name}_REGISTER_MODULE_HEADERS "") foreach (pyg_file ${Z3_MOD_PYG_FILES}) set(_full_pyg_file_path "${CMAKE_CURRENT_SOURCE_DIR}/${pyg_file}") if (NOT (EXISTS "${_full_pyg_file_path}")) @@ -112,11 +133,70 @@ macro(z3_add_component component_name) VERBATIM ) list(APPEND _list_generated_headers "${_full_output_file_path}") + + # FIXME: This implicit dependency of a generated file depending on + # generated files was inherited from the old build system. + + # Typically generated headers contain `REG_PARAMS()`, `REG_MODULE_PARAMS()` + # and `REG_MODULE_DESCRIPTION()` declarations so add to the list of + # header files to scan. + set_property(GLOBAL + APPEND + PROPERTY Z3_${component_name}_REGISTER_MODULE_HEADERS + "${_full_output_file_path}" + ) endforeach() unset(_full_include_dir_path) unset(_full_output_file_path) unset(_output_file) + # Add tactic/probe headers to global property + set_property(GLOBAL PROPERTY Z3_${component_name}_TACTIC_HEADERS "") + foreach (tactic_header ${Z3_MOD_TACTIC_HEADERS}) + set(_full_tactic_header_file_path "${CMAKE_CURRENT_SOURCE_DIR}/${tactic_header}") + if (NOT (EXISTS "${_full_tactic_header_file_path}")) + message(FATAL_ERROR "\"${_full_tactic_header_file_path}\" does not exist") + endif() + set_property(GLOBAL + APPEND + PROPERTY Z3_${component_name}_TACTIC_HEADERS + "${_full_tactic_header_file_path}" + ) + endforeach() + unset(_full_tactic_header_file_path) + + # Add additional register module headers + foreach (extra_register_module_header ${Z3_MOD_EXTRA_REGISTER_MODULE_HEADERS}) + set(_full_extra_register_module_header_path + "${CMAKE_CURRENT_SOURCE_DIR}/${extra_register_module_header}" + ) + if (NOT (EXISTS "${_full_extra_register_module_header_path}")) + message(FATAL_ERROR "\"${_full_extra_register_module_header_path}\" does not exist") + endif() + set_property(GLOBAL + APPEND + PROPERTY Z3_${component_name}_REGISTER_MODULE_HEADERS + "${_full_extra_register_module_header_path}" + ) + endforeach() + unset(_full_extra_register_module_header) + + # Add memory initializer/finalizer headers to global property + set_property(GLOBAL PROPERTY Z3_${component_name}_MEM_INIT_FINALIZER_HEADERS "") + foreach (memory_init_finalizer_header ${Z3_MOD_MEMORY_INIT_FINALIZER_HEADERS}) + set(_full_memory_init_finalizer_header_path + "${CMAKE_CURRENT_SOURCE_DIR}/${memory_init_finalizer_header}") + if (NOT (EXISTS "${_full_memory_init_finalizer_header_path}")) + message(FATAL_ERROR "\"${_full_memory_init_finalizer_header_path}\" does not exist") + endif() + set_property(GLOBAL + APPEND + PROPERTY Z3_${component_name}_MEM_INIT_FINALIZER_HEADERS + "${_full_memory_init_finalizer_header_path}" + ) + endforeach() + unset(_full_memory_init_finalizer_header_path) + # Using "object" libraries here means we have a convenient # name to refer to a component in CMake but we don't actually # create a static/library from them. This allows us to easily @@ -191,25 +271,33 @@ macro(z3_add_install_tactic_rule) ) endif() z3_expand_dependencies(_expanded_components ${ARGN}) - # Get paths to search - set(_search_paths "") + + # Get header files that declare tactics/probes + set(_tactic_header_files "") foreach (dependency ${_expanded_components}) - get_property(_dep_include_dirs GLOBAL PROPERTY Z3_${dependency}_INCLUDES) - list(APPEND _search_paths ${_dep_include_dirs}) + get_property(_component_tactic_header_files + GLOBAL + PROPERTY Z3_${dependency}_TACTIC_HEADERS + ) + list(APPEND _tactic_header_files ${_component_tactic_header_files}) endforeach() + unset(_component_tactic_header_files) + list(APPEND _search_paths "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") add_custom_command(OUTPUT "install_tactic.cpp" COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/mk_install_tactic_cpp.py" "${CMAKE_CURRENT_BINARY_DIR}" - ${_search_paths} + ${_tactic_header_files} DEPENDS "${CMAKE_SOURCE_DIR}/scripts/mk_install_tactic_cpp.py" ${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES} - ${_expanded_components} + ${_tactic_header_files} COMMENT "Generating \"${CMAKE_CURRENT_BINARY_DIR}/install_tactic.cpp\"" ${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG} VERBATIM ) + unset(_expanded_components) + unset(_tactic_header_files) endmacro() macro(z3_add_memory_initializer_rule) @@ -230,18 +318,31 @@ macro(z3_add_memory_initializer_rule) list(APPEND _search_paths ${_dep_include_dirs}) endforeach() list(APPEND _search_paths "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") + + # Get header files that declare initializers and finalizers + set(_mem_init_finalize_headers "") + foreach (dependency ${_expanded_components}) + get_property(_dep_mem_init_finalize_headers + GLOBAL + PROPERTY Z3_${dependency}_MEM_INIT_FINALIZER_HEADERS + ) + list(APPEND _mem_init_finalize_headers ${_dep_mem_init_finalize_headers}) + endforeach() + add_custom_command(OUTPUT "mem_initializer.cpp" COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/mk_mem_initializer_cpp.py" "${CMAKE_CURRENT_BINARY_DIR}" - ${_search_paths} + ${_mem_init_finalize_headers} DEPENDS "${CMAKE_SOURCE_DIR}/scripts/mk_mem_initializer_cpp.py" ${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES} - ${_expanded_components} + ${_mem_init_finalize_headers} COMMENT "Generating \"${CMAKE_CURRENT_BINARY_DIR}/mem_initializer.cpp\"" ${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG} VERBATIM ) + unset(_mem_init_finalize_headers) + unset(_expanded_components) endmacro() macro(z3_add_gparams_register_modules_rule) @@ -255,23 +356,27 @@ macro(z3_add_gparams_register_modules_rule) ) endif() z3_expand_dependencies(_expanded_components ${ARGN}) - # Get paths to search - set(_search_paths "") + + # Get the list of header files to parse + set(_register_module_header_files "") foreach (dependency ${_expanded_components}) - get_property(_dep_include_dirs GLOBAL PROPERTY Z3_${dependency}_INCLUDES) - list(APPEND _search_paths ${_dep_include_dirs}) + get_property(_component_register_module_header_files GLOBAL PROPERTY Z3_${dependency}_REGISTER_MODULE_HEADERS) + list(APPEND _register_module_header_files ${_component_register_module_header_files}) endforeach() - list(APPEND _search_paths "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") + unset(_component_register_module_header_files) + add_custom_command(OUTPUT "gparams_register_modules.cpp" COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/mk_gparams_register_modules_cpp.py" "${CMAKE_CURRENT_BINARY_DIR}" - ${_search_paths} + ${_register_module_header_files} DEPENDS "${CMAKE_SOURCE_DIR}/scripts/mk_gparams_register_modules_cpp.py" ${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES} - ${_expanded_components} + ${_register_module_header_files} COMMENT "Generating \"${CMAKE_CURRENT_BINARY_DIR}/gparams_register_modules.cpp\"" ${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG} VERBATIM ) + unset(_expanded_components) + unset(_register_module_header_files) endmacro() diff --git a/contrib/cmake/cmake/z3_add_cxx_flag.cmake b/cmake/z3_add_cxx_flag.cmake similarity index 68% rename from contrib/cmake/cmake/z3_add_cxx_flag.cmake rename to cmake/z3_add_cxx_flag.cmake index 8bffd7de3..d2624d890 100644 --- a/contrib/cmake/cmake/z3_add_cxx_flag.cmake +++ b/cmake/z3_add_cxx_flag.cmake @@ -2,12 +2,13 @@ include(CheckCXXCompilerFlag) include(CMakeParseArguments) function(z3_add_cxx_flag flag) - CMAKE_PARSE_ARGUMENTS(z3_add_flag "REQUIRED" "" "" ${ARGN}) + CMAKE_PARSE_ARGUMENTS(z3_add_flag "REQUIRED;GLOBAL" "" "" ${ARGN}) string(REPLACE "-" "_" SANITIZED_FLAG_NAME "${flag}") string(REPLACE "/" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") string(REPLACE "=" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") string(REPLACE " " "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") string(REPLACE ":" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") + string(REPLACE "+" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") unset(HAS_${SANITIZED_FLAG_NAME}) CHECK_CXX_COMPILER_FLAG("${flag}" HAS_${SANITIZED_FLAG_NAME}) if (z3_add_flag_REQUIRED AND NOT HAS_${SANITIZED_FLAG_NAME}) @@ -15,8 +16,13 @@ function(z3_add_cxx_flag flag) endif() if (HAS_${SANITIZED_FLAG_NAME}) message(STATUS "C++ compiler supports ${flag}") - list(APPEND Z3_COMPONENT_CXX_FLAGS "${flag}") - set(Z3_COMPONENT_CXX_FLAGS "${Z3_COMPONENT_CXX_FLAGS}" PARENT_SCOPE) + if (z3_add_flag_GLOBAL) + # Set globally + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag} " PARENT_SCOPE) + else() + list(APPEND Z3_COMPONENT_CXX_FLAGS "${flag}") + set(Z3_COMPONENT_CXX_FLAGS "${Z3_COMPONENT_CXX_FLAGS}" PARENT_SCOPE) + endif() else() message(STATUS "C++ compiler does not support ${flag}") endif() diff --git a/contrib/cmake/cmake/z3_append_linker_flag_list_to_target.cmake b/cmake/z3_append_linker_flag_list_to_target.cmake similarity index 100% rename from contrib/cmake/cmake/z3_append_linker_flag_list_to_target.cmake rename to cmake/z3_append_linker_flag_list_to_target.cmake diff --git a/contrib/ci/Dockerfiles/z3_base_ubuntu32_16.04.Dockerfile b/contrib/ci/Dockerfiles/z3_base_ubuntu32_16.04.Dockerfile new file mode 100644 index 000000000..d8a32edea --- /dev/null +++ b/contrib/ci/Dockerfiles/z3_base_ubuntu32_16.04.Dockerfile @@ -0,0 +1,50 @@ +# This base image is not officially supported by Docker it +# is generated by running +# ``` +# ./update.sh xenial +# ``` +# from git@github.com:daald/docker-brew-ubuntu-core-32bit.git +# at commit 34ea593b40b423755b7d46b6c8c89fc8162ea74b +# +# We could actually store the image generated by this Dockerfile +# rather than just the bare image. However given we have a TravisCI +# cache I'm not sure if it faster to use the TravisCI cache or to +# download from DockerHub everytime. +FROM z3prover/ubuntu32:16.04 + +RUN apt-get update && \ + apt-get -y --no-install-recommends install \ + binutils \ + clang \ + clang-3.9 \ + cmake \ + doxygen \ + default-jdk \ + gcc \ + gcc-5 \ + git \ + graphviz \ + g++ \ + g++ \ + libgmp-dev \ + libgomp1 \ + libomp5 \ + libomp-dev \ + make \ + mono-devel \ + ninja-build \ + python3 \ + python3-setuptools \ + python2.7 \ + python-setuptools \ + sudo + +# Create `user` user for container with password `user`. and give it +# password-less sudo access +RUN useradd -m user && \ + echo user:user | chpasswd && \ + cp /etc/sudoers /etc/sudoers.bak && \ + echo 'user ALL=(root) NOPASSWD: ALL' >> /etc/sudoers +USER user +WORKDIR /home/user + diff --git a/contrib/ci/Dockerfiles/z3_base_ubuntu_14.04.Dockerfile b/contrib/ci/Dockerfiles/z3_base_ubuntu_14.04.Dockerfile new file mode 100644 index 000000000..c28e59e97 --- /dev/null +++ b/contrib/ci/Dockerfiles/z3_base_ubuntu_14.04.Dockerfile @@ -0,0 +1,35 @@ +FROM ubuntu:14.04 + +RUN apt-get update && \ + apt-get -y --no-install-recommends install \ + binutils \ + clang-3.9 \ + cmake \ + doxygen \ + default-jdk \ + gcc-multilib \ + gcc-4.8-multilib \ + git \ + graphviz \ + g++-multilib \ + g++-4.8-multilib \ + libgmp-dev \ + libgomp1 \ + lib32gomp1 \ + make \ + mono-devel \ + ninja-build \ + python3 \ + python3-setuptools \ + python2.7 \ + python-setuptools + +# Create `user` user for container with password `user`. and give it +# password-less sudo access +RUN useradd -m user && \ + echo user:user | chpasswd && \ + cp /etc/sudoers /etc/sudoers.bak && \ + echo 'user ALL=(root) NOPASSWD: ALL' >> /etc/sudoers +USER user +WORKDIR /home/user + diff --git a/contrib/ci/Dockerfiles/z3_base_ubuntu_16.04.Dockerfile b/contrib/ci/Dockerfiles/z3_base_ubuntu_16.04.Dockerfile new file mode 100644 index 000000000..98a5a3e09 --- /dev/null +++ b/contrib/ci/Dockerfiles/z3_base_ubuntu_16.04.Dockerfile @@ -0,0 +1,38 @@ +FROM ubuntu:16.04 + +RUN apt-get update && \ + apt-get -y --no-install-recommends install \ + binutils \ + clang \ + clang-3.9 \ + cmake \ + doxygen \ + default-jdk \ + gcc-multilib \ + gcc-5-multilib \ + git \ + graphviz \ + g++-multilib \ + g++-5-multilib \ + libgmp-dev \ + libgomp1 \ + libomp5 \ + libomp-dev \ + make \ + mono-devel \ + ninja-build \ + python3 \ + python3-setuptools \ + python2.7 \ + python-setuptools \ + sudo + +# Create `user` user for container with password `user`. and give it +# password-less sudo access +RUN useradd -m user && \ + echo user:user | chpasswd && \ + cp /etc/sudoers /etc/sudoers.bak && \ + echo 'user ALL=(root) NOPASSWD: ALL' >> /etc/sudoers +USER user +WORKDIR /home/user + diff --git a/contrib/ci/Dockerfiles/z3_build.Dockerfile b/contrib/ci/Dockerfiles/z3_build.Dockerfile new file mode 100644 index 000000000..2d16d5394 --- /dev/null +++ b/contrib/ci/Dockerfiles/z3_build.Dockerfile @@ -0,0 +1,111 @@ +ARG DOCKER_IMAGE_BASE +FROM ${DOCKER_IMAGE_BASE} + + +# Specify defaults. This can be changed when invoking +# `docker build`. +ARG ASAN_BUILD=0 +ARG BUILD_DOCS=0 +ARG CC=gcc +ARG CXX=g++ +ARG DOTNET_BINDINGS=1 +ARG JAVA_BINDINGS=1 +ARG NO_SUPPRESS_OUTPUT=0 +ARG PYTHON_BINDINGS=1 +ARG PYTHON_EXECUTABLE=/usr/bin/python2.7 +ARG RUN_SYSTEM_TESTS=1 +ARG RUN_UNIT_TESTS=1 +ARG TARGET_ARCH=x86_64 +ARG TEST_INSTALL=1 +ARG UBSAN_BUILD=0 +ARG USE_LIBGMP=0 +ARG USE_LTO=0 +ARG USE_OPENMP=1 +ARG Z3_SRC_DIR=/home/user/z3_src +ARG Z3_BUILD_TYPE=RelWithDebInfo +ARG Z3_CMAKE_GENERATOR=Ninja +ARG Z3_INSTALL_PREFIX=/usr +ARG Z3_STATIC_BUILD=0 +# Blank default indicates use latest. +ARG Z3_SYSTEM_TEST_GIT_REVISION +ARG Z3_WARNINGS_AS_ERRORS=SERIOUS_ONLY +ARG Z3_VERBOSE_BUILD_OUTPUT=0 + +ENV \ + ASAN_BUILD=${ASAN_BUILD} \ + BUILD_DOCS=${BUILD_DOCS} \ + CC=${CC} \ + CXX=${CXX} \ + DOTNET_BINDINGS=${DOTNET_BINDINGS} \ + JAVA_BINDINGS=${JAVA_BINDINGS} \ + NO_SUPPRESS_OUTPUT=${NO_SUPPRESS_OUTPUT} \ + PYTHON_BINDINGS=${PYTHON_BINDINGS} \ + PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} \ + RUN_SYSTEM_TESTS=${RUN_SYSTEM_TESTS} \ + RUN_UNIT_TESTS=${RUN_UNIT_TESTS} \ + TARGET_ARCH=${TARGET_ARCH} \ + TEST_INSTALL=${TEST_INSTALL} \ + UBSAN_BUILD=${UBSAN_BUILD} \ + USE_LIBGMP=${USE_LIBGMP} \ + USE_LTO=${USE_LTO} \ + USE_OPENMP=${USE_OPENMP} \ + Z3_SRC_DIR=${Z3_SRC_DIR} \ + Z3_BUILD_DIR=/home/user/z3_build \ + Z3_CMAKE_GENERATOR=${Z3_CMAKE_GENERATOR} \ + Z3_VERBOSE_BUILD_OUTPUT=${Z3_VERBOSE_BUILD_OUTPUT} \ + Z3_STATIC_BUILD=${Z3_STATIC_BUILD} \ + Z3_SYSTEM_TEST_DIR=/home/user/z3_system_test \ + Z3_SYSTEM_TEST_GIT_REVISION=${Z3_SYSTEM_TEST_GIT_REVISION} \ + Z3_WARNINGS_AS_ERRORS=${Z3_WARNINGS_AS_ERRORS} \ + Z3_INSTALL_PREFIX=${Z3_INSTALL_PREFIX} + +# We add context across incrementally to maximal cache reuse + +# Build Z3 +RUN mkdir -p "${Z3_SRC_DIR}" && \ + mkdir -p "${Z3_SRC_DIR}/contrib/ci/scripts" +# Deliberately leave out `contrib` +ADD /cmake ${Z3_SRC_DIR}/cmake/ +ADD /doc ${Z3_SRC_DIR}/doc/ +ADD /examples ${Z3_SRC_DIR}/examples/ +ADD /scripts ${Z3_SRC_DIR}/scripts/ +ADD /src ${Z3_SRC_DIR}/src/ +ADD *.txt *.md RELEASE_NOTES ${Z3_SRC_DIR}/ + +ADD \ + /contrib/ci/scripts/build_z3_cmake.sh \ + /contrib/ci/scripts/set_compiler_flags.sh \ + /contrib/ci/scripts/set_generator_args.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/build_z3_cmake.sh + +# Test building docs +ADD \ + /contrib/ci/scripts/test_z3_docs.sh \ + /contrib/ci/scripts/run_quiet.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_docs.sh + +# Test examples +ADD \ + /contrib/ci/scripts/test_z3_examples_cmake.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_examples_cmake.sh + +# Run unit tests +ADD \ + /contrib/ci/scripts/test_z3_unit_tests_cmake.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_unit_tests_cmake.sh + +# Run system tests +ADD \ + /contrib/ci/scripts/test_z3_system_tests.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_system_tests.sh + +# Test install +ADD \ + /contrib/ci/scripts/test_z3_install_cmake.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_install_cmake.sh diff --git a/contrib/ci/README.md b/contrib/ci/README.md new file mode 100644 index 000000000..2e117c8b1 --- /dev/null +++ b/contrib/ci/README.md @@ -0,0 +1,114 @@ +# Continous integration scripts + +## TravisCI + +For testing on Linux and macOS we use [TravisCI](https://travis-ci.org/) + +TravisCI consumes the `.travis.yml` file in the root of the repository +to tell it how to build and test Z3. + +However the logic for building and test Z3 is kept out of this file +and instead in a set of scripts in `scripts/`. This avoids +coupling the build to TravisCI tightly so we can migrate to another +service if required in the future. + +The scripts rely on a set of environment variables to control the configuration +of the build. The `.travis.yml` declares a list of configuration with each +configuration setting different environment variables. + +Note that the build scripts currently only support Z3 built with CMake. Support +for building Z3 using the older Python/Makefile build system might be added in +the future. + +### Configuration variables + +* `ASAN_BUILD` - Do [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) build (`0` or `1`) +* `BUILD_DOCS` - Build API documentation (`0` or `1`) +* `C_COMPILER` - Path to C Compiler +* `CXX_COMPILER` - Path to C++ Compiler +* `DOTNET_BINDINGS` - Build and test .NET API bindings (`0` or `1`) +* `JAVA_BINDINGS` - Build and test Java API bindings (`0` or `1`) +* `NO_SUPPRESS_OUTPUT` - Don't suppress output of some commands (`0` or `1`) +* `PYTHON_BINDINGS` - Build and test Python API bindings (`0` or `1`) +* `RUN_SYSTEM_TESTS` - Run system tests (`0` or `1`) +* `RUN_UNIT_TESTS` - Run unit tests (`0` or `1`) +* `TARGET_ARCH` - Target architecture (`x86_64` or `i686`) +* `TEST_INSTALL` - Test running `install` target (`0` or `1`) +* `UBSAN_BUILD` - Do [UndefinedBehaviourSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) build (`0` or `1`) +* `USE_LIBGMP` - Use [GNU multiple precision library](https://gmplib.org/) (`0` or `1`) +* `USE_LTO` - Link binaries using link time optimization (`0` or `1`) +* `USE_OPENMP` - Use OpenMP (`0` or `1`) +* `Z3_BUILD_TYPE` - CMake build type (`RelWithDebInfo`, `Release`, `Debug`, or `MinSizeRel`) +* `Z3_CMAKE_GENERATOR` - CMake generator (`Ninja` or `Unix Makefiles`) +* `Z3_VERBOSE_BUILD_OUTPUT` - Show compile commands in CMake builds (`0` or `1`) +* `Z3_STATIC_BUILD` - Build Z3 binaries and libraries statically (`0` or `1`) +* `Z3_SYSTEM_TEST_GIT_REVISION` - Git revision of [z3test](https://github.com/Z3Prover/z3test). If empty lastest revision will be used. +* `Z3_WARNINGS_AS_ERRORS` - Set the `WARNINGS_AS_ERRORS` CMake option pased to Z3 (`OFF`, `ON`, or `SERIOUS_ONLY`) + +### Linux + +For Linux we use Docker to perform the build so that it easily reproducible +on a local machine and so that we can avoid depending on TravisCI's environment +and instead use a Linux distribution of our choice. + +The `scripts/travis_ci_linux_entry_point.sh` script + +1. Creates a base image containing all the dependencies needed to build and test Z3 +2. Builds and tests Z3 using the base image propagating configuration environment + variables (if set) into the build using the `--build-arg` argument of the `docker run` + command. + +If an environemnt variable is not set a defaults value is used which can be +found in `Dockerfiles/z3_build.Dockerfile`. + +#### Linux specific configuration variables + +* `LINUX_BASE` - The base docker image identifier to use (`ubuntu_16.04`, `ubuntu32_16.04`, or `ubuntu_14.04`). + +#### Reproducing a build locally + +A build can be reproduced locally by using the `scripts/travis_ci_linux_entry_point.sh` +script and setting the appropriate environment variable. + +For example lets say we wanted to reproduce the build below. + +```yaml + + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo +``` + +This can be done by running the command + +```bash +LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo scripts/travis_ci_linux_entry_point.sh +``` + +The `docker build` command which we use internally supports caching. What this +means in practice is that re-running the above command will re-use successfully +completed stages of the build provided they haven't changed. This requires that +the `Dockerfiles/z3_build.Dockerfile` is carefully crafted to avoid invalidating +the cache when unrelated files sent to the build context change. + +#### TravisCI docker image cache + +To improve build times the Z3 base docker images are cached using +[TravisCI's cache directory feature](https://docs.travis-ci.com/user/caching). +If the `DOCKER_TRAVIS_CI_CACHE_DIR` environment variable is set (see `.travis.yml`) +then the directory pointed to by the environment variable is used as a cache +for Docker images. + +The logic for this can be found in `scripts/travis_ci_linux_entry_point.sh`. +The build time improvements are rather modest (~ 2 minutes) and the cache is +rather large due to TravisCI giving each configuration its own cache. So this +feature might be removed in the future. + +It may be better to just build the base image once (outside of TravisCI), upload +it to [DockerHub](https://hub.docker.com/) and have the build pull down the pre-built +image everytime. + +An [organization](https://hub.docker.com/u/z3prover/) has been created on +DockerHub for this. + +### macOS + +Not yet implemented. diff --git a/contrib/ci/maintainers.txt b/contrib/ci/maintainers.txt new file mode 100644 index 000000000..caa6798c6 --- /dev/null +++ b/contrib/ci/maintainers.txt @@ -0,0 +1,3 @@ +# Maintainers + +- Dan Liew (@delcypher) diff --git a/contrib/ci/scripts/build_z3_cmake.sh b/contrib/ci/scripts/build_z3_cmake.sh new file mode 100755 index 000000000..76fd0fb84 --- /dev/null +++ b/contrib/ci/scripts/build_z3_cmake.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# This script builds Z3 + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +: ${Z3_SRC_DIR?"Z3_SRC_DIR must be specified"} +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} +: ${Z3_BUILD_TYPE?"Z3_BUILD_TYPE must be specified"} +: ${Z3_CMAKE_GENERATOR?"Z3_CMAKE_GENERATOR must be specified"} +: ${Z3_STATIC_BUILD?"Z3_STATIC_BUILD must be specified"} +: ${USE_OPENMP?"USE_OPENMP must be specified"} +: ${USE_LIBGMP?"USE_LIBGMP must be specified"} +: ${BUILD_DOCS?"BUILD_DOCS must be specified"} +: ${PYTHON_EXECUTABLE?"PYTHON_EXECUTABLE must be specified"} +: ${PYTHON_BINDINGS?"PYTHON_BINDINGS must be specified"} +: ${DOTNET_BINDINGS?"DOTNET_BINDINGS must be specified"} +: ${JAVA_BINDINGS?"JAVA_BINDINGS must be specified"} +: ${USE_LTO?"USE_LTO must be specified"} +: ${Z3_INSTALL_PREFIX?"Z3_INSTALL_PREFIX must be specified"} +: ${Z3_WARNINGS_AS_ERRORS?"Z3_WARNINGS_AS_ERRORS must be specified"} + +ADDITIONAL_Z3_OPTS=() + +# Static or dynamic libz3 +if [ "X${Z3_STATIC_BUILD}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=('-DBUILD_LIBZ3_SHARED=OFF') +else + ADDITIONAL_Z3_OPTS+=('-DBUILD_LIBZ3_SHARED=ON') +fi + +# Use OpenMP? +if [ "X${USE_OPENMP}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=('-DUSE_OPENMP=ON') +else + ADDITIONAL_Z3_OPTS+=('-DUSE_OPENMP=OFF') +fi + +# Use LibGMP? +if [ "X${USE_LIBGMP}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=('-DUSE_LIB_GMP=ON') +else + ADDITIONAL_Z3_OPTS+=('-DUSE_LIB_GMP=OFF') +fi + +# Use link time optimziation? +if [ "X${USE_LTO}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=('-DLINK_TIME_OPTIMIZATION=ON') +else + ADDITIONAL_Z3_OPTS+=('-DLINK_TIME_OPTIMIZATION=OFF') +fi + +# Build API docs? +if [ "X${BUILD_DOCS}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_DOCUMENTATION=ON' \ + '-DALWAYS_BUILD_DOCS=OFF' \ + ) +else + ADDITIONAL_Z3_OPTS+=('-DBUILD_DOCUMENTATION=OFF') +fi + +# Python bindings? +if [ "X${PYTHON_BINDINGS}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_PYTHON_BINDINGS=ON' \ + '-DINSTALL_PYTHON_BINDINGS=ON' \ + ) +else + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_PYTHON_BINDINGS=OFF' \ + '-DINSTALL_PYTHON_BINDINGS=OFF' \ + ) +fi + +# .NET bindings? +if [ "X${DOTNET_BINDINGS}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_DOTNET_BINDINGS=ON' \ + '-DINSTALL_DOTNET_BINDINGS=ON' \ + ) +else + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_DOTNET_BINDINGS=OFF' \ + '-DINSTALL_DOTNET_BINDINGS=OFF' \ + ) +fi + +# Java bindings? +if [ "X${JAVA_BINDINGS}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_JAVA_BINDINGS=ON' \ + '-DINSTALL_JAVA_BINDINGS=ON' \ + ) +else + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_JAVA_BINDINGS=OFF' \ + '-DINSTALL_JAVA_BINDINGS=OFF' \ + ) +fi + +# Set compiler flags +source ${SCRIPT_DIR}/set_compiler_flags.sh + +# Sanity check +if [ ! -e "${Z3_SRC_DIR}/CMakeLists.txt" ]; then + echo "Z3_SRC_DIR is invalid" + exit 1 +fi + +# Make build tree +mkdir -p "${Z3_BUILD_DIR}" +cd "${Z3_BUILD_DIR}" + +# Configure +cmake \ + -G "${Z3_CMAKE_GENERATOR}" \ + -DCMAKE_BUILD_TYPE=${Z3_BUILD_TYPE} \ + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} \ + -DCMAKE_INSTALL_PREFIX=${Z3_INSTALL_PREFIX} \ + -DWARNINGS_AS_ERRORS=${Z3_WARNINGS_AS_ERRORS} \ + "${ADDITIONAL_Z3_OPTS[@]}" \ + "${Z3_SRC_DIR}" + +# Build +source ${SCRIPT_DIR}/set_generator_args.sh +cmake --build $(pwd) "${GENERATOR_ARGS[@]}" diff --git a/contrib/ci/scripts/run_quiet.sh b/contrib/ci/scripts/run_quiet.sh new file mode 100644 index 000000000..5abc910e8 --- /dev/null +++ b/contrib/ci/scripts/run_quiet.sh @@ -0,0 +1,41 @@ +# Simple wrapper function that runs a command suppressing +# it's output. However it's output will be shown in the +# case that `NO_SUPPRESS_OUTPUT` is set to `1` or the command +# fails. +# +# The use case for this trying to avoid large logs on TravisCI +function run_quiet() { + if [ "X${NO_SUPPRESS_OUTPUT}" = "X1" ]; then + "${@}" + else + OLD_SETTINGS="$-" + set +x + set +e + TMP_DIR="${TMP_DIR:-/tmp/}" + STDOUT="${TMP_DIR}/$$.stdout" + STDERR="${TMP_DIR}/$$.stderr" + "${@}" > "${STDOUT}" 2> "${STDERR}" + EXIT_STATUS="$?" + if [ "${EXIT_STATUS}" -ne 0 ]; then + echo "Command \"$@\" failed" + echo "EXIT CODE: ${EXIT_STATUS}" + echo "STDOUT" + echo "" + echo "\`\`\`" + cat ${STDOUT} + echo "\`\`\`" + echo "" + echo "STDERR" + echo "" + echo "\`\`\`" + cat ${STDERR} + echo "\`\`\`" + echo "" + fi + # Clean up + rm "${STDOUT}" "${STDERR}" + [ $( echo "${OLD_SETTINGS}" | grep -c 'e') -ne 0 ] && set -e + [ $( echo "${OLD_SETTINGS}" | grep -c 'x') -ne 0 ] && set -x + return ${EXIT_STATUS} + fi +} diff --git a/contrib/ci/scripts/set_compiler_flags.sh b/contrib/ci/scripts/set_compiler_flags.sh new file mode 100644 index 000000000..7efdecdac --- /dev/null +++ b/contrib/ci/scripts/set_compiler_flags.sh @@ -0,0 +1,46 @@ +# This script should is intended to be included by other +# scripts and should not be executed directly + +: ${TARGET_ARCH?"TARGET_ARCH must be specified"} +: ${ASAN_BUILD?"ASAN_BUILD must be specified"} +: ${UBSAN_BUILD?"UBSAN_BUILD must be specified"} +: ${CC?"CC must be specified"} +: ${CXX?"CXX must be specified"} + +case ${TARGET_ARCH} in + x86_64) + CXXFLAGS="${CXXFLAGS} -m64" + CFLAGS="${CFLAGS} -m64" + ;; + i686) + CXXFLAGS="${CXXFLAGS} -m32" + CFLAGS="${CFLAGS} -m32" + ;; + *) + echo "Unknown arch \"${TARGET_ARCH}\"" + exit 1 +esac + +if [ "X${ASAN_BUILD}" = "X1" ]; then + CXXFLAGS="${CXXFLAGS} -fsanitize=address -fno-omit-frame-pointer" + CFLAGS="${CFLAGS} -fsanitize=address -fno-omit-frame-pointer" +fi + +if [ "X${UBSAN_BUILD}" = "X1" ]; then + CXXFLAGS="${CXXFLAGS} -fsanitize=undefined" + CFLAGS="${CFLAGS} -fsanitize=undefined" +fi + +# Report flags +echo "CXXFLAGS: ${CXXFLAGS}" +echo "CFLAGS: ${CFLAGS}" + +# Report compiler +echo "CC: ${CC}" +${CC} --version +echo "CXX: ${CXX}" +${CXX} --version + +# Export the values +export CFLAGS +export CXXFLAGS diff --git a/contrib/ci/scripts/set_generator_args.sh b/contrib/ci/scripts/set_generator_args.sh new file mode 100644 index 000000000..0ef7b76aa --- /dev/null +++ b/contrib/ci/scripts/set_generator_args.sh @@ -0,0 +1,20 @@ +# This script should is intended to be included by other +# scripts and should not be executed directly + +: ${Z3_CMAKE_GENERATOR?"Z3_CMAKE_GENERATOR must be specified"} +: ${Z3_VERBOSE_BUILD_OUTPUT?"Z3_VERBOSE_BUILD_OUTPUT must be specified"} + +GENERATOR_ARGS=('--') +if [ "${Z3_CMAKE_GENERATOR}" = "Unix Makefiles" ]; then + GENERATOR_ARGS+=("-j$(nproc)") + if [ "X${Z3_VERBOSE_BUILD_OUTPUT}" = "X1" ]; then + GENERATOR_ARGS+=("VERBOSE=1") + fi +elif [ "${Z3_CMAKE_GENERATOR}" = "Ninja" ]; then + if [ "X${Z3_VERBOSE_BUILD_OUTPUT}" = "X1" ]; then + GENERATOR_ARGS+=("-v") + fi +else + echo "Unknown CMake generator \"${Z3_CMAKE_GENERATOR}\"" + exit 1 +fi diff --git a/contrib/ci/scripts/test_z3_docs.sh b/contrib/ci/scripts/test_z3_docs.sh new file mode 100755 index 000000000..6a65ffedd --- /dev/null +++ b/contrib/ci/scripts/test_z3_docs.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" +. ${SCRIPT_DIR}/run_quiet.sh + +set -x +set -e +set -o pipefail + +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} +: ${BUILD_DOCS?"BUILD_DOCS must be specified"} + +# Set CMake generator args +source ${SCRIPT_DIR}/set_generator_args.sh + +cd "${Z3_BUILD_DIR}" + +# Generate documentation +if [ "X${BUILD_DOCS}" = "X1" ]; then + # TODO: Make quiet once we've fixed the build + run_quiet cmake --build $(pwd) --target api_docs "${GENERATOR_ARGS[@]}" +fi + +# TODO: Test or perhaps deploy the built docs? diff --git a/contrib/ci/scripts/test_z3_examples_cmake.sh b/contrib/ci/scripts/test_z3_examples_cmake.sh new file mode 100755 index 000000000..2eda3de7b --- /dev/null +++ b/contrib/ci/scripts/test_z3_examples_cmake.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# This script tests Z3 + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" +. ${SCRIPT_DIR}/run_quiet.sh + +set -x +set -e +set -o pipefail +: ${Z3_SRC_DIR?"Z3_SRC_DIR must be specified"} +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} +: ${PYTHON_BINDINGS?"PYTHON_BINDINGS must be specified"} +: ${PYTHON_EXECUTABLE?"PYTHON_EXECUTABLE must be specified"} +: ${DOTNET_BINDINGS?"DOTNET_BINDINGS must be specified"} +: ${JAVA_BINDINGS?"JAVA_BINDINGS must be specified"} + +# Set compiler flags +source ${SCRIPT_DIR}/set_compiler_flags.sh + +# Set CMake generator args +source ${SCRIPT_DIR}/set_generator_args.sh + +cd "${Z3_BUILD_DIR}" + +# Build and run C example +cmake --build $(pwd) --target c_example "${GENERATOR_ARGS[@]}" +run_quiet examples/c_example_build_dir/c_example + +# Build and run C++ example +cmake --build $(pwd) --target cpp_example "${GENERATOR_ARGS[@]}" +run_quiet examples/cpp_example_build_dir/cpp_example + +# Build and run tptp5 example +cmake --build $(pwd) --target z3_tptp5 "${GENERATOR_ARGS[@]}" +# FIXME: Do something more useful with example +run_quiet examples/tptp_build_dir/z3_tptp5 -help + +# Build an run c_maxsat_example +cmake --build $(pwd) --target c_maxsat_example "${GENERATOR_ARGS[@]}" +run_quiet \ + examples/c_maxsat_example_build_dir/c_maxsat_example \ + ${Z3_SRC_DIR}/examples/maxsat/ex.smt + + +if [ "X${PYTHON_BINDINGS}" = "X1" ]; then + # Run python examples + # `all_interval_series.py` produces a lot of output so just throw + # away output. + # TODO: This example is slow should we remove it from testing? + run_quiet ${PYTHON_EXECUTABLE} python/all_interval_series.py + run_quiet ${PYTHON_EXECUTABLE} python/complex.py + run_quiet ${PYTHON_EXECUTABLE} python/example.py + # FIXME: `hamiltonian.py` example is disabled because its too slow. + #${PYTHON_EXECUTABLE} python/hamiltonian.py + run_quiet ${PYTHON_EXECUTABLE} python/marco.py + run_quiet ${PYTHON_EXECUTABLE} python/mss.py + run_quiet ${PYTHON_EXECUTABLE} python/socrates.py + run_quiet ${PYTHON_EXECUTABLE} python/visitor.py + run_quiet ${PYTHON_EXECUTABLE} python/z3test.py +fi + +if [ "X${DOTNET_BINDINGS}" = "X1" ]; then + # Build .NET example + # FIXME: Move compliation step into CMake target + mcs ${Z3_SRC_DIR}/examples/dotnet/Program.cs /target:exe /out:dotnet_test.exe /reference:Microsoft.Z3.dll /r:System.Numerics.dll + # Run .NET example + run_quiet mono ./dotnet_test.exe +fi + +if [ "X${JAVA_BINDINGS}" = "X1" ]; then + # Build Java example + # FIXME: Move compilation step into CMake target + mkdir -p examples/java + cp ${Z3_SRC_DIR}/examples/java/JavaExample.java examples/java/ + javac examples/java/JavaExample.java -classpath com.microsoft.z3.jar + # Run Java example + if [ "$(uname)" = "Darwin" ]; then + # macOS + export DYLD_LIBRARY_PATH=$(pwd):${DYLD_LIBRARY_PATH} + else + # Assume Linux for now + export LD_LIBRARY_PATH=$(pwd):${LD_LIBRARY_PATH} + fi + run_quiet java -cp .:examples/java:com.microsoft.z3.jar JavaExample +fi + diff --git a/contrib/ci/scripts/test_z3_install_cmake.sh b/contrib/ci/scripts/test_z3_install_cmake.sh new file mode 100755 index 000000000..804158f6f --- /dev/null +++ b/contrib/ci/scripts/test_z3_install_cmake.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +: ${TEST_INSTALL?"TEST_INSTALL must be specified"} +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} + +if [ "X${TEST_INSTALL}" != "X1" ]; then + echo "Skipping install" + exit 0 +fi + +# Set CMake generator args +source ${SCRIPT_DIR}/set_generator_args.sh + +cd "${Z3_BUILD_DIR}" + +sudo cmake --build $(pwd) --target install "${GENERATOR_ARGS[@]}" + +# TODO: Test the installed version in some way diff --git a/contrib/ci/scripts/test_z3_system_tests.sh b/contrib/ci/scripts/test_z3_system_tests.sh new file mode 100755 index 000000000..dfb1084a4 --- /dev/null +++ b/contrib/ci/scripts/test_z3_system_tests.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +set -x +set -e +set -o pipefail + +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} +: ${Z3_BUILD_TYPE?"Z3_BUILD_TYPE must be specified"} +: ${RUN_SYSTEM_TESTS?"RUN_SYSTEM_TESTS must be speicifed"} +: ${PYTHON_BINDINGS?"PYTHON_BINDINGS must be specified"} +: ${PYTHON_EXECUTABLE?"PYTHON_EXECUTABLE must be specified"} +: ${Z3_SYSTEM_TEST_DIR?"Z3_SYSTEM_TEST_DIR must be specified"} + +if [ "X${RUN_SYSTEM_TESTS}" != "X1" ]; then + echo "Skipping system tests" + exit 0 +fi + +Z3_EXE="${Z3_BUILD_DIR}/z3" +Z3_LIB_DIR="${Z3_BUILD_DIR}" + +# Set value if not already defined externally +Z3_SYSTEM_TEST_GIT_URL="${Z3_GIT_URL:-https://github.com/Z3Prover/z3test.git}" + +# Clone repo to destination +mkdir -p "${Z3_SYSTEM_TEST_GIT_URL}" +git clone "${Z3_SYSTEM_TEST_GIT_URL}" "${Z3_SYSTEM_TEST_DIR}" +cd "${Z3_SYSTEM_TEST_DIR}" + +if [ -n "${Z3_SYSTEM_TEST_GIT_REVISION}" ]; then + # If a particular revision is requested then check it out. + # This is useful for reproducible builds + git checkout "${Z3_SYSTEM_TEST_GIT_REVISION}" +fi + +############################################################################### +# Run system tests +############################################################################### + +# SMTLIBv2 tests +${PYTHON_EXECUTABLE} scripts/test_benchmarks.py "${Z3_EXE}" regressions/smt2 + +${PYTHON_EXECUTABLE} scripts/test_benchmarks.py "${Z3_EXE}" regressions/smt2-extra + +if [ "X${Z3_BUILD_TYPE}" = "XDebug" ]; then + ${PYTHON_EXECUTABLE} scripts/test_benchmarks.py "${Z3_EXE}" regressions/smt2-debug +fi + +if [ "X${PYTHON_BINDINGS}" = "X1" ]; then + # Run python binding tests + ${PYTHON_EXECUTABLE} scripts/test_pyscripts.py "${Z3_LIB_DIR}" regressions/python/ +fi + +# FIXME: Run `scripts/test_cs.py` once it has been modified to support mono diff --git a/contrib/ci/scripts/test_z3_unit_tests_cmake.sh b/contrib/ci/scripts/test_z3_unit_tests_cmake.sh new file mode 100755 index 000000000..666673328 --- /dev/null +++ b/contrib/ci/scripts/test_z3_unit_tests_cmake.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" +. ${SCRIPT_DIR}/run_quiet.sh + +set -x +set -e +set -o pipefail + +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} +: ${RUN_UNIT_TESTS?"RUN_UNIT_TESTS must be specified"} + +if [ "X${RUN_UNIT_TESTS}" != "X1" ]; then + echo "Skipping unit tests" + exit 0 +fi + +# Set CMake generator args +source ${SCRIPT_DIR}/set_generator_args.sh + +cd "${Z3_BUILD_DIR}" + +# Build and run internal tests +cmake --build $(pwd) --target test-z3 "${GENERATOR_ARGS[@]}" +# Run all tests that don't require arguments +run_quiet ./test-z3 /a diff --git a/contrib/ci/scripts/travis_ci_entry_point.sh b/contrib/ci/scripts/travis_ci_entry_point.sh new file mode 100755 index 000000000..41bde7230 --- /dev/null +++ b/contrib/ci/scripts/travis_ci_entry_point.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +: ${TRAVIS_OS_NAME?"TRAVIS_OS_NAME should be set"} + +if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + ${SCRIPT_DIR}/travis_ci_osx_entry_point.sh +elif [ "${TRAVIS_OS_NAME}" = "linux" ]; then + ${SCRIPT_DIR}/travis_ci_linux_entry_point.sh +else + echo "Unsupported OS \"${TRAVIS_OS_NAME}\"" + exit 1 +fi diff --git a/contrib/ci/scripts/travis_ci_linux_entry_point.sh b/contrib/ci/scripts/travis_ci_linux_entry_point.sh new file mode 100755 index 000000000..84b2dd400 --- /dev/null +++ b/contrib/ci/scripts/travis_ci_linux_entry_point.sh @@ -0,0 +1,215 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +DOCKER_FILE_DIR="$(cd ${SCRIPT_DIR}/../Dockerfiles; echo $PWD)" + +: ${LINUX_BASE?"LINUX_BASE must be specified"} + + + +# Sanity check. Current working directory should be repo root +if [ ! -f "./README.md" ]; then + echo "Current working directory should be repo root" + exit 1 +fi + +BUILD_OPTS=() +# Override options if they have been provided. +# Otherwise the defaults in the Docker file will be used +if [ -n "${Z3_CMAKE_GENERATOR}" ]; then + BUILD_OPTS+=("--build-arg" "Z3_CMAKE_GENERATOR=${Z3_CMAKE_GENERATOR}") +fi + +if [ -n "${USE_OPENMP}" ]; then + BUILD_OPTS+=("--build-arg" "USE_OPENMP=${USE_OPENMP}") +fi + +if [ -n "${USE_LIBGMP}" ]; then + BUILD_OPTS+=("--build-arg" "USE_LIBGMP=${USE_LIBGMP}") +fi + +if [ -n "${BUILD_DOCS}" ]; then + BUILD_OPTS+=("--build-arg" "BUILD_DOCS=${BUILD_DOCS}") +fi + +if [ -n "${PYTHON_EXECUTABLE}" ]; then + BUILD_OPTS+=("--build-arg" "PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}") +fi + +if [ -n "${PYTHON_BINDINGS}" ]; then + BUILD_OPTS+=("--build-arg" "PYTHON_BINDINGS=${PYTHON_BINDINGS}") +fi + +if [ -n "${DOTNET_BINDINGS}" ]; then + BUILD_OPTS+=("--build-arg" "DOTNET_BINDINGS=${DOTNET_BINDINGS}") +fi + +if [ -n "${JAVA_BINDINGS}" ]; then + BUILD_OPTS+=("--build-arg" "JAVA_BINDINGS=${JAVA_BINDINGS}") +fi + +if [ -n "${USE_LTO}" ]; then + BUILD_OPTS+=("--build-arg" "USE_LTO=${USE_LTO}") +fi + +if [ -n "${Z3_INSTALL_PREFIX}" ]; then + BUILD_OPTS+=("--build-arg" "Z3_INSTALL_PREFIX=${Z3_INSTALL_PREFIX}") +fi + +# TravisCI reserves CC for itself so use a different name +if [ -n "${C_COMPILER}" ]; then + BUILD_OPTS+=("--build-arg" "CC=${C_COMPILER}") +fi + +# TravisCI reserves CXX for itself so use a different name +if [ -n "${CXX_COMPILER}" ]; then + BUILD_OPTS+=("--build-arg" "CXX=${CXX_COMPILER}") +fi + +if [ -n "${TARGET_ARCH}" ]; then + BUILD_OPTS+=("--build-arg" "TARGET_ARCH=${TARGET_ARCH}") +fi + +if [ -n "${ASAN_BUILD}" ]; then + BUILD_OPTS+=("--build-arg" "ASAN_BUILD=${ASAN_BUILD}") +fi + +if [ -n "${UBSAN_BUILD}" ]; then + BUILD_OPTS+=("--build-arg" "UBSAN_BUILD=${UBSAN_BUILD}") +fi + +if [ -n "${TEST_INSTALL}" ]; then + BUILD_OPTS+=("--build-arg" "TEST_INSTALL=${TEST_INSTALL}") +fi + +if [ -n "${RUN_SYSTEM_TESTS}" ]; then + BUILD_OPTS+=("--build-arg" "RUN_SYSTEM_TESTS=${RUN_SYSTEM_TESTS}") +fi + +if [ -n "${Z3_SYSTEM_TEST_GIT_REVISION}" ]; then + BUILD_OPTS+=( \ + "--build-arg" \ + "Z3_SYSTEM_TEST_GIT_REVISION=${Z3_SYSTEM_TEST_GIT_REVISION}" \ + ) +fi + +if [ -n "${RUN_UNIT_TESTS}" ]; then + BUILD_OPTS+=("--build-arg" "RUN_UNIT_TESTS=${RUN_UNIT_TESTS}") +fi + +if [ -n "${Z3_VERBOSE_BUILD_OUTPUT}" ]; then + BUILD_OPTS+=( \ + "--build-arg" \ + "Z3_VERBOSE_BUILD_OUTPUT=${Z3_VERBOSE_BUILD_OUTPUT}" \ + ) +fi + +if [ -n "${Z3_STATIC_BUILD}" ]; then + BUILD_OPTS+=("--build-arg" "Z3_STATIC_BUILD=${Z3_STATIC_BUILD}") +fi + +if [ -n "${NO_SUPPRESS_OUTPUT}" ]; then + BUILD_OPTS+=( \ + "--build-arg" \ + "NO_SUPPRESS_OUTPUT=${NO_SUPPRESS_OUTPUT}" \ + ) +fi + +if [ -n "${Z3_WARNINGS_AS_ERRORS}" ]; then + BUILD_OPTS+=( \ + "--build-arg" \ + "Z3_WARNINGS_AS_ERRORS=${Z3_WARNINGS_AS_ERRORS}" \ + ) +fi + +case ${LINUX_BASE} in + ubuntu_14.04) + BASE_DOCKER_FILE="${DOCKER_FILE_DIR}/z3_base_ubuntu_14.04.Dockerfile" + BASE_DOCKER_IMAGE_NAME="z3_base_ubuntu:14.04" + ;; + ubuntu_16.04) + BASE_DOCKER_FILE="${DOCKER_FILE_DIR}/z3_base_ubuntu_16.04.Dockerfile" + BASE_DOCKER_IMAGE_NAME="z3_base_ubuntu:16.04" + ;; + ubuntu32_16.04) + BASE_DOCKER_FILE="${DOCKER_FILE_DIR}/z3_base_ubuntu32_16.04.Dockerfile" + BASE_DOCKER_IMAGE_NAME="z3_base_ubuntu32:16.04" + ;; + *) + echo "Unknown Linux base ${LINUX_BASE}" + exit 1 + ;; +esac + +# Initially assume that we need to build the base Docker image +MUST_BUILD=1 + +# Travis CI persistent cache. +# +# This inspired by http://rundef.com/fast-travis-ci-docker-build . +# The idea is to cache the built image for subsequent builds to +# reduce build time. +if [ -n "${DOCKER_TRAVIS_CI_CACHE_DIR}" ]; then + CHECKSUM_FILE="${DOCKER_TRAVIS_CI_CACHE_DIR}/${BASE_DOCKER_IMAGE_NAME}.chksum" + CACHED_DOCKER_IMAGE="${DOCKER_TRAVIS_CI_CACHE_DIR}/${BASE_DOCKER_IMAGE_NAME}.gz" + if [ -f "${CACHED_DOCKER_IMAGE}" ]; then + # There's a cached image to use. Check the checksums of the Dockerfile + # match. If they don't that implies we need to build a fresh image. + if [ -f "${CHECKSUM_FILE}" ]; then + CURRENT_DOCKERFILE_CHECKSUM=$(sha256sum "${BASE_DOCKER_FILE}" | awk '{ print $1 }') + CACHED_DOCKERFILE_CHECKSUM=$(cat "${CHECKSUM_FILE}") + if [ "X${CURRENT_DOCKERFILE_CHECKSUM}" = "X${CACHED_DOCKERFILE_CHECKSUM}" ]; then + # Load the cached image + MUST_BUILD=0 + gunzip --stdout "${CACHED_DOCKER_IMAGE}" | docker load + fi + fi + fi +fi + +if [ "${MUST_BUILD}" -eq 1 ]; then + # The base image contains all the dependencies we want to build + # Z3. + docker build -t "${BASE_DOCKER_IMAGE_NAME}" - < "${BASE_DOCKER_FILE}" + + if [ -n "${DOCKER_TRAVIS_CI_CACHE_DIR}" ]; then + # Write image and checksum to cache + docker save "${BASE_DOCKER_IMAGE_NAME}" | \ + gzip > "${CACHED_DOCKER_IMAGE}" + sha256sum "${BASE_DOCKER_FILE}" | awk '{ print $1 }' > \ + "${CHECKSUM_FILE}" + fi +fi + + +DOCKER_MAJOR_VERSION=$(docker info --format '{{.ServerVersion}}' | sed 's/^\([0-9]\+\)\.\([0-9]\+\).*$/\1/') +DOCKER_MINOR_VERSION=$(docker info --format '{{.ServerVersion}}' | sed 's/^\([0-9]\+\)\.\([0-9]\+\).*$/\2/') +DOCKER_BUILD_FILE="${DOCKER_FILE_DIR}/z3_build.Dockerfile" + +if [ "${DOCKER_MAJOR_VERSION}${DOCKER_MINOR_VERSION}" -lt 1705 ]; then + # Workaround limitation in older Docker versions where the FROM + # command cannot be parameterized with an ARG. + sed \ + -e '/^ARG DOCKER_IMAGE_BASE/d' \ + -e 's/${DOCKER_IMAGE_BASE}/'"${BASE_DOCKER_IMAGE_NAME}/" \ + "${DOCKER_BUILD_FILE}" > "${DOCKER_BUILD_FILE}.patched" + DOCKER_BUILD_FILE="${DOCKER_BUILD_FILE}.patched" +else + # This feature landed in Docker 17.05 + # See https://github.com/moby/moby/pull/31352 + BUILD_OPTS+=( \ + "--build-arg" \ + "DOCKER_IMAGE_BASE=${BASE_DOCKER_IMAGE_NAME}" \ + ) +fi + +# Now build Z3 and test it using the created base image +docker build \ + -f "${DOCKER_BUILD_FILE}" \ + "${BUILD_OPTS[@]}" \ + . diff --git a/contrib/ci/scripts/travis_ci_osx_entry_point.sh b/contrib/ci/scripts/travis_ci_osx_entry_point.sh new file mode 100755 index 000000000..03be81647 --- /dev/null +++ b/contrib/ci/scripts/travis_ci_osx_entry_point.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +echo "Not implemented" +exit 1 diff --git a/contrib/cmake/bootstrap.py b/contrib/cmake/bootstrap.py index a3c81fb25..dac08b383 100755 --- a/contrib/cmake/bootstrap.py +++ b/contrib/cmake/bootstrap.py @@ -1,25 +1,13 @@ #!/usr/bin/env python """ -This script is used to copy or delete the -CMake build system files from the contrib/cmake -folder into the their correct location in the Z3 -repository. +This script is an artifact of compromise that was +made when the CMake build system was first introduced +(see #461). -It offers two modes - -* create - This will symlink the ``cmake`` directory and copy (or hard link) -the appropriate files into their correct locations in the repository. - -* remove - This will remove the symlinked ``cmake`` -directory and remove the files added by the above -methods. - -This has the advantage -that editing the hard link edits the underlying file -(making development easier because copying files is -not neccessary) and CMake will regenerate correctly -because the modification time stamps will be correct. +This script now does nothing. It remains only to not +break out-of-tree scripts that build Z3 using CMake. +Eventually this script will be removed. """ import argparse import logging @@ -28,189 +16,6 @@ import pprint import shutil import sys -def get_full_path_to_script(): - return os.path.abspath(__file__) - -def get_cmake_contrib_dir(): - return os.path.dirname(get_full_path_to_script()) - -def get_repo_root_dir(): - r = os.path.dirname(os.path.dirname(get_cmake_contrib_dir())) - assert os.path.isdir(r) - return r - -# These are paths that should be ignored when checking if a folder -# in the ``contrib/cmake`` exists in the root of the repository -verificationExceptions = { - os.path.join(get_repo_root_dir(), 'cmake'), - os.path.join(get_repo_root_dir(), 'cmake', 'modules') -} - -def contribPathToRepoPath(path): - assert path.startswith(get_cmake_contrib_dir()) - stripped = path[len(get_cmake_contrib_dir()) + 1:] # Plus one is to remove leading slash - assert not os.path.isabs(stripped) - logging.debug('stripped:{}'.format(stripped)) - r = os.path.join(get_repo_root_dir(), stripped) - assert os.path.isabs(r) - logging.debug('Converted contrib path "{}" to repo path "{}"'.format(path, r)) - return r - -def verify_mirrored_directory_struture(): - """ - Check that the directories contained in ``contrib/cmake`` exist - in the root of the repo. - """ - for (dirpath, _, _) in os.walk(get_cmake_contrib_dir()): - expectedDir = contribPathToRepoPath(dirpath) - logging.debug('expectedDir:{}'.format(expectedDir)) - if (not (os.path.exists(expectedDir) and os.path.isdir(expectedDir)) and - expectedDir not in verificationExceptions): - logging.error(('Expected to find directory "{}" but it does not exist' - ' or is not a directory').format(expectedDir)) - return 1 - - return 0 - -def mk_sym_link(target, linkName): - logging.info('Making symbolic link target="{}", linkName="{}"'.format(target, linkName)) - if os.path.exists(linkName): - logging.info('Removing existing link "{}"'.format(linkName)) - if not os.path.islink(linkName): - logging.warning('"{}" overwriting file that is not a symlink'.format(linkName)) - delete_path(linkName) - if os.name == 'posix': - os.symlink(target, linkName) - else: - # TODO: Windows does support symlinks but the implementation to do that - # from python is a little complicated so for now lets just copy everyting - logging.warning('Creating symbolic links is not supported. Just making a copy instead') - if os.path.isdir(target): - # Recursively copy directory - shutil.copytree(src=target, dst=linkName, symlinks=False) - else: - # Copy file - assert os.path.isfile(target) - shutil.copy2(src=target, dst=linkName) - -def delete_path(path): - logging.info('Removing "{}"'.format(path)) - if not os.path.exists(path): - logging.warning('"{}" does not exist'.format(path)) - return - if os.path.isdir(path) and not os.path.islink(path): - # FIXME: If we can get symbolic link support on Windows we - # can disallow this completely. - assert os.name == 'nt' - shutil.rmtree(path) - else: - os.remove(path) - -def shouldSkipFile(path): - # Skip this script - if path == get_full_path_to_script(): - return True - # Skip the maintainers file - if path == os.path.join(get_cmake_contrib_dir(), 'maintainers.txt'): - return True - # Skip Vim temporary files - if os.path.basename(path).startswith('.') and path.endswith('.swp'): - return True - return False - - -def create(useHardLinks): - """ - Copy or hard link files in the CMake contrib directory - into the repository where they are intended to live. - - Note that symbolic links for the CMakeLists.txt files - are not appropriate because they won't have the right - file modification time when the files they point to - are modified. This would prevent CMake from correctly - reconfiguring when it detects this is required. - """ - - # Make the ``cmake`` directory a symbolic link. - # We treat this one specially as it is the only directory - # that doesn't already exist in the repository root so - # we can just use a symlink here - linkName = os.path.join(get_repo_root_dir(), 'cmake') - target = os.path.join(get_cmake_contrib_dir(), 'cmake') - specialDir = target - mk_sym_link(target, linkName) - - for (dirPath,_ , fileNames) in os.walk(get_cmake_contrib_dir()): - # Skip the special directory and its children - if dirPath.startswith(specialDir): - logging.info('Skipping directory "{}"'.format(dirPath)) - continue - - for fileName in fileNames: - fileInContrib = os.path.join(dirPath, fileName) - # Skip files - if shouldSkipFile(fileInContrib): - logging.info('Skipping "{}"'.format(fileInContrib)) - continue - fileInRepo = contribPathToRepoPath(fileInContrib) - logging.info('"{}" => "{}"'.format(fileInContrib, fileInRepo)) - if useHardLinks: - if not os.name == 'posix': - logging.error('Hard links are not supported on your platform') - return False - if os.path.exists(fileInRepo): - delete_path(fileInRepo) - os.link(fileInContrib, fileInRepo) - else: - try: - shutil.copy2(src=fileInContrib, dst=fileInRepo) - except shutil.Error as e: - # Can hit this if used created hard links first and then run again without - # wanting hard links - if sys.version_info.major <= 2: - logging.error(e.message) - else: - # Python >= 3 - if isinstance(e, shutil.SameFileError): - logging.error('Trying to copy "{}" to "{}" but they are the same file'.format( - fileInContrib, fileInRepo)) - else: - logging.error(e) - logging.error('You should remove the files using the "remove" mode ' - 'and try to create again. You probably are mixing the ' - 'hard-link and non-hard-link create modes') - return False - return True - -def remove(): - """ - Remove the CMake files from their intended location in - the repository. This is used to remove - the files created by the ``create()`` function. - """ - # This directory is treated specially as it is normally - # a symlink. - linkName = os.path.join(get_repo_root_dir(), 'cmake') - delete_path(linkName) - specialDir = os.path.join(get_cmake_contrib_dir(), 'cmake') - - for (dirPath,_ , fileNames) in os.walk(get_cmake_contrib_dir()): - # Skip the special directory and its children - if dirPath.startswith(specialDir): - logging.info('Skipping directory "{}"'.format(dirPath)) - continue - for fileName in fileNames: - fileInContrib = os.path.join(dirPath, fileName) - # Skip files - if shouldSkipFile(fileInContrib): - logging.info('Skipping "{}"'.format(fileInContrib)) - continue - fileInRepo = contribPathToRepoPath(fileInContrib) - if os.path.exists(fileInRepo): - logging.info('Removing "{}"'.format(fileInRepo)) - delete_path(fileInRepo) - return True - def main(args): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser(description=__doc__) @@ -233,28 +38,10 @@ def main(args): logLevel = getattr(logging, pargs.log_level.upper(),None) logging.basicConfig(level=logLevel) - - # Before we start make sure we can transplant the CMake files on to - # repository - if verify_mirrored_directory_struture() != 0: - logging.error('"{}" does not mirror "{}"'.format(get_cmake_contrib_dir(), get_repo_root_dir())) - return 1 - - if pargs.mode == "create": - if not create(useHardLinks=pargs.hard_link): - logging.error("Failed to create") - return 1 - elif pargs.mode == "create_hard_link": - if not create(useHardLinks=True): - logging.error("Failed to create_hard_link") - return 1 - elif pargs.mode == "remove": - if not remove(): - logging.error("Failed to remove") - return 1 - else: - logging.error('Unknown mode "{}"'.format(pargs.mode)) - + logging.warning('Use of this script is deprecated. The script will be removed in the future') + logging.warning('Action "{}" ignored'.format(pargs.mode)) + if pargs.hard_link: + logging.warning('Hard link option ignored') return 0 if __name__ == '__main__': diff --git a/contrib/cmake/cmake/compiler_warnings.cmake b/contrib/cmake/cmake/compiler_warnings.cmake deleted file mode 100644 index e02b28b2c..000000000 --- a/contrib/cmake/cmake/compiler_warnings.cmake +++ /dev/null @@ -1,54 +0,0 @@ -set(GCC_AND_CLANG_WARNINGS - "-Wall" -) -set(GCC_ONLY_WARNINGS "") -set(CLANG_ONLY_WARNINGS "") -set(MSVC_WARNINGS "/W3") - -set(WARNING_FLAGS_TO_CHECK "") -if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") - list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS}) - list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_ONLY_WARNINGS}) -elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS}) - list(APPEND WARNING_FLAGS_TO_CHECK ${CLANG_ONLY_WARNINGS}) - # FIXME: Remove "x.." when CMP0054 is set to NEW -elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - list(APPEND WARNING_FLAGS_TO_CHECK ${MSVC_WARNINGS}) - - # CMake's default flags include /W3 already so remove them if - # they already exist. - if ("${CMAKE_CXX_FLAGS}" MATCHES "/W3") - string(REPLACE "/W3" "" _cmake_cxx_flags_remove_w3 "${CMAKE_CXX_FLAGS}") - set(CMAKE_CXX_FLAGS "${_cmake_cxx_flags_remove_w3}" CACHE STRING "" FORCE) - endif() -else() - message(AUTHOR_WARNING "Unknown compiler") -endif() - -# Loop through flags and use the ones which the compiler supports -foreach (flag ${WARNING_FLAGS_TO_CHECK}) - z3_add_cxx_flag("${flag}") -endforeach() - -option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF) -if (WARNINGS_AS_ERRORS) - if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")) - list(APPEND Z3_COMPONENT_CXX_FLAGS "-Werror") - # FIXME: Remove "x.." when CMP0054 is set to NEW - elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - list(APPEND Z3_COMPONENT_CXX_FLAGS "/WX") - else() - message(AUTHOR_WARNING "Unknown compiler") - endif() - message(STATUS "Treating compiler warnings as errors") -else() - message(STATUS "Not treating compiler warnings as errors") - # FIXME: Remove "x.." when CMP0054 is set to NEW - if ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - # Warnings as errors is off by default for MSVC so setting this - # is not necessary but this duplicates the behaviour of the old - # build system. - list(APPEND Z3_COMPONENT_CXX_FLAGS "/WX-") - endif() -endif() diff --git a/contrib/cmake/doc/CMakeLists.txt b/doc/CMakeLists.txt similarity index 100% rename from contrib/cmake/doc/CMakeLists.txt rename to doc/CMakeLists.txt diff --git a/doc/website.dox.in b/doc/website.dox.in index 17a8552d1..f8659ec0b 100644 --- a/doc/website.dox.in +++ b/doc/website.dox.in @@ -4,9 +4,7 @@ Z3 is a high-performance theorem prover being developed at Microsoft Research. - The Z3 website moved to http://github.com/z3prover.. - - The old Z3 websites can be found here and here. + The Z3 website is at http://github.com/z3prover.. This website hosts the automatically generated documentation for the Z3 APIs. diff --git a/doc/z3api.cfg.in b/doc/z3api.cfg.in index 9e946aa7f..9c4b464c2 100644 --- a/doc/z3api.cfg.in +++ b/doc/z3api.cfg.in @@ -704,10 +704,13 @@ INPUT_ENCODING = UTF-8 FILE_PATTERNS = website.dox \ z3_api.h \ z3_algebraic.h \ + z3_ast_containers.h \ + z3_fixedpoint.h \ + z3_fpa.h \ + z3_interp.h \ + z3_optimization.h \ z3_polynomial.h \ z3_rcf.h \ - z3_interp.h \ - z3_fpa.h \ z3++.h \ @PYTHON_API_FILES@ @DOTNET_API_FILES@ @JAVA_API_FILES@ diff --git a/contrib/cmake/examples/CMakeLists.txt b/examples/CMakeLists.txt similarity index 79% rename from contrib/cmake/examples/CMakeLists.txt rename to examples/CMakeLists.txt index 3fa49f9e0..ba7f6ee59 100644 --- a/contrib/cmake/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -23,6 +23,22 @@ ExternalProject_Add(c_example ) set_target_properties(c_example PROPERTIES EXCLUDE_FROM_ALL TRUE) +################################################################################ +# Build maxsat example project using libz3's C API as an external project +################################################################################ +ExternalProject_Add(c_maxsat_example + DEPENDS libz3 + # Configure step + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/maxsat" + CMAKE_ARGS "-DZ3_DIR=${CMAKE_BINARY_DIR}" + # Build step + ${EXTERNAL_PROJECT_BUILD_ALWAYS_ARG} + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/c_maxsat_example_build_dir" + # Install Step + INSTALL_COMMAND "${CMAKE_COMMAND}" -E echo "" # Dummy command +) +set_target_properties(c_maxsat_example PROPERTIES EXCLUDE_FROM_ALL TRUE) + ################################################################################ # Build example project using libz3's C++ API as an external project diff --git a/contrib/cmake/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt similarity index 100% rename from contrib/cmake/examples/c++/CMakeLists.txt rename to examples/c++/CMakeLists.txt diff --git a/contrib/cmake/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt similarity index 100% rename from contrib/cmake/examples/c/CMakeLists.txt rename to examples/c/CMakeLists.txt diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index 20bb012b1..64149a553 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -2152,6 +2152,31 @@ namespace test_mapi Console.WriteLine("OK, model: {0}", s.Model.ToString()); } + public static void TranslationExample() + { + Context ctx1 = new Context(); + Context ctx2 = new Context(); + + Sort s1 = ctx1.IntSort; + Sort s2 = ctx2.IntSort; + Sort s3 = s1.Translate(ctx2); + + Console.WriteLine(s1 == s2); + Console.WriteLine(s1.Equals(s2)); + Console.WriteLine(s2.Equals(s3)); + Console.WriteLine(s1.Equals(s3)); + + Expr e1 = ctx1.MkIntConst("e1"); + Expr e2 = ctx2.MkIntConst("e1"); + Expr e3 = e1.Translate(ctx2); + + Console.WriteLine(e1 == e2); + Console.WriteLine(e1.Equals(e2)); + Console.WriteLine(e2.Equals(e3)); + Console.WriteLine(e1.Equals(e3)); + } + + static void Main(string[] args) { try @@ -2225,6 +2250,8 @@ namespace test_mapi QuantifierExample4(ctx); } + TranslationExample(); + Log.Close(); if (Log.isOpen()) Console.WriteLine("Log is still open!"); diff --git a/examples/java/JavaExample.java b/examples/java/JavaExample.java index 5810dab37..25076e27c 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -281,7 +281,7 @@ class JavaExample } void disprove(Context ctx, BoolExpr f, boolean useMBQI) - throws TestFailedException + throws TestFailedException { BoolExpr[] a = {}; disprove(ctx, f, useMBQI, a); @@ -2279,6 +2279,29 @@ class JavaExample System.out.println(my); } + public void translationExample() { + Context ctx1 = new Context(); + Context ctx2 = new Context(); + + Sort s1 = ctx1.getIntSort(); + Sort s2 = ctx2.getIntSort(); + Sort s3 = s1.translate(ctx2); + + System.out.println(s1 == s2); + System.out.println(s1.equals(s2)); + System.out.println(s2.equals(s3)); + System.out.println(s1.equals(s3)); + + Expr e1 = ctx1.mkIntConst("e1"); + Expr e2 = ctx2.mkIntConst("e1"); + Expr e3 = e1.translate(ctx2); + + System.out.println(e1 == e2); + System.out.println(e1.equals(e2)); + System.out.println(e2.equals(e3)); + System.out.println(e1.equals(e3)); + } + public static void main(String[] args) { JavaExample p = new JavaExample(); @@ -2300,8 +2323,8 @@ class JavaExample HashMap cfg = new HashMap(); cfg.put("model", "true"); Context ctx = new Context(cfg); - - p.optimizeExample(ctx); + + p.optimizeExample(ctx); p.basicTests(ctx); p.castingTest(ctx); p.sudokuExample(ctx); @@ -2355,7 +2378,9 @@ class JavaExample Context ctx = new Context(cfg); p.quantifierExample3(ctx); p.quantifierExample4(ctx); - } + } + + p.translationExample(); Log.close(); if (Log.isOpen()) diff --git a/examples/maxsat/CMakeLists.txt b/examples/maxsat/CMakeLists.txt new file mode 100644 index 000000000..b48e167ea --- /dev/null +++ b/examples/maxsat/CMakeLists.txt @@ -0,0 +1,42 @@ +################################################################################ +# Example maxsat project +################################################################################ +# NOTE: Even though this is a C project, libz3 uses C++. When using libz3 +# as a static library if we don't configure this project to also support +# C++ we will use the C linker rather than the C++ linker and will not link +# the C++ standard library in resulting in a link failure. +project(Z3_C_MAXSAT_EXAMPLE C CXX) +cmake_minimum_required(VERSION 2.8.12) +find_package(Z3 + REQUIRED + CONFIG + # `NO_DEFAULT_PATH` is set so that -DZ3_DIR has to be passed to find Z3. + # This should prevent us from accidently picking up an installed + # copy of Z3. This is here to benefit Z3's build sytem when building + # this project. When making your own project you probably shouldn't + # use this option. + NO_DEFAULT_PATH +) +message(STATUS "Z3_FOUND: ${Z3_FOUND}") +message(STATUS "Found Z3 ${Z3_VERSION_STRING}") +message(STATUS "Z3_DIR: ${Z3_DIR}") + +add_executable(c_maxsat_example maxsat.c) +target_include_directories(c_maxsat_example PRIVATE ${Z3_C_INCLUDE_DIRS}) +target_link_libraries(c_maxsat_example PRIVATE ${Z3_LIBRARIES}) + +if ("${CMAKE_SYSTEM_NAME}" MATCHES "[Ww]indows") + # On Windows we need to copy the Z3 libraries + # into the same directory as the executable + # so that they can be found. + foreach (z3_lib ${Z3_LIBRARIES}) + message(STATUS "Adding copy rule for ${z3_lib}") + add_custom_command(TARGET c_maxsat_example + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E copy_if_different + $ + $ + ) + endforeach() +endif() diff --git a/examples/maxsat/maxsat.c b/examples/maxsat/maxsat.c index eaf01482c..a312e79ad 100644 --- a/examples/maxsat/maxsat.c +++ b/examples/maxsat/maxsat.c @@ -348,7 +348,15 @@ void assert_at_most_k(Z3_context ctx, Z3_solver s, unsigned n, Z3_ast * lits, un */ void assert_at_most_one(Z3_context ctx, Z3_solver s, unsigned n, Z3_ast * lits) { - assert_at_most_k(ctx, s, n, lits, 1); + assert_at_most_k(ctx, s, n, lits, 1); +} + + +Z3_solver mk_solver(Z3_context ctx) +{ + Z3_solver r = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, r); + return r; } /** @@ -357,7 +365,7 @@ void assert_at_most_one(Z3_context ctx, Z3_solver s, unsigned n, Z3_ast * lits) void tst_at_most_one() { Z3_context ctx = mk_context(); - Z3_solver s = Z3_mk_solver(ctx); + Z3_solver s = mk_solver(ctx); Z3_ast k1 = mk_bool_var(ctx, "k1"); Z3_ast k2 = mk_bool_var(ctx, "k2"); Z3_ast k3 = mk_bool_var(ctx, "k3"); @@ -376,7 +384,9 @@ void tst_at_most_one() if (result != Z3_L_TRUE) error("BUG"); m = Z3_solver_get_model(ctx, s); + Z3_model_inc_ref(ctx, m); printf("model:\n%s\n", Z3_model_to_string(ctx, m)); + Z3_model_dec_ref(ctx, m); Z3_solver_assert(ctx, s, mk_binary_or(ctx, k2, k3)); Z3_solver_assert(ctx, s, mk_binary_or(ctx, k1, k6)); printf("it must be sat...\n"); @@ -384,12 +394,15 @@ void tst_at_most_one() if (result != Z3_L_TRUE) error("BUG"); m = Z3_solver_get_model(ctx, s); + Z3_model_inc_ref(ctx, m); printf("model:\n%s\n", Z3_model_to_string(ctx, m)); Z3_solver_assert(ctx, s, mk_binary_or(ctx, k4, k5)); printf("it must be unsat...\n"); result = Z3_solver_check(ctx, s); if (result != Z3_L_FALSE) error("BUG"); + Z3_model_dec_ref(ctx, m); + Z3_solver_dec_ref(ctx, s); Z3_del_context(ctx); } @@ -454,8 +467,10 @@ int naive_maxsat(Z3_context ctx, Z3_solver s, unsigned num_hard_cnstrs, Z3_ast * printf("unsat\n"); return num_soft_cnstrs - k - 1; } - m = Z3_solver_get_model(ctx, s); + m = Z3_solver_get_model(ctx, s); + Z3_model_inc_ref(ctx, m); num_disabled = get_num_disabled_soft_constraints(ctx, m, num_soft_cnstrs, aux_vars); + Z3_model_dec_ref(ctx, m); if (num_disabled > k) { error("BUG"); } @@ -506,6 +521,7 @@ int fu_malik_maxsat_step(Z3_context ctx, Z3_solver s, unsigned num_soft_cnstrs, } else { core = Z3_solver_get_unsat_core(ctx, s); + Z3_ast_vector_inc_ref(ctx, core); core_size = Z3_ast_vector_size(ctx, core); block_vars = (Z3_ast*) malloc(sizeof(Z3_ast) * core_size); k = 0; @@ -514,7 +530,7 @@ int fu_malik_maxsat_step(Z3_context ctx, Z3_solver s, unsigned num_soft_cnstrs, unsigned j; // check whether assumption[i] is in the core or not for (j = 0; j < core_size; j++) { - if (assumptions[i] == Z3_ast_vector_get(ctx, core, j)) + if (assumptions[i] == Z3_ast_vector_get(ctx, core, j)) break; } if (j < core_size) { @@ -531,6 +547,7 @@ int fu_malik_maxsat_step(Z3_context ctx, Z3_solver s, unsigned num_soft_cnstrs, } } assert_at_most_one(ctx, s, k, block_vars); + Z3_ast_vector_dec_ref(ctx, core); return 0; // not done. } } @@ -597,7 +614,7 @@ int smtlib_maxsat(char * file_name, int approach) Z3_ast * hard_cnstrs, * soft_cnstrs; unsigned result = 0; ctx = mk_context(); - s = Z3_mk_solver(ctx); + s = mk_solver(ctx); Z3_parse_smtlib_file(ctx, file_name, 0, 0, 0, 0, 0, 0); hard_cnstrs = get_hard_constraints(ctx, &num_hard_cnstrs); soft_cnstrs = get_soft_constraints(ctx, &num_soft_cnstrs); @@ -615,6 +632,7 @@ int smtlib_maxsat(char * file_name, int approach) } free_cnstr_array(hard_cnstrs); free_cnstr_array(soft_cnstrs); + Z3_solver_dec_ref(ctx, s); return result; } diff --git a/contrib/cmake/examples/python/CMakeLists.txt b/examples/python/CMakeLists.txt similarity index 70% rename from contrib/cmake/examples/python/CMakeLists.txt rename to examples/python/CMakeLists.txt index fdbb7891f..9bd45df41 100644 --- a/contrib/cmake/examples/python/CMakeLists.txt +++ b/examples/python/CMakeLists.txt @@ -1,5 +1,11 @@ set(python_example_files + all_interval_series.py + complex/complex.py example.py + hamiltonian/hamiltonian.py + mus/marco.py + mus/mss.py + socrates.py visitor.py ) @@ -10,7 +16,10 @@ foreach (example_file ${python_example_files}) add_custom_command(OUTPUT "${z3py_bindings_build_dest}/${example_file}" COMMAND "${CMAKE_COMMAND}" "-E" "copy" "${CMAKE_CURRENT_SOURCE_DIR}/${example_file}" - "${z3py_bindings_build_dest}/${example_file}" + # We flatten the hierarchy so that all python files have + # the `z3` directory in their directory so that their import + # statements "just work". + "${z3py_bindings_build_dest}/" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${example_file}" COMMENT "Copying \"${example_file}\" to ${z3py_bindings_build_dest}/${example_file}" ) diff --git a/examples/python/all_interval_series.py b/examples/python/all_interval_series.py index d55017a56..216941451 100644 --- a/examples/python/all_interval_series.py +++ b/examples/python/all_interval_series.py @@ -4,7 +4,7 @@ # adjacent entries fall in the range 0,..,n-1 # This is known as the "The All-Interval Series Problem" # See http://www.csplib.org/Problems/prob007/ - +from __future__ import print_function from z3 import * import time @@ -56,7 +56,7 @@ def process_model(s, xij, n): block += [xij[i][j]] k = j values += [k] - print values + print(values) sys.stdout.flush() return block @@ -68,9 +68,9 @@ def all_models(n): block = process_model(s, xij, n) s.add(Not(And(block))) count += 1 - print s.statistics() - print time.clock() - start - print count + print(s.statistics()) + print(time.clock() - start) + print(count) set_option(verbose=1) all_models(12) diff --git a/examples/python/complex/complex.py b/examples/python/complex/complex.py index 467d76c55..3623b5f1e 100644 --- a/examples/python/complex/complex.py +++ b/examples/python/complex/complex.py @@ -6,6 +6,10 @@ # # Author: Leonardo de Moura (leonardo) ############################################ +from __future__ import print_function +import sys +if sys.version_info.major >= 3: + from functools import reduce from z3 import * def _to_complex(a): @@ -53,7 +57,7 @@ class ComplexExpr: return self if k < 0: return (self ** (-k)).inv() - return reduce(lambda x, y: x * y, [self for _ in xrange(k)], ComplexExpr(1, 0)) + return reduce(lambda x, y: x * y, [self for _ in range(k)], ComplexExpr(1, 0)) def inv(self): den = self.r*self.r + self.i*self.i @@ -63,6 +67,12 @@ class ComplexExpr: inv_other = _to_complex(other).inv() return self.__mul__(inv_other) + if sys.version_info.major >= 3: + # In python 3 the meaning of the '/' operator + # was changed. + def __truediv__(self, other): + return self.__div__(other) + def __rdiv__(self, other): other = _to_complex(other) return self.inv().__mul__(other) @@ -113,5 +123,5 @@ print(s.model()) s.add(x.i != 1) print(s.check()) # print(s.model()) -print ((3 + I) ** 2)/(5 - I) -print ((3 + I) ** -3)/(5 - I) +print(((3 + I) ** 2)/(5 - I)) +print(((3 + I) ** -3)/(5 - I)) diff --git a/examples/python/mus/mss.py b/examples/python/mus/mss.py index fd2d209da..c7b44c8a4 100644 --- a/examples/python/mus/mss.py +++ b/examples/python/mus/mss.py @@ -45,11 +45,6 @@ def enumerate_sets(solver): else: break -class CompareSetSize(): - def __call__(self, s1, s2): - return len(s1) < len(s2) - - class MSSSolver: s = Solver() varcache = {} @@ -157,7 +152,7 @@ class MSSSolver: mcs = [x for x in self.orig_soft_vars if not is_true(self.model[x])] self.s.add(Or(mcs)) core_literals = set([]) - cores.sort(CompareSetSize()) + cores.sort(key=lambda element: len(element)) for core in cores: if len(core & core_literals) == 0: self.relax_core(core) diff --git a/examples/python/visitor.py b/examples/python/visitor.py index 9255c6a80..504e2acc8 100644 --- a/examples/python/visitor.py +++ b/examples/python/visitor.py @@ -1,5 +1,5 @@ # Copyright (c) Microsoft Corporation 2015 - +from __future__ import print_function from z3 import * def visitor(e, seen): @@ -22,8 +22,8 @@ fml = x + x + y > 2 seen = {} for e in visitor(fml, seen): if is_const(e) and e.decl().kind() == Z3_OP_UNINTERPRETED: - print "Variable", e + print("Variable", e) else: - print e + print(e) diff --git a/contrib/cmake/examples/tptp/CMakeLists.txt b/examples/tptp/CMakeLists.txt similarity index 100% rename from contrib/cmake/examples/tptp/CMakeLists.txt rename to examples/tptp/CMakeLists.txt diff --git a/scripts/mk_genfile_common.py b/scripts/mk_genfile_common.py index 98346f99f..21771cc04 100644 --- a/scripts/mk_genfile_common.py +++ b/scripts/mk_genfile_common.py @@ -587,7 +587,7 @@ def mk_def_file_internal(defname, dll_name, export_header_files): ############################################################################### # Functions for generating ``gparams_register_modules.cpp`` ############################################################################### -def mk_gparams_register_modules_internal(component_src_dirs, path): +def mk_gparams_register_modules_internal(h_files_full_path, path): """ Generate a ``gparams_register_modules.cpp`` file in the directory ``path``. Returns the path to the generated file. @@ -600,7 +600,7 @@ def mk_gparams_register_modules_internal(component_src_dirs, path): This procedure is invoked by gparams::init() """ - assert isinstance(component_src_dirs, list) + assert isinstance(h_files_full_path, list) assert check_dir_exists(path) cmds = [] mod_cmds = [] @@ -612,11 +612,6 @@ def mk_gparams_register_modules_internal(component_src_dirs, path): reg_pat = re.compile('[ \t]*REG_PARAMS\(\'([^\']*)\'\)') reg_mod_pat = re.compile('[ \t]*REG_MODULE_PARAMS\(\'([^\']*)\', *\'([^\']*)\'\)') reg_mod_descr_pat = re.compile('[ \t]*REG_MODULE_DESCRIPTION\(\'([^\']*)\', *\'([^\']*)\'\)') - h_files_full_path = [] - for component_src_dir in component_src_dirs: - h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir)) - h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files)) - h_files_full_path.extend(h_files) for h_file in sorted_headers_by_component(h_files_full_path): added_include = False with open(h_file, 'r') as fin: @@ -651,7 +646,7 @@ def mk_gparams_register_modules_internal(component_src_dirs, path): # Functions/data structures for generating ``install_tactics.cpp`` ############################################################################### -def mk_install_tactic_cpp_internal(component_src_dirs, path): +def mk_install_tactic_cpp_internal(h_files_full_path, path): """ Generate a ``install_tactics.cpp`` file in the directory ``path``. Returns the path the generated file. @@ -662,9 +657,10 @@ def mk_install_tactic_cpp_internal(component_src_dirs, path): void install_tactics(tactic_manager & ctx) ``` - It installs all tactics found in the given component directories - ``component_src_dirs`` The procedure looks for ``ADD_TACTIC`` commands - in the ``.h`` and ``.hpp`` files of these components. + It installs all tactics declared in the given header files + ``h_files_full_path`` The procedure looks for ``ADD_TACTIC`` and + ``ADD_PROBE``commands in the ``.h`` and ``.hpp`` files of these + components. """ ADD_TACTIC_DATA = [] ADD_PROBE_DATA = [] @@ -679,7 +675,7 @@ def mk_install_tactic_cpp_internal(component_src_dirs, path): 'ADD_PROBE': ADD_PROBE, } - assert isinstance(component_src_dirs, list) + assert isinstance(h_files_full_path, list) assert check_dir_exists(path) fullname = os.path.join(path, 'install_tactic.cpp') fout = open(fullname, 'w') @@ -689,11 +685,6 @@ def mk_install_tactic_cpp_internal(component_src_dirs, path): fout.write('#include"cmd_context.h"\n') tactic_pat = re.compile('[ \t]*ADD_TACTIC\(.*\)') probe_pat = re.compile('[ \t]*ADD_PROBE\(.*\)') - h_files_full_path = [] - for component_src_dir in sorted(component_src_dirs): - h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir)) - h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files)) - h_files_full_path.extend(h_files) for h_file in sorted_headers_by_component(h_files_full_path): added_include = False with open(h_file, 'r') as fin: @@ -740,7 +731,7 @@ def mk_install_tactic_cpp_internal(component_src_dirs, path): # Functions for generating ``mem_initializer.cpp`` ############################################################################### -def mk_mem_initializer_cpp_internal(component_src_dirs, path): +def mk_mem_initializer_cpp_internal(h_files_full_path, path): """ Generate a ``mem_initializer.cpp`` file in the directory ``path``. Returns the path to the generated file. @@ -754,7 +745,7 @@ def mk_mem_initializer_cpp_internal(component_src_dirs, path): These procedures are invoked by the Z3 memory_manager """ - assert isinstance(component_src_dirs, list) + assert isinstance(h_files_full_path, list) assert check_dir_exists(path) initializer_cmds = [] finalizer_cmds = [] @@ -765,11 +756,6 @@ def mk_mem_initializer_cpp_internal(component_src_dirs, path): # ADD_INITIALIZER with priority initializer_prio_pat = re.compile('[ \t]*ADD_INITIALIZER\(\'([^\']*)\',[ \t]*(-?[0-9]*)\)') finalizer_pat = re.compile('[ \t]*ADD_FINALIZER\(\'([^\']*)\'\)') - h_files_full_path = [] - for component_src_dir in sorted(component_src_dirs): - h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir)) - h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files)) - h_files_full_path.extend(h_files) for h_file in sorted_headers_by_component(h_files_full_path): added_include = False with open(h_file, 'r') as fin: diff --git a/scripts/mk_gparams_register_modules_cpp.py b/scripts/mk_gparams_register_modules_cpp.py index cf6e8da96..9614768ca 100755 --- a/scripts/mk_gparams_register_modules_cpp.py +++ b/scripts/mk_gparams_register_modules_cpp.py @@ -1,10 +1,8 @@ #!/usr/bin/env python """ -Determines the available global parameters -in header files in the list of source directions -and generates a ``gparams_register_modules.cpp`` file in -the destination directory that defines a function -``void gparams_register_modules()``. +Determines the available global parameters from a list of header files and +generates a ``gparams_register_modules.cpp`` file in the destination directory +that defines a function ``void gparams_register_modules()``. """ import mk_genfile_common import argparse @@ -16,19 +14,22 @@ def main(args): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("destination_dir", help="destination directory") - parser.add_argument("source_dirs", nargs="+", - help="One or more source directories to search") + parser.add_argument("header_files", nargs="+", + help="One or more header files to parse") pargs = parser.parse_args(args) if not mk_genfile_common.check_dir_exists(pargs.destination_dir): return 1 - for source_dir in pargs.source_dirs: - if not mk_genfile_common.check_dir_exists(source_dir): - return 1 + if not mk_genfile_common.check_files_exist(pargs.header_files): + return 1 + + h_files_full_path = [] + for header_file in pargs.header_files: + h_files_full_path.append(os.path.abspath(header_file)) output = mk_genfile_common.mk_gparams_register_modules_internal( - pargs.source_dirs, + h_files_full_path, pargs.destination_dir ) logging.info('Generated "{}"'.format(output)) diff --git a/scripts/mk_install_tactic_cpp.py b/scripts/mk_install_tactic_cpp.py index 21e66b3ab..a152eff14 100755 --- a/scripts/mk_install_tactic_cpp.py +++ b/scripts/mk_install_tactic_cpp.py @@ -1,10 +1,8 @@ #!/usr/bin/env python """ -Determines the available tactics -in header files in the list of source directions -and generates a ``install_tactic.cpp`` file in -the destination directory that defines a function -``void install_tactics(tactic_manager& ctx)``. +Determines the available tactics from a list of header files and generates a +``install_tactic.cpp`` file in the destination directory that defines a +function ``void install_tactics(tactic_manager& ctx)``. """ import mk_genfile_common import argparse @@ -16,19 +14,22 @@ def main(args): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("destination_dir", help="destination directory") - parser.add_argument("source_dirs", nargs="+", - help="One or more source directories to search") + parser.add_argument("header_files", nargs="+", + help="One or more header files to parse") pargs = parser.parse_args(args) if not mk_genfile_common.check_dir_exists(pargs.destination_dir): return 1 - for source_dir in pargs.source_dirs: - if not mk_genfile_common.check_dir_exists(source_dir): - return 1 + if not mk_genfile_common.check_files_exist(pargs.header_files): + return 1 + + h_files_full_path = [] + for header_file in pargs.header_files: + h_files_full_path.append(os.path.abspath(header_file)) output = mk_genfile_common.mk_install_tactic_cpp_internal( - pargs.source_dirs, + h_files_full_path, pargs.destination_dir ) logging.info('Generated "{}"'.format(output)) diff --git a/scripts/mk_mem_initializer_cpp.py b/scripts/mk_mem_initializer_cpp.py index b56fcbced..238595fa3 100755 --- a/scripts/mk_mem_initializer_cpp.py +++ b/scripts/mk_mem_initializer_cpp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python """ -Scans the source directories for +Scans the listed header files for memory initializers and finalizers and emits and implementation of ``void mem_initialize()`` and @@ -17,19 +17,19 @@ def main(args): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("destination_dir", help="destination directory") - parser.add_argument("source_dirs", nargs="+", - help="One or more source directories to search") + parser.add_argument("header_files", nargs="+", + help="One or more header files to parse") pargs = parser.parse_args(args) if not mk_genfile_common.check_dir_exists(pargs.destination_dir): return 1 - for source_dir in pargs.source_dirs: - if not mk_genfile_common.check_dir_exists(source_dir): - return 1 + h_files_full_path = [] + for header_file in pargs.header_files: + h_files_full_path.append(os.path.abspath(header_file)) output = mk_genfile_common.mk_mem_initializer_cpp_internal( - pargs.source_dirs, + h_files_full_path, pargs.destination_dir ) logging.info('Generated "{}"'.format(output)) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index e7e35817f..a5f75fd1c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -104,6 +104,8 @@ GIT_DESCRIBE=False SLOW_OPTIMIZE=False USE_OMP=True LOG_SYNC=False +GUARD_CF=False +ALWAYS_DYNAMIC_BASE=False FPMATH="Default" FPMATH_FLAGS="-mfpmath=sse -msse -msse2" @@ -623,13 +625,13 @@ def display_help(exit_code): print(" -d, --debug compile Z3 in debug mode.") print(" -t, --trace enable tracing in release mode.") if IS_WINDOWS: + print(" --guardcf enable Control Flow Guard runtime checks.") print(" -x, --x64 create 64 binary when using Visual Studio.") else: print(" --x86 force 32-bit x86 build on x64 systems.") print(" -m, --makefiles generate only makefiles.") if IS_WINDOWS: print(" -v, --vsproj generate Visual Studio Project Files.") - if IS_WINDOWS: print(" --optimize generate optimized code during linking.") print(" --dotnet generate .NET bindings.") print(" --dotnet-key= sign the .NET assembly using the private key in .") @@ -670,10 +672,11 @@ def parse_options(): global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE, VS_PAR, VS_PAR_NUM global DOTNET_ENABLED, DOTNET_KEY_FILE, JAVA_ENABLED, ML_ENABLED, STATIC_LIB, STATIC_BIN, PREFIX, GMP, PYTHON_PACKAGE_DIR, GPROF, GIT_HASH, GIT_DESCRIBE, PYTHON_INSTALL_ENABLED, PYTHON_ENABLED global LINUX_X64, SLOW_OPTIMIZE, USE_OMP, LOG_SYNC + global GUARD_CF, ALWAYS_DYNAMIC_BASE try: options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:df:sxhmcvtnp:gj', - ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', + ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', 'guardcf', 'trace', 'dotnet', 'dotnet-key=', 'staticlib', 'prefix=', 'gmp', 'java', 'parallel=', 'gprof', 'githash=', 'git-describe', 'x86', 'ml', 'optimize', 'noomp', 'pypkgdir=', 'python', 'staticbin', 'log-sync']) except: @@ -742,6 +745,9 @@ def parse_options(): elif opt in ('--python'): PYTHON_ENABLED = True PYTHON_INSTALL_ENABLED = True + elif opt == '--guardcf': + GUARD_CF = True + ALWAYS_DYNAMIC_BASE = True # /GUARD:CF requires /DYNAMICBASE else: print("ERROR: Invalid command line option '%s'" % opt) display_help(1) @@ -2310,6 +2316,7 @@ def mk_config(): 'SLINK_OUT_FLAG=/Fe\n' 'OS_DEFINES=/D _WINDOWS\n') extra_opt = '' + link_extra_opt = '' HAS_OMP = test_openmp('cl') if HAS_OMP: extra_opt = ' /openmp' @@ -2319,10 +2326,14 @@ def mk_config(): extra_opt = '%s /DZ3_LOG_SYNC' % extra_opt if GIT_HASH: extra_opt = ' %s /D Z3GITHASH=%s' % (extra_opt, GIT_HASH) + if GUARD_CF: + extra_opt = ' %s /guard:cf' % extra_opt + link_extra_opt = ' %s /GUARD:CF' % link_extra_opt if STATIC_BIN: static_opt = '/MT' else: static_opt = '/MD' + maybe_disable_dynamic_base = '/DYNAMICBASE' if ALWAYS_DYNAMIC_BASE else '/DYNAMICBASE:NO' if DEBUG_MODE: static_opt = static_opt + 'd' config.write( @@ -2333,8 +2344,8 @@ def mk_config(): config.write( 'CXXFLAGS=/c /Zi /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- %s %s\n' % (extra_opt, static_opt)) config.write( - 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' - 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') + 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' + 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (link_extra_opt, maybe_disable_dynamic_base, link_extra_opt)) elif VS_ARM: print("ARM on VS is unsupported") exit(1) @@ -2342,8 +2353,8 @@ def mk_config(): config.write( 'CXXFLAGS=/c /Zi /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2 %s %s\n' % (extra_opt, static_opt)) config.write( - 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' - 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') + 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' + 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (link_extra_opt, maybe_disable_dynamic_base, link_extra_opt)) else: # Windows Release mode LTCG=' /LTCG' if SLOW_OPTIMIZE else '' @@ -2358,8 +2369,8 @@ def mk_config(): config.write( 'CXXFLAGS=/c%s /Zi /nologo /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG /D _LIB /D _WINDOWS /D _AMD64_ /D _UNICODE /D UNICODE /Gm- /EHsc /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TP %s %s\n' % (GL, extra_opt, static_opt)) config.write( - 'LINK_EXTRA_FLAGS=/link%s /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608\n' - 'SLINK_EXTRA_FLAGS=/link%s /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608\n' % (LTCG, LTCG)) + 'LINK_EXTRA_FLAGS=/link%s /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 %s\n' + 'SLINK_EXTRA_FLAGS=/link%s /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 %s\n' % (LTCG, link_extra_opt, LTCG, link_extra_opt)) elif VS_ARM: print("ARM on VS is unsupported") exit(1) @@ -2367,8 +2378,8 @@ def mk_config(): config.write( 'CXXFLAGS=/nologo /c%s /Zi /W3 /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG /D _CONSOLE /D _WINDOWS /D ASYNC_COMMANDS /Gm- /EHsc /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2 %s %s\n' % (GL, extra_opt, static_opt)) config.write( - 'LINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' - 'SLINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n' % (LTCG, LTCG)) + 'LINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' + 'SLINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (LTCG, link_extra_opt, LTCG, maybe_disable_dynamic_base, link_extra_opt)) @@ -2712,12 +2723,22 @@ def mk_all_assembly_infos(major, minor, build, revision): else: raise MKException("Failed to find assembly template info file '%s'" % assembly_info_template) +def get_header_files_for_components(component_src_dirs): + assert isinstance(component_src_dirs, list) + h_files_full_path = [] + for component_src_dir in sorted(component_src_dirs): + h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir)) + h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files)) + h_files_full_path.extend(h_files) + return h_files_full_path + def mk_install_tactic_cpp(cnames, path): component_src_dirs = [] for cname in cnames: c = get_component(cname) component_src_dirs.append(c.src_dir) - generated_file = mk_genfile_common.mk_install_tactic_cpp_internal(component_src_dirs, path) + h_files_full_path = get_header_files_for_components(component_src_dirs) + generated_file = mk_genfile_common.mk_install_tactic_cpp_internal(h_files_full_path, path) if VERBOSE: print("Generated '{}'".format(generated_file)) @@ -2735,7 +2756,8 @@ def mk_mem_initializer_cpp(cnames, path): for cname in cnames: c = get_component(cname) component_src_dirs.append(c.src_dir) - generated_file = mk_genfile_common.mk_mem_initializer_cpp_internal(component_src_dirs, path) + h_files_full_path = get_header_files_for_components(component_src_dirs) + generated_file = mk_genfile_common.mk_mem_initializer_cpp_internal(h_files_full_path, path) if VERBOSE: print("Generated '{}'".format(generated_file)) @@ -2753,7 +2775,8 @@ def mk_gparams_register_modules(cnames, path): for cname in cnames: c = get_component(cname) component_src_dirs.append(c.src_dir) - generated_file = mk_genfile_common.mk_gparams_register_modules_internal(component_src_dirs, path) + h_files_full_path = get_header_files_for_components(component_src_dirs) + generated_file = mk_genfile_common.mk_gparams_register_modules_internal(h_files_full_path, path) if VERBOSE: print("Generated '{}'".format(generated_file)) diff --git a/scripts/update_api.py b/scripts/update_api.py index cc96bd425..3c1e1cc07 100755 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -321,16 +321,19 @@ def mk_py_wrappers(): core_py.write("def %s(" % name) display_args(num) core_py.write("):\n") + core_py.write(" _lib = lib()\n") + core_py.write(" if _lib.%s is None:\n" % name) + core_py.write(" return\n") if result != VOID: - core_py.write(" r = lib().%s(" % name) + core_py.write(" r = _lib.%s(" % name) else: - core_py.write(" lib().%s(" % name) + core_py.write(" _lib.%s(" % name) display_args_to_z3(params) core_py.write(")\n") if len(params) > 0 and param_type(params[0]) == CONTEXT: - core_py.write(" err = lib().Z3_get_error_code(a0)\n") + core_py.write(" err = _lib.Z3_get_error_code(a0)\n") core_py.write(" if err != Z3_OK:\n") - core_py.write(" raise Z3Exception(lib().Z3_get_error_msg(a0, err))\n") + core_py.write(" raise Z3Exception(_lib.Z3_get_error_msg(a0, err))\n") if result == STRING: core_py.write(" return _to_pystr(r)\n") elif result != VOID: @@ -1600,6 +1603,11 @@ def write_exe_c_preamble(exe_c): # exe_c.write('void Z3_replayer_error_handler(Z3_context ctx, Z3_error_code c) { printf("[REPLAYER ERROR HANDLER]: %s\\n", Z3_get_error_msg(ctx, c)); }\n') +def write_core_py_post(core_py): + core_py.write(""" + +""") + def write_core_py_preamble(core_py): core_py.write('# Automatically generated file\n') core_py.write('import sys, os\n') @@ -1612,18 +1620,19 @@ def write_core_py_preamble(core_py): _ext = 'dll' if sys.platform in ('win32', 'cygwin') else 'dylib' if sys.platform == 'darwin' else 'so' _lib = None + def lib(): global _lib if _lib is None: - _dirs = ['.', os.path.dirname(os.path.abspath(__file__)), pkg_resources.resource_filename('z3', 'lib'), os.path.join(sys.prefix, 'lib'), None] - for _dir in _dirs: - try: - init(_dir) - break - except: - pass - if _lib is None: - raise Z3Exception("init(Z3_LIBRARY_PATH) must be invoked before using Z3-python") + _dirs = ['.', os.path.dirname(os.path.abspath(__file__)), pkg_resources.resource_filename('z3', 'lib'), os.path.join(sys.prefix, 'lib'), None] + for _dir in _dirs: + try: + init(_dir) + break + except: + pass + if _lib is None: + raise Z3Exception("init(Z3_LIBRARY_PATH) must be invoked before using Z3-python") return _lib def _to_ascii(s): @@ -1728,6 +1737,7 @@ def generate_files(api_files, def_APIs(api_files) mk_bindings(exe_c) mk_py_wrappers() + write_core_py_post(core_py) if mk_util.is_verbose(): print("Generated '{}'".format(log_h.name)) diff --git a/contrib/cmake/src/CMakeLists.txt b/src/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/CMakeLists.txt rename to src/CMakeLists.txt diff --git a/contrib/cmake/src/ackermannization/CMakeLists.txt b/src/ackermannization/CMakeLists.txt similarity index 86% rename from contrib/cmake/src/ackermannization/CMakeLists.txt rename to src/ackermannization/CMakeLists.txt index 93529ae12..3ce7f97cc 100644 --- a/contrib/cmake/src/ackermannization/CMakeLists.txt +++ b/src/ackermannization/CMakeLists.txt @@ -17,4 +17,7 @@ z3_add_component(ackermannization PYG_FILES ackermannization_params.pyg ackermannize_bv_tactic_params.pyg + TACTIC_HEADERS + ackermannize_bv_tactic.h + ackr_bound_probe.h ) diff --git a/contrib/cmake/src/api/CMakeLists.txt b/src/api/CMakeLists.txt similarity index 99% rename from contrib/cmake/src/api/CMakeLists.txt rename to src/api/CMakeLists.txt index 8e796168f..79c5fc1c9 100644 --- a/contrib/cmake/src/api/CMakeLists.txt +++ b/src/api/CMakeLists.txt @@ -7,7 +7,7 @@ set(generated_files # Sanity check foreach (gen_file ${generated_files}) if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${gen_file}") - message(FATAL_ERROR "\"${CMAKE_CURRENT_SOURCE_DIR}/${gen_files}\"" + message(FATAL_ERROR "\"${CMAKE_CURRENT_SOURCE_DIR}/${gen_file}\"" ${z3_polluted_tree_msg}) endif() endforeach() diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index 3cec4ec02..d34cad2f4 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -558,6 +558,7 @@ extern "C" { Z3_TRY; LOG_Z3_get_sort(c, a); RESET_ERROR_CODE(); + CHECK_IS_EXPR(a, 0); Z3_sort r = of_sort(mk_c(c)->m().get_sort(to_expr(a))); RETURN_Z3(r); Z3_CATCH_RETURN(0); @@ -821,9 +822,13 @@ extern "C" { RESET_ERROR_CODE(); std::ostringstream buffer; switch (mk_c(c)->get_print_mode()) { - case Z3_PRINT_SMTLIB_FULL: - buffer << mk_pp(to_ast(a), mk_c(c)->m()); + case Z3_PRINT_SMTLIB_FULL: { + params_ref p; + p.set_uint("max_depth", 4294967295u); + p.set_uint("min_alias_size", 4294967295u); + buffer << mk_pp(to_ast(a), mk_c(c)->m(), p); break; + } case Z3_PRINT_LOW_LEVEL: buffer << mk_ll_pp(to_ast(a), mk_c(c)->m()); break; @@ -1066,7 +1071,7 @@ extern "C" { case OP_BIT2BOOL: return Z3_OP_BIT2BOOL; case OP_BSMUL_NO_OVFL: return Z3_OP_BSMUL_NO_OVFL; case OP_BUMUL_NO_OVFL: return Z3_OP_BUMUL_NO_OVFL; - case OP_BSMUL_NO_UDFL: return Z3_OP_BSMUL_NO_UDFL; + case OP_BSMUL_NO_UDFL: return Z3_OP_BSMUL_NO_UDFL; case OP_BSDIV_I: return Z3_OP_BSDIV_I; case OP_BUDIV_I: return Z3_OP_BUDIV_I; case OP_BSREM_I: return Z3_OP_BSREM_I; diff --git a/src/api/api_datatype.cpp b/src/api/api_datatype.cpp index 5096c8e80..647cdc581 100644 --- a/src/api/api_datatype.cpp +++ b/src/api/api_datatype.cpp @@ -52,7 +52,7 @@ extern "C" { { datatype_decl * dt = mk_datatype_decl(to_symbol(name), 1, constrs); - bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &dt, tuples); + bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &dt, 0, 0, tuples); del_datatype_decl(dt); if (!is_ok) { @@ -119,7 +119,7 @@ extern "C" { { datatype_decl * dt = mk_datatype_decl(to_symbol(name), n, constrs.c_ptr()); - bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &dt, sorts); + bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &dt, 0, 0, sorts); del_datatype_decl(dt); if (!is_ok) { @@ -180,7 +180,7 @@ extern "C" { sort_ref_vector sorts(m); { datatype_decl * decl = mk_datatype_decl(to_symbol(name), 2, constrs); - bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &decl, sorts); + bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &decl, 0, 0, sorts); del_datatype_decl(decl); if (!is_ok) { @@ -357,7 +357,7 @@ extern "C" { sort_ref_vector sorts(m); { datatype_decl * data = mk_datatype_decl(c, name, num_constructors, constructors); - bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &data, sorts); + bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &data, 0, 0, sorts); del_datatype_decl(data); if (!is_ok) { @@ -420,7 +420,7 @@ extern "C" { datas.push_back(mk_datatype_decl(c,sort_names[i], cl->size(), reinterpret_cast(cl->c_ptr()))); } sort_ref_vector _sorts(m); - bool ok = mk_c(c)->get_dt_plugin()->mk_datatypes(datas.size(), datas.c_ptr(), _sorts); + bool ok = mk_c(c)->get_dt_plugin()->mk_datatypes(datas.size(), datas.c_ptr(), 0, 0, _sorts); del_datatype_decls(datas.size(), datas.c_ptr()); if (!ok) { diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index bd03237be..e0406d7cc 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -87,7 +87,7 @@ namespace z3 { inline std::ostream & operator<<(std::ostream & out, exception const & e) { out << e.msg(); return out; } #if !defined(Z3_THROW) -#if __cpp_exceptions || _CPPUNWIND +#if __cpp_exceptions || _CPPUNWIND || __EXCEPTIONS #define Z3_THROW(x) throw x #else #define Z3_THROW(x) {} @@ -2796,6 +2796,6 @@ namespace z3 { /*@}*/ /*@}*/ - +#undef Z3_THROW #endif diff --git a/contrib/cmake/src/api/dll/CMakeLists.txt b/src/api/dll/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/api/dll/CMakeLists.txt rename to src/api/dll/CMakeLists.txt diff --git a/src/api/dotnet/AST.cs b/src/api/dotnet/AST.cs index 2ffaaa661..c7ca1851e 100644 --- a/src/api/dotnet/AST.cs +++ b/src/api/dotnet/AST.cs @@ -14,7 +14,7 @@ Author: Christoph Wintersteiger (cwinter) 2012-03-16 Notes: - + --*/ using System; @@ -25,7 +25,7 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// The abstract syntax tree (AST) class. + /// The abstract syntax tree (AST) class. /// [ContractVerification(true)] public class AST : Z3Object, IComparable @@ -35,7 +35,7 @@ namespace Microsoft.Z3 /// /// An AST /// An AST - /// True if and are from the same context + /// True if and are from the same context /// and represent the same sort; false otherwise. public static bool operator ==(AST a, AST b) { @@ -51,7 +51,7 @@ namespace Microsoft.Z3 /// /// An AST /// An AST - /// True if and are not from the same context + /// True if and are not from the same context /// or represent different sorts; false otherwise. public static bool operator !=(AST a, AST b) { @@ -120,12 +120,12 @@ namespace Microsoft.Z3 if (ReferenceEquals(Context, ctx)) return this; else - return new AST(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx)); + return Create(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx)); } /// /// The kind of the AST. - /// + /// public Z3_ast_kind ASTKind { get { return (Z3_ast_kind)Native.Z3_get_ast_kind(Context.nCtx, NativeObject); } @@ -224,10 +224,10 @@ namespace Microsoft.Z3 { Native.Z3_dec_ref(ctx.nCtx, obj); } - }; + }; internal override void IncRef(IntPtr o) - { + { // Console.WriteLine("AST IncRef()"); if (Context == null || o == IntPtr.Zero) return; diff --git a/contrib/cmake/src/api/dotnet/CMakeLists.txt b/src/api/dotnet/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/api/dotnet/CMakeLists.txt rename to src/api/dotnet/CMakeLists.txt diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index 23ffe61bd..6c52b83c8 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -163,13 +163,7 @@ namespace Microsoft.Z3 /// A copy of the term which is associated with new public Expr Translate(Context ctx) { - Contract.Requires(ctx != null); - Contract.Ensures(Contract.Result() != null); - - if (ReferenceEquals(Context, ctx)) - return this; - else - return Expr.Create(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx)); + return (Expr)base.Translate(ctx); } /// @@ -809,7 +803,62 @@ namespace Microsoft.Z3 /// Retrieve string corresponding to string constant. /// /// the expression should be a string constant, (IsString should be true). - public string String { get { return Native.Z3_get_string(Context.nCtx, NativeObject); } } + public string String { get { return Native.Z3_get_string(Context.nCtx, NativeObject); } } + + /// + /// Check whether expression is a concatentation. + /// + /// a Boolean + public bool IsConcat { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONCAT; } } + + /// + /// Check whether expression is a prefix. + /// + /// a Boolean + public bool IsPrefix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_PREFIX; } } + + /// + /// Check whether expression is a suffix. + /// + /// a Boolean + public bool IsSuffix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_SUFFIX; } } + + /// + /// Check whether expression is a contains. + /// + /// a Boolean + public bool IsContains { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONTAINS; } } + + /// + /// Check whether expression is an extract. + /// + /// a Boolean + public bool IsExtract { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_EXTRACT; } } + + /// + /// Check whether expression is a replace. + /// + /// a Boolean + public bool IsReplace { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_REPLACE; } } + + /// + /// Check whether expression is an at. + /// + /// a Boolean + public bool IsAt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_AT; } } + + /// + /// Check whether expression is a sequence length. + /// + /// a Boolean + public bool IsLength { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_LENGTH; } } + + /// + /// Check whether expression is a sequence index. + /// + /// a Boolean + public bool IsIndex { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_INDEX; } } + #endregion diff --git a/src/api/dotnet/FuncDecl.cs b/src/api/dotnet/FuncDecl.cs index 2f5cd0ce8..0587a2276 100644 --- a/src/api/dotnet/FuncDecl.cs +++ b/src/api/dotnet/FuncDecl.cs @@ -14,7 +14,7 @@ Author: Christoph Wintersteiger (cwinter) 2012-03-16 Notes: - + --*/ using System; @@ -23,7 +23,7 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// Function declarations. + /// Function declarations. /// [ContractVerification(true)] public class FuncDecl : AST @@ -62,7 +62,7 @@ namespace Microsoft.Z3 /// /// A hash code. - /// + /// public override int GetHashCode() { return base.GetHashCode(); @@ -205,7 +205,7 @@ namespace Microsoft.Z3 } /// - /// Function declarations can have Parameters associated with them. + /// Function declarations can have Parameters associated with them. /// public class Parameter { @@ -315,6 +315,17 @@ namespace Microsoft.Z3 #endif #endregion + /// + /// Translates (copies) the function declaration to the Context . + /// + /// A context + /// A copy of the function declaration which is associated with + new public FuncDecl Translate(Context ctx) + { + return (FuncDecl) base.Translate(ctx); + } + + /// /// Create expression that applies function to arguments. /// @@ -342,6 +353,5 @@ namespace Microsoft.Z3 Context.CheckContextMatch(args); return Expr.Create(Context, this, args); } - } } diff --git a/src/api/dotnet/Quantifier.cs b/src/api/dotnet/Quantifier.cs index eb21ed2b9..eca4e3c7e 100644 --- a/src/api/dotnet/Quantifier.cs +++ b/src/api/dotnet/Quantifier.cs @@ -14,7 +14,7 @@ Author: Christoph Wintersteiger (cwinter) 2012-03-19 Notes: - + --*/ using System; @@ -157,6 +157,16 @@ namespace Microsoft.Z3 } } + /// + /// Translates (copies) the quantifier to the Context . + /// + /// A context + /// A copy of the quantifier which is associated with + new public Quantifier Translate(Context ctx) + { + return (Quantifier)base.Translate(ctx); + } + #region Internal [ContractVerification(false)] // F: Clousot ForAll decompilation gets confused below. Setting verification off until I fixed the bug internal Quantifier(Context ctx, bool isForall, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) diff --git a/src/api/dotnet/Sort.cs b/src/api/dotnet/Sort.cs index e1b8ca1b7..e6f195434 100644 --- a/src/api/dotnet/Sort.cs +++ b/src/api/dotnet/Sort.cs @@ -14,7 +14,7 @@ Author: Christoph Wintersteiger (cwinter) 2012-03-15 Notes: - + --*/ using System; @@ -33,7 +33,7 @@ namespace Microsoft.Z3 /// /// A Sort /// A Sort - /// True if and are from the same context + /// True if and are from the same context /// and represent the same sort; false otherwise. public static bool operator ==(Sort a, Sort b) { @@ -49,7 +49,7 @@ namespace Microsoft.Z3 /// /// A Sort /// A Sort - /// True if and are not from the same context + /// True if and are not from the same context /// or represent different sorts; false otherwise. public static bool operator !=(Sort a, Sort b) { @@ -113,10 +113,20 @@ namespace Microsoft.Z3 return Native.Z3_sort_to_string(Context.nCtx, NativeObject); } + /// + /// Translates (copies) the sort to the Context . + /// + /// A context + /// A copy of the sort which is associated with + new public Sort Translate(Context ctx) + { + return (Sort)base.Translate(ctx); + } + #region Internal /// /// Sort constructor - /// + /// internal Sort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } #if DEBUG @@ -154,5 +164,5 @@ namespace Microsoft.Z3 } } #endregion - } + } } diff --git a/contrib/cmake/src/api/dotnet/cmake_install_gac.cmake.in b/src/api/dotnet/cmake_install_gac.cmake.in similarity index 100% rename from contrib/cmake/src/api/dotnet/cmake_install_gac.cmake.in rename to src/api/dotnet/cmake_install_gac.cmake.in diff --git a/contrib/cmake/src/api/dotnet/cmake_uninstall_gac.cmake.in b/src/api/dotnet/cmake_uninstall_gac.cmake.in similarity index 100% rename from contrib/cmake/src/api/dotnet/cmake_uninstall_gac.cmake.in rename to src/api/dotnet/cmake_uninstall_gac.cmake.in diff --git a/src/api/java/AST.java b/src/api/java/AST.java index e1cde837f..350830443 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -87,12 +87,10 @@ public class AST extends Z3Object implements Comparable **/ public AST translate(Context ctx) { - if (getContext() == ctx) { return this; } else { - return new AST(ctx, Native.translate(getContext().nCtx(), - getNativeObject(), ctx.nCtx())); + return create(ctx, Native.translate(getContext().nCtx(), getNativeObject(), ctx.nCtx())); } } diff --git a/contrib/cmake/src/api/java/CMakeLists.txt b/src/api/java/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/api/java/CMakeLists.txt rename to src/api/java/CMakeLists.txt diff --git a/src/api/java/Context.java b/src/api/java/Context.java index d9e938086..09683b4a4 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -25,6 +25,12 @@ import java.util.Map; /** * The main interaction with Z3 happens via the Context. + * For applications that spawn an unbounded number of contexts, + * the proper use is within a try-with-resources + * scope so that the Context object gets garbage collected in + * a predictable way. Contexts maintain all data-structures + * related to terms and formulas that are created relative + * to them. **/ public class Context implements AutoCloseable { private final long m_ctx; diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index 71a2e3e1e..6cabbb1b8 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -194,14 +194,7 @@ public class Expr extends AST **/ public Expr translate(Context ctx) { - if (getContext() == ctx) { - return this; - } else { - return Expr.create( - ctx, - Native.translate(getContext().nCtx(), getNativeObject(), - ctx.nCtx())); - } + return (Expr) super.translate(ctx); } /** @@ -1297,6 +1290,15 @@ public class Expr extends AST return Native.getString(getContext().nCtx(), getNativeObject()); } + /** + * Check whether expression is a concatenation + * @return a boolean + */ + public boolean isConcat() + { + return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_SEQ_CONCAT; + } + /** * Indicates whether the term is a binary equivalence modulo namings. * Remarks: This binary predicate is used in proof terms. It captures diff --git a/src/api/java/Fixedpoint.java b/src/api/java/Fixedpoint.java index ad6d5a658..7bb0fda58 100644 --- a/src/api/java/Fixedpoint.java +++ b/src/api/java/Fixedpoint.java @@ -88,6 +88,7 @@ public class Fixedpoint extends Z3Object /** * Add rule into the fixedpoint solver. * + * @param rule implication (Horn clause) representing rule * @param name Nullable rule name. * @throws Z3Exception **/ @@ -178,6 +179,7 @@ public class Fixedpoint extends Z3Object /** * Update named rule into in the fixedpoint solver. * + * @param rule implication (Horn clause) representing rule * @param name Nullable rule name. * @throws Z3Exception **/ diff --git a/src/api/java/FuncDecl.java b/src/api/java/FuncDecl.java index 273e853c0..255bc2c4a 100644 --- a/src/api/java/FuncDecl.java +++ b/src/api/java/FuncDecl.java @@ -1,6 +1,6 @@ /** Copyright (c) 2012-2014 Microsoft Corporation - + Module Name: FuncDecl.java @@ -12,8 +12,8 @@ Author: @author Christoph Wintersteiger (cwinter) 2012-03-15 Notes: - -**/ + +**/ package com.microsoft.z3; @@ -59,6 +59,18 @@ public class FuncDecl extends AST return Native.getFuncDeclId(getContext().nCtx(), getNativeObject()); } + /** + * Translates (copies) the function declaration to the Context {@code ctx}. + * @param ctx A context + * + * @return A copy of the function declaration which is associated with {@code ctx} + * @throws Z3Exception on error + **/ + public FuncDecl translate(Context ctx) + { + return (FuncDecl) super.translate(ctx); + } + /** * The arity of the function declaration **/ @@ -68,7 +80,7 @@ public class FuncDecl extends AST } /** - * The size of the domain of the function declaration + * The size of the domain of the function declaration * @see #getArity **/ public int getDomainSize() @@ -324,7 +336,7 @@ public class FuncDecl extends AST } FuncDecl(Context ctx, Symbol name, Sort[] domain, Sort range) - + { super(ctx, Native.mkFuncDecl(ctx.nCtx(), name.getNativeObject(), AST.arrayLength(domain), AST.arrayToNative(domain), @@ -333,7 +345,7 @@ public class FuncDecl extends AST } FuncDecl(Context ctx, String prefix, Sort[] domain, Sort range) - + { super(ctx, Native.mkFreshFuncDecl(ctx.nCtx(), prefix, AST.arrayLength(domain), AST.arrayToNative(domain), @@ -351,7 +363,7 @@ public class FuncDecl extends AST } /** - * Create expression that applies function to arguments. + * Create expression that applies function to arguments. **/ public Expr apply(Expr ... args) { diff --git a/src/api/java/Quantifier.java b/src/api/java/Quantifier.java index bc2537107..ce2adce21 100644 --- a/src/api/java/Quantifier.java +++ b/src/api/java/Quantifier.java @@ -145,6 +145,19 @@ public class Quantifier extends BoolExpr .nCtx(), getNativeObject())); } + /** + * Translates (copies) the quantifier to the Context {@code ctx}. + * + * @param ctx A context + * + * @return A copy of the quantifier which is associated with {@code ctx} + * @throws Z3Exception on error + **/ + public Quantifier translate(Context ctx) + { + return (Quantifier) super.translate(ctx); + } + /** * Create a quantified expression. * diff --git a/src/api/java/Sort.java b/src/api/java/Sort.java index 0763a69a3..e7a186ad2 100644 --- a/src/api/java/Sort.java +++ b/src/api/java/Sort.java @@ -87,6 +87,19 @@ public class Sort extends AST return Native.sortToString(getContext().nCtx(), getNativeObject()); } + /** + * Translates (copies) the sort to the Context {@code ctx}. + * + * @param ctx A context + * + * @return A copy of the sort which is associated with {@code ctx} + * @throws Z3Exception on error + **/ + public Sort translate(Context ctx) + { + return (Sort) super.translate(ctx); + } + /** * Sort constructor **/ diff --git a/contrib/cmake/src/api/python/CMakeLists.txt b/src/api/python/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/api/python/CMakeLists.txt rename to src/api/python/CMakeLists.txt diff --git a/src/api/python/z3/z3.py b/src/api/python/z3/z3.py index 7e93e58ae..85eae0958 100644 --- a/src/api/python/z3/z3.py +++ b/src/api/python/z3/z3.py @@ -12,7 +12,7 @@ Several online tutorials for Z3Py are available at: http://rise4fun.com/Z3Py/tutorial/guide -Please send feedback, comments and/or corrections to leonardo@microsoft.com. Your comments are very valuable. +Please send feedback, comments and/or corrections on the Issue tracker for https://github.com/Z3prover/z3.git. Your comments are very valuable. Small example: @@ -50,6 +50,7 @@ from fractions import Fraction import sys import io import math +import copy if sys.version < '3': def _is_int(v): @@ -288,6 +289,9 @@ class AstRef(Z3PPObject): if self.ctx.ref() is not None: Z3_dec_ref(self.ctx.ref(), self.as_ast()) + def __deepcopy__(self, memo={}): + return _to_ast_ref(self.ast, self.ctx) + def __str__(self): return obj_to_string(self) @@ -314,7 +318,7 @@ class AstRef(Z3PPObject): raise Z3Exception("Symbolic expressions cannot be cast to concrete Boolean values.") def sexpr(self): - """Return an string representing the AST node in s-expression notation. + """Return a string representing the AST node in s-expression notation. >>> x = Int('x') >>> ((x + 1)*x).sexpr() @@ -4357,6 +4361,11 @@ class Datatype: self.name = name self.constructors = [] + def __deepcopy__(self, memo={}): + r = Datatype(self.name, self.ctx) + r.constructors = copy.deepcopy(self.constructors) + return r + def declare_core(self, name, rec_name, *args): if __debug__: _z3_assert(isinstance(name, str), "String expected") @@ -4647,11 +4656,17 @@ class ParamsRef: Consider using the function `args2params` to create instances of this object. """ - def __init__(self, ctx=None): + def __init__(self, ctx=None, params=None): self.ctx = _get_ctx(ctx) - self.params = Z3_mk_params(self.ctx.ref()) + if params is None: + self.params = Z3_mk_params(self.ctx.ref()) + else: + self.params = params Z3_params_inc_ref(self.ctx.ref(), self.params) + def __deepcopy__(self, memo={}): + return ParamsRef(self.ctx, self.params) + def __del__(self): if self.ctx.ref() is not None: Z3_params_dec_ref(self.ctx.ref(), self.params) @@ -4711,6 +4726,9 @@ class ParamDescrsRef: self.descr = descr Z3_param_descrs_inc_ref(self.ctx.ref(), self.descr) + def __deepcopy__(self, memo={}): + return ParamsDescrsRef(self.descr, self.ctx) + def __del__(self): if self.ctx.ref() is not None: Z3_param_descrs_dec_ref(self.ctx.ref(), self.descr) @@ -4772,6 +4790,9 @@ class Goal(Z3PPObject): self.goal = Z3_mk_goal(self.ctx.ref(), models, unsat_cores, proofs) Z3_goal_inc_ref(self.ctx.ref(), self.goal) + def __deepcopy__(self, memo={}): + return Goal(False, False, False, self.ctx, self.goal) + def __del__(self): if self.goal is not None and self.ctx.ref() is not None: Z3_goal_dec_ref(self.ctx.ref(), self.goal) @@ -5034,6 +5055,9 @@ class AstVector(Z3PPObject): self.ctx = ctx Z3_ast_vector_inc_ref(self.ctx.ref(), self.vector) + def __deepcopy__(self, memo={}): + return AstVector(self.vector, self.ctx) + def __del__(self): if self.vector is not None and self.ctx.ref() is not None: Z3_ast_vector_dec_ref(self.ctx.ref(), self.vector) @@ -5169,6 +5193,9 @@ class AstMap: self.ctx = ctx Z3_ast_map_inc_ref(self.ctx.ref(), self.map) + def __deepcopy__(self, memo={}): + return AstMap(self.map, self.ctx) + def __del__(self): if self.map is not None and self.ctx.ref() is not None: Z3_ast_map_dec_ref(self.ctx.ref(), self.map) @@ -5284,6 +5311,9 @@ class FuncEntry: self.ctx = ctx Z3_func_entry_inc_ref(self.ctx.ref(), self.entry) + def __deepcopy__(self, memo={}): + return FuncEntry(self.entry, self.ctx) + def __del__(self): if self.ctx.ref() is not None: Z3_func_entry_dec_ref(self.ctx.ref(), self.entry) @@ -5390,6 +5420,9 @@ class FuncInterp(Z3PPObject): if self.f is not None: Z3_func_interp_inc_ref(self.ctx.ref(), self.f) + def __deepcopy__(self, memo={}): + return FuncInterp(self.f, self.ctx) + def __del__(self): if self.f is not None and self.ctx.ref() is not None: Z3_func_interp_dec_ref(self.ctx.ref(), self.f) @@ -5500,6 +5533,9 @@ class ModelRef(Z3PPObject): self.ctx = ctx Z3_model_inc_ref(self.ctx.ref(), self.model) + def __deepcopy__(self, memo={}): + return ModelRef(self.m, self.ctx) + def __del__(self): if self.ctx.ref() is not None: Z3_model_dec_ref(self.ctx.ref(), self.model) @@ -5776,6 +5812,9 @@ class Statistics: self.ctx = ctx Z3_stats_inc_ref(self.ctx.ref(), self.stats) + def __deepcopy__(self, memo={}): + return Statistics(self.stats, self.ctx) + def __del__(self): if self.ctx.ref() is not None: Z3_stats_dec_ref(self.ctx.ref(), self.stats) @@ -5910,6 +5949,9 @@ class CheckSatResult: def __init__(self, r): self.r = r + def __deepcopy__(self, memo={}): + return CheckSatResult(self.r) + def __eq__(self, other): return isinstance(other, CheckSatResult) and self.r == other.r @@ -5949,6 +5991,9 @@ class Solver(Z3PPObject): self.solver = solver Z3_solver_inc_ref(self.ctx.ref(), self.solver) + def __deepcopy__(self, memo={}): + return Solver(self.solver, self.ctx) + def __del__(self): if self.solver is not None and self.ctx.ref() is not None: Z3_solver_dec_ref(self.ctx.ref(), self.solver) @@ -6009,6 +6054,24 @@ class Solver(Z3PPObject): """ Z3_solver_pop(self.ctx.ref(), self.solver, num) + def num_scopes(self): + """Return the current number of backtracking points. + + >>> s = Solver() + >>> s.num_scopes() + 0L + >>> s.push() + >>> s.num_scopes() + 1L + >>> s.push() + >>> s.num_scopes() + 2L + >>> s.pop() + >>> s.num_scopes() + 1L + """ + return Z3_solver_get_num_scopes(self.ctx.ref(), self.solver) + def reset(self): """Remove all asserted constraints and backtracking points created using `push()`. @@ -6384,6 +6447,9 @@ class Fixedpoint(Z3PPObject): Z3_fixedpoint_inc_ref(self.ctx.ref(), self.fixedpoint) self.vars = [] + def __deepcopy__(self, memo={}): + return FixedPoint(self.fixedpoint, self.ctx) + def __del__(self): if self.fixedpoint is not None and self.ctx.ref() is not None: Z3_fixedpoint_dec_ref(self.ctx.ref(), self.fixedpoint) @@ -6758,6 +6824,9 @@ class Optimize(Z3PPObject): self.optimize = Z3_mk_optimize(self.ctx.ref()) Z3_optimize_inc_ref(self.ctx.ref(), self.optimize) + def __deepcopy__(self, memo={}): + return Optimize(self.optimize, self.ctx) + def __del__(self): if self.optimize is not None and self.ctx.ref() is not None: Z3_optimize_dec_ref(self.ctx.ref(), self.optimize) @@ -6910,6 +6979,9 @@ class ApplyResult(Z3PPObject): self.ctx = ctx Z3_apply_result_inc_ref(self.ctx.ref(), self.result) + def __deepcopy__(self, memo={}): + return ApplyResult(self.result, self.ctx) + def __del__(self): if self.ctx.ref() is not None: Z3_apply_result_dec_ref(self.ctx.ref(), self.result) @@ -7038,6 +7110,9 @@ class Tactic: raise Z3Exception("unknown tactic '%s'" % tactic) Z3_tactic_inc_ref(self.ctx.ref(), self.tactic) + def __deepcopy__(self, memo={}): + return Tactic(self.tactic, self.ctx) + def __del__(self): if self.tactic is not None and self.ctx.ref() is not None: Z3_tactic_dec_ref(self.ctx.ref(), self.tactic) @@ -7310,6 +7385,9 @@ class Probe: raise Z3Exception("unknown probe '%s'" % probe) Z3_probe_inc_ref(self.ctx.ref(), self.probe) + def __deepcopy__(self, memo={}): + return Probe(self.probe, self.ctx) + def __del__(self): if self.probe is not None and self.ctx.ref() is not None: Z3_probe_dec_ref(self.ctx.ref(), self.probe) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 85d007e70..819e9e54f 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -48,6 +48,7 @@ DEFINE_TYPE(Z3_rcf_num); /*@{*/ /** @name Types + @{ Most of the types in the C API are opaque pointers. @@ -395,6 +396,33 @@ typedef enum The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) + - Z3_OP_BSMUL_NO_OVFL: a predicate to check that bit-wise signed multiplication does not overflow. + Signed multiplication overflows if the operands have the same sign and the result of multiplication + does not fit within the available bits. \sa Z3_mk_bvmul_no_overflow. + + - Z3_OP_BUMUL_NO_OVFL: check that bit-wise unsigned multiplication does not overflow. + Unsigned multiplication overflows if the result does not fit within the available bits. + \sa Z3_mk_bvmul_no_overflow. + + - Z3_OP_BSMUL_NO_UDFL: check that bit-wise signed multiplication does not underflow. + Signed multiplication underflows if the operands have opposite signs and the result of multiplication + does not fit within the avaialble bits. Z3_mk_bvmul_no_underflow. + + - Z3_OP_BSDIV_I: Binary signed division. + It has the same semantics as Z3_OP_BSDIV, but created in a context where the second operand can be assumed to be non-zero. + + - Z3_OP_BUDIV_I: Binary unsigned division. + It has the same semantics as Z3_OP_BUDIV, but created in a context where the second operand can be assumed to be non-zero. + + - Z3_OP_BSREM_I: Binary signed remainder. + It has the same semantics as Z3_OP_BSREM, but created in a context where the second operand can be assumed to be non-zero. + + - Z3_OP_BUREM_I: Binary unsigned remainder. + It has the same semantics as Z3_OP_BUREM, but created in a context where the second operand can be assumed to be non-zero. + + - Z3_OP_BSMOD_I: Binary signed modulus. + It has the same semantics as Z3_OP_BSMOD, but created in a context where the second operand can be assumed to be non-zero. + - Z3_OP_PR_UNDEF: Undef/Null proof object. - Z3_OP_PR_TRUE: Proof for the expression 'true'. @@ -5238,7 +5266,6 @@ extern "C" { def_API('Z3_get_error_msg', STRING, (_in(CONTEXT), _in(ERROR_CODE))) */ Z3_string Z3_API Z3_get_error_msg(Z3_context c, Z3_error_code err); - /*@}*/ /** \brief Return a string describing the given error code. @@ -5349,6 +5376,13 @@ extern "C" { /** \brief Add a new formula \c a to the given goal. + The formula is split according to the following procedure that is applied + until a fixed-point: + Conjunctions are split into separate formulas. + Negations are distributed over disjunctions, resulting in separate formulas. + If the goal is \c false, adding new formulas is a no-op. + If the formula \c a is \c true, then nothing is added. + If the formula \c a is \c false, then the entire goal is replaced by the formula \c false. def_API('Z3_goal_assert', VOID, (_in(CONTEXT), _in(GOAL), _in(AST))) */ @@ -5791,9 +5825,35 @@ extern "C" { /** @name Solvers*/ /*@{*/ /** - \brief Create a new (incremental) solver. This solver also uses a - set of builtin tactics for handling the first check-sat command, and - check-sat commands that take more than a given number of milliseconds to be solved. + \brief Create a new solver. This solver is a "combined solver" (see + combined_solver module) that internally uses a non-incremental (solver1) and an + incremental solver (solver2). This combined solver changes its behaviour based + on how it is used and how its parameters are set. + + If the solver is used in a non incremental way (i.e. no calls to + `Z3_solver_push()` or `Z3_solver_pop()`, and no calls to + `Z3_solver_assert()` or `Z3_solver_assert_and_track()` after checking + satisfiability without an intervening `Z3_solver_reset()`) then solver1 + will be used. This solver will apply Z3's "default" tactic. + + The "default" tactic will attempt to probe the logic used by the + assertions and will apply a specialized tactic if one is supported. + Otherwise the general `(and-then simplify smt)` tactic will be used. + + If the solver is used in an incremental way then the combined solver + will switch to using solver2 (which behaves similarly to the general + "smt" tactic). + + Note however it is possible to set the `solver2_timeout`, + `solver2_unknown`, and `ignore_solver1` parameters of the combined + solver to change its behaviour. + + The function #Z3_solver_get_model retrieves a model if the + assertions is satisfiable (i.e., the result is \c + Z3_L_TRUE) and model construction is enabled. + The function #Z3_solver_get_model can also be used even + if the result is \c Z3_L_UNDEF, but the returned model + is not guaranteed to satisfy quantified assertions. \remark User must use #Z3_solver_inc_ref and #Z3_solver_dec_ref to manage solver objects. Even if the context was created using #Z3_mk_context instead of #Z3_mk_context_rc. @@ -5803,7 +5863,17 @@ extern "C" { Z3_solver Z3_API Z3_mk_solver(Z3_context c); /** - \brief Create a new (incremental) solver. + \brief Create a new incremental solver. + + This is equivalent to applying the "smt" tactic. + + Unlike `Z3_mk_solver()` this solver + - Does not attempt to apply any logic specific tactics. + - Does not change its behaviour based on whether it used + incrementally/non-incrementally. + + Note that these differences can result in very different performance + compared to `Z3_mk_solver()`. The function #Z3_solver_get_model retrieves a model if the assertions is satisfiable (i.e., the result is \c diff --git a/src/api/z3_optimization.h b/src/api/z3_optimization.h index 795b4b8fd..f49e1b9ce 100644 --- a/src/api/z3_optimization.h +++ b/src/api/z3_optimization.h @@ -75,7 +75,7 @@ extern "C" { \brief Add a maximization constraint. \param c - context \param o - optimization context - \param a - arithmetical term + \param t - arithmetical term def_API('Z3_optimize_maximize', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST))) */ unsigned Z3_API Z3_optimize_maximize(Z3_context c, Z3_optimize o, Z3_ast t); @@ -84,7 +84,7 @@ extern "C" { \brief Add a minimization constraint. \param c - context \param o - optimization context - \param a - arithmetical term + \param t - arithmetical term def_API('Z3_optimize_minimize', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST))) */ diff --git a/contrib/cmake/src/ast/CMakeLists.txt b/src/ast/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/CMakeLists.txt rename to src/ast/CMakeLists.txt diff --git a/src/ast/arith_decl_plugin.h b/src/ast/arith_decl_plugin.h index beb227c33..6d6da9ed5 100644 --- a/src/ast/arith_decl_plugin.h +++ b/src/ast/arith_decl_plugin.h @@ -275,7 +275,9 @@ public: bool is_uminus(expr const * n) const { return is_app_of(n, m_afid, OP_UMINUS); } bool is_mul(expr const * n) const { return is_app_of(n, m_afid, OP_MUL); } bool is_div(expr const * n) const { return is_app_of(n, m_afid, OP_DIV); } + bool is_div0(expr const * n) const { return is_app_of(n, m_afid, OP_DIV_0); } bool is_idiv(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV); } + bool is_idiv0(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV_0); } bool is_mod(expr const * n) const { return is_app_of(n, m_afid, OP_MOD); } bool is_rem(expr const * n) const { return is_app_of(n, m_afid, OP_REM); } bool is_to_real(expr const * n) const { return is_app_of(n, m_afid, OP_TO_REAL); } diff --git a/src/ast/ast.h b/src/ast/ast.h index 6bb3b01c9..f71d5135c 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -667,6 +667,8 @@ public: expr * get_arg(unsigned idx) const { SASSERT(idx < m_num_args); return m_args[idx]; } expr * const * get_args() const { return m_args; } unsigned get_size() const { return get_obj_size(get_num_args()); } + expr * const * begin() const { return m_args; } + expr * const * end() const { return m_args + m_num_args; } unsigned get_depth() const { return flags()->m_depth; } bool is_ground() const { return flags()->m_ground; } @@ -2082,6 +2084,7 @@ public: bool is_undef_proof(expr const * e) const { return e == m_undef_proof; } bool is_asserted(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_ASSERTED); } + bool is_hypothesis (expr const *e) const {return is_app_of (e, m_basic_family_id, PR_HYPOTHESIS);} bool is_goal(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_GOAL); } bool is_modus_ponens(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_MODUS_PONENS); } bool is_reflexivity(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_REFLEXIVITY); } @@ -2112,6 +2115,7 @@ public: bool is_skolemize(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_SKOLEMIZE); } MATCH_UNARY(is_asserted); + MATCH_UNARY(is_hypothesis); MATCH_UNARY(is_lemma); bool has_fact(proof const * p) const { diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index 89af8bd3e..f97397108 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -429,8 +429,18 @@ format_ns::format * smt2_pp_environment::pp_sort(sort * s) { if ((get_sutil().is_seq(s) || get_sutil().is_re(s)) && !get_sutil().is_string(s)) { ptr_buffer fs; fs.push_back(pp_sort(to_sort(s->get_parameter(0).get_ast()))); - return mk_seq1(m, fs.begin(), fs.end(), f2f(), get_sutil().is_seq(s)?"Seq":"Re"); + return mk_seq1(m, fs.begin(), fs.end(), f2f(), get_sutil().is_seq(s)?"Seq":"RegEx"); } +#if 0 + if (get_dtutil().is_datatype(s)) { + ptr_buffer fs; + unsigned sz = get_dtutil().get_datatype_num_parameter_sorts(s); + for (unsigned i = 0; i < sz; i++) { + fs.push_back(pp_sort(get_dtutil().get_datatype_parameter_sort(s, i))); + } + return mk_seq1(m, fs.begin(), fs.end(), f2f(), s->get_name().str().c_str()); + } +#endif return format_ns::mk_string(get_manager(), s->get_name().str().c_str()); } @@ -557,7 +567,14 @@ class smt2_printer { format * f; if (v->get_idx() < m_var_names.size()) { symbol s = m_var_names[m_var_names.size() - v->get_idx() - 1]; - f = mk_string(m(), s.str().c_str()); + std::string vname; + if (is_smt2_quoted_symbol (s)) { + vname = mk_smt2_quoted_symbol (s); + } + else { + vname = s.str(); + } + f = mk_string(m(), vname.c_str ()); } else { // fallback... it is not supposed to happen when the printer is correctly used. @@ -884,7 +901,14 @@ class smt2_printer { symbol * it = m_var_names.end() - num_decls; for (unsigned i = 0; i < num_decls; i++, it++) { format * fs[1] = { m_env.pp_sort(q->get_decl_sort(i)) }; - buf.push_back(mk_seq1(m(), fs, fs+1, f2f(), it->str().c_str())); + std::string var_name; + if (is_smt2_quoted_symbol (*it)) { + var_name = mk_smt2_quoted_symbol (*it); + } + else { + var_name = it->str ();\ + } + buf.push_back(mk_seq1(m(), fs, fs+1, f2f(), var_name.c_str ())); } return mk_seq5(m(), buf.begin(), buf.end(), f2f()); } diff --git a/src/ast/ast_smt2_pp.h b/src/ast/ast_smt2_pp.h index f2d177041..c3e72f7bc 100644 --- a/src/ast/ast_smt2_pp.h +++ b/src/ast/ast_smt2_pp.h @@ -30,6 +30,7 @@ Revision History: #include"fpa_decl_plugin.h" #include"dl_decl_plugin.h" #include"seq_decl_plugin.h" +#include"datatype_decl_plugin.h" #include"smt2_util.h" class smt2_pp_environment { @@ -50,6 +51,7 @@ public: virtual fpa_util & get_futil() = 0; virtual seq_util & get_sutil() = 0; virtual datalog::dl_decl_util& get_dlutil() = 0; + virtual datatype_util& get_dtutil() = 0; virtual bool uses(symbol const & s) const = 0; virtual format_ns::format * pp_fdecl(func_decl * f, unsigned & len); virtual format_ns::format * pp_bv_literal(app * t, bool use_bv_lits, bool bv_neg); @@ -74,9 +76,10 @@ class smt2_pp_environment_dbg : public smt2_pp_environment { array_util m_arutil; fpa_util m_futil; seq_util m_sutil; + datatype_util m_dtutil; datalog::dl_decl_util m_dlutil; public: - smt2_pp_environment_dbg(ast_manager & m):m_manager(m), m_autil(m), m_bvutil(m), m_arutil(m), m_futil(m), m_sutil(m), m_dlutil(m) {} + smt2_pp_environment_dbg(ast_manager & m):m_manager(m), m_autil(m), m_bvutil(m), m_arutil(m), m_futil(m), m_sutil(m), m_dtutil(m), m_dlutil(m) {} virtual ast_manager & get_manager() const { return m_manager; } virtual arith_util & get_autil() { return m_autil; } virtual bv_util & get_bvutil() { return m_bvutil; } @@ -84,6 +87,7 @@ public: virtual array_util & get_arutil() { return m_arutil; } virtual fpa_util & get_futil() { return m_futil; } virtual datalog::dl_decl_util& get_dlutil() { return m_dlutil; } + virtual datatype_util& get_dtutil() { return m_dtutil; } virtual bool uses(symbol const & s) const { return false; } }; diff --git a/src/ast/ast_smt_pp.cpp b/src/ast/ast_smt_pp.cpp index 706f65ac4..fe02f24a0 100644 --- a/src/ast/ast_smt_pp.cpp +++ b/src/ast/ast_smt_pp.cpp @@ -366,7 +366,22 @@ class smt_printer { return; } else if (s->is_sort_of(m_dt_fid, DATATYPE_SORT)) { - m_out << m_renaming.get_symbol(s->get_name()); + m_out << m_renaming.get_symbol(s->get_name()); +#if 0 + datatype_util util(m_manager); + unsigned num_sorts = util.get_datatype_num_parameter_sorts(s); + if (num_sorts > 0) { + m_out << "("; + } + + if (num_sorts > 0) { + for (unsigned i = 0; i < num_sorts; ++i) { + m_out << " "; + visit_sort(util.get_datatype_parameter_sort(s, i)); + } + m_out << ")"; + } +#endif return; } else { diff --git a/src/ast/bv_decl_plugin.cpp b/src/ast/bv_decl_plugin.cpp index 03b4fe637..321943c72 100644 --- a/src/ast/bv_decl_plugin.cpp +++ b/src/ast/bv_decl_plugin.cpp @@ -732,7 +732,7 @@ void bv_decl_plugin::get_op_names(svector & op_names, symbol const op_names.push_back(builtin_name("bvudiv_i", OP_BUDIV_I)); op_names.push_back(builtin_name("bvsrem_i", OP_BSREM_I)); op_names.push_back(builtin_name("bvurem_i", OP_BUREM_I)); - op_names.push_back(builtin_name("bvumod_i", OP_BSMOD_I)); + op_names.push_back(builtin_name("bvsmod_i", OP_BSMOD_I)); op_names.push_back(builtin_name("ext_rotate_left",OP_EXT_ROTATE_LEFT)); op_names.push_back(builtin_name("ext_rotate_right",OP_EXT_ROTATE_RIGHT)); diff --git a/src/ast/datatype_decl_plugin.cpp b/src/ast/datatype_decl_plugin.cpp index 4d531d2db..34b092ee9 100644 --- a/src/ast/datatype_decl_plugin.cpp +++ b/src/ast/datatype_decl_plugin.cpp @@ -20,6 +20,7 @@ Revision History: #include"warning.h" #include"ast_smt2_pp.h" + /** \brief Auxiliary class used to declare inductive datatypes. */ @@ -124,6 +125,7 @@ static parameter const & read(unsigned num_parameters, parameter const * paramet static int read_int(unsigned num_parameters, parameter const * parameters, unsigned idx, bool_buffer & read_pos) { const parameter & r = read(num_parameters, parameters, idx, read_pos); if (!r.is_int()) { + TRACE("datatype", tout << "expected integer parameter at position " << idx << " got: " << r << "\n";); throw invalid_datatype(); } return r.get_int(); @@ -132,11 +134,25 @@ static int read_int(unsigned num_parameters, parameter const * parameters, unsig static symbol read_symbol(unsigned num_parameters, parameter const * parameters, unsigned idx, bool_buffer & read_pos) { parameter const & r = read(num_parameters, parameters, idx, read_pos); if (!r.is_symbol()) { + TRACE("datatype", tout << "expected symol parameter at position " << idx << " got: " << r << "\n";); throw invalid_datatype(); } return r.get_symbol(); } +static sort* read_sort(unsigned num_parameters, parameter const * parameters, unsigned idx, bool_buffer & read_pos) { + parameter const & r = read(num_parameters, parameters, idx, read_pos); + if (!r.is_ast()) { + TRACE("datatype", tout << "expected ast parameter at position " << idx << " got: " << r << "\n";); + throw invalid_datatype(); + } + ast* a = r.get_ast(); + if (!is_sort(a)) { + throw invalid_datatype(); + } + return to_sort(a); +} + enum status { WHITE, GRAY, @@ -160,7 +176,7 @@ static bool is_recursive_datatype(parameter const * parameters) { continue; } already_found[tid] = GRAY; - unsigned o = parameters[2 + 2*tid + 1].get_int(); // constructor offset + unsigned o = datatype_decl_plugin::constructor_offset(parameters, tid); // constructor offset unsigned num_constructors = parameters[o].get_int(); bool can_process = true; for (unsigned s = 1; s <= num_constructors; s++) { @@ -210,7 +226,7 @@ static sort_size get_datatype_size(parameter const * parameters) { continue; } already_found[tid] = GRAY; - unsigned o = parameters[2 + 2*tid + 1].get_int(); // constructor offset + unsigned o = datatype_decl_plugin::constructor_offset(parameters, tid); unsigned num_constructors = parameters[o].get_int(); bool is_very_big = false; bool can_process = true; @@ -296,7 +312,7 @@ static bool is_well_founded(parameter const * parameters) { changed = false; for (unsigned tid = 0; tid < num_types; tid++) { if (!well_founded[tid]) { - unsigned o = parameters[2 + 2*tid + 1].get_int(); // constructor offset + unsigned o = datatype_decl_plugin::constructor_offset(parameters, tid); // constructor offset unsigned num_constructors = parameters[o].get_int(); for (unsigned s = 1; s <= num_constructors; s++) { unsigned k_i = parameters[o + s].get_int(); @@ -350,9 +366,14 @@ sort * datatype_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, param throw invalid_datatype(); } unsigned tid = read_int(num_parameters, parameters, 1, found); + unsigned num_sort_params = read_int(num_parameters, parameters, 2, found); + for (unsigned j = 0; j < num_sort_params; ++j) { + read_sort(num_parameters, parameters, 3 + j, found); + } + unsigned c_offset = constructor_offset(parameters); for (unsigned j = 0; j < num_types; j++) { - read_symbol(num_parameters, parameters, 2 + 2*j, found); // type name - unsigned o = read_int(num_parameters, parameters, 2 + 2*j + 1, found); + read_symbol(num_parameters, parameters, c_offset + 2*j, found); // type name + unsigned o = read_int(num_parameters, parameters, c_offset + 2*j + 1, found); unsigned num_constructors = read_int(num_parameters, parameters, o, found); if (num_constructors == 0) { throw invalid_datatype(); @@ -368,9 +389,9 @@ sort * datatype_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, param parameter const & a_type = read(num_parameters, parameters, first_accessor + 2*r + 1, found); // accessort type if (!a_type.is_int() && !a_type.is_ast()) { throw invalid_datatype(); - if (a_type.is_ast() && !is_sort(a_type.get_ast())) { - throw invalid_datatype(); - } + } + if (a_type.is_ast() && !is_sort(a_type.get_ast())) { + throw invalid_datatype(); } } } @@ -387,7 +408,7 @@ sort * datatype_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, param // compute datatype size sort_size ts = get_datatype_size(parameters); - symbol const & tname = parameters[2+2*tid].get_symbol(); + symbol const & tname = parameters[c_offset + 2*tid].get_symbol(); return m_manager->mk_sort(tname, sort_info(m_family_id, k, ts, num_parameters, parameters, true)); } @@ -489,7 +510,7 @@ func_decl * datatype_decl_plugin::mk_func_decl(decl_kind k, unsigned num_paramet } unsigned c_idx = parameters[1].get_int(); unsigned tid = datatype->get_parameter(1).get_int(); - unsigned o = datatype->get_parameter(2 + 2 * tid + 1).get_int(); + unsigned o = datatype_decl_plugin::constructor_offset(datatype, tid); unsigned num_constructors = datatype->get_parameter(o).get_int(); if (c_idx >= num_constructors) { m_manager->raise_exception("invalid parameters for datatype operator"); @@ -504,8 +525,6 @@ func_decl * datatype_decl_plugin::mk_func_decl(decl_kind k, unsigned num_paramet return 0; } else { - - symbol c_name = datatype->get_parameter(k_i).get_symbol(); unsigned num_accessors = datatype->get_parameter(k_i + 2).get_int(); if (num_accessors != arity) { @@ -577,16 +596,22 @@ func_decl * datatype_decl_plugin::mk_func_decl(decl_kind k, unsigned num_paramet } } -bool datatype_decl_plugin::mk_datatypes(unsigned num_datatypes, datatype_decl * const * datatypes, sort_ref_vector & new_types) { +bool datatype_decl_plugin::mk_datatypes(unsigned num_datatypes, datatype_decl * const * datatypes, unsigned num_params, sort* const* sort_params, sort_ref_vector & new_types) { buffer p; p.push_back(parameter(num_datatypes)); p.push_back(parameter(-1)); + p.push_back(parameter(num_params)); + for (unsigned i = 0; i < num_params; ++i) { + p.push_back(parameter(sort_params[i])); + } + + unsigned c_offset = constructor_offset(p.c_ptr()); for (unsigned i = 0; i < num_datatypes; i++) { p.push_back(parameter(datatypes[i]->get_name())); p.push_back(parameter(-1)); // offset is unknown at this point } for (unsigned i = 0; i < num_datatypes; i++) { - p[3+2*i] = parameter(p.size()); // save offset to constructor table + p[c_offset + 1 + 2*i] = parameter(p.size()); // save offset to constructor table ptr_vector const & constructors = datatypes[i]->get_constructors(); unsigned num_constructors = constructors.size(); p.push_back(parameter(num_constructors)); @@ -595,7 +620,7 @@ bool datatype_decl_plugin::mk_datatypes(unsigned num_datatypes, datatype_decl * } } for (unsigned i = 0; i < num_datatypes; i++) { - unsigned o = p[3+2*i].get_int(); + unsigned o = constructor_offset(p.c_ptr(), i); ptr_vector const & constructors = datatypes[i]->get_constructors(); unsigned num_constructors = constructors.size(); for (unsigned j = 0; j < num_constructors; j++) { @@ -655,7 +680,7 @@ bool datatype_decl_plugin::is_fully_interp(sort const * s) const { parameter const * parameters = s->get_parameters(); unsigned num_types = parameters[0].get_int(); for (unsigned tid = 0; tid < num_types; tid++) { - unsigned o = parameters[2 + 2*tid + 1].get_int(); // constructor offset + unsigned o = datatype_decl_plugin::constructor_offset(s, tid); unsigned num_constructors = parameters[o].get_int(); for (unsigned si = 1; si <= num_constructors; si++) { unsigned k_i = parameters[o + si].get_int(); @@ -692,6 +717,28 @@ bool datatype_decl_plugin::is_value_visit(expr * arg, ptr_buffer & todo) co } } +unsigned datatype_decl_plugin::constructor_offset(sort const* s) { + return constructor_offset(s->get_parameters()); +} + +unsigned datatype_decl_plugin::constructor_offset(parameter const& p) { + return 3 + p.get_int(); +} + +unsigned datatype_decl_plugin::constructor_offset(parameter const* ps) { + return constructor_offset(ps[2]); +} + +unsigned datatype_decl_plugin::constructor_offset(sort const* s, unsigned tid) { + unsigned c_offset = constructor_offset(s->get_parameters()); + return s->get_parameter(c_offset + 1 + 2*tid).get_int(); +} + +unsigned datatype_decl_plugin::constructor_offset(parameter const* ps, unsigned tid) { + unsigned c_offset = constructor_offset(ps[2]); + return ps[c_offset + 1 + 2*tid].get_int(); +} + bool datatype_decl_plugin::is_value(app * e) const { TRACE("dt_is_value", tout << "checking\n" << mk_ismt2_pp(e, *m_manager) << "\n";); if (!get_util().is_constructor(e)) @@ -742,7 +789,7 @@ datatype_util::~datatype_util() { func_decl * datatype_util::get_constructor(sort * ty, unsigned c_id) { unsigned tid = ty->get_parameter(1).get_int(); - unsigned o = ty->get_parameter(3 + 2*tid).get_int(); + unsigned o = datatype_decl_plugin::constructor_offset(ty, tid); unsigned k_i = ty->get_parameter(o + c_id + 1).get_int(); unsigned num_accessors = ty->get_parameter(k_i + 2).get_int(); parameter p[2] = { parameter(ty), parameter(c_id) }; @@ -765,7 +812,7 @@ ptr_vector const * datatype_util::get_datatype_constructors(sort * ty m_vectors.push_back(r); m_datatype2constructors.insert(ty, r); unsigned tid = ty->get_parameter(1).get_int(); - unsigned o = ty->get_parameter(3 + 2*tid).get_int(); + unsigned o = datatype_decl_plugin::constructor_offset(ty, tid); unsigned num_constructors = ty->get_parameter(o).get_int(); for (unsigned c_id = 0; c_id < num_constructors; c_id++) { func_decl * c = get_constructor(ty, c_id); @@ -880,7 +927,7 @@ ptr_vector const * datatype_util::get_constructor_accessors(func_decl unsigned c_id = constructor->get_parameter(1).get_int(); sort * datatype = constructor->get_range(); unsigned tid = datatype->get_parameter(1).get_int(); - unsigned o = datatype->get_parameter(3 + 2*tid).get_int(); + unsigned o = datatype_decl_plugin::constructor_offset(datatype, tid); unsigned k_i = datatype->get_parameter(o + c_id + 1).get_int(); unsigned num_accessors = datatype->get_parameter(k_i+2).get_int(); parameter p[3] = { parameter(datatype), parameter(c_id), parameter(-1) }; diff --git a/src/ast/datatype_decl_plugin.h b/src/ast/datatype_decl_plugin.h index ba0bedd32..b2bcf3ab0 100644 --- a/src/ast/datatype_decl_plugin.h +++ b/src/ast/datatype_decl_plugin.h @@ -100,10 +100,16 @@ public: Contract for sort: parameters[0] - (int) n - number of recursive types. parameters[1] - (int) i - index 0..n-1 of which type is defined. - + + parameters[2] - (int) p - number of type parameters. + + for j = 0..p-1 + parameters[3 + j] - (sort) s - type parameter + + c_offset := 3 + p for j in 0..n-1 - parameters[2 + 2*j] - (symbol) name of the type - parameters[2 + 2*j + 1] - (int) o - offset where the constructors are defined. + parameters[c_offset + 2*j] - (symbol) name of the type + parameters[c_offset + 2*j + 1] - (int) o - offset where the constructors are defined. for each offset o at parameters[2 + 2*j + 1] for some j in 0..n-1 parameters[o] - (int) m - number of constructors @@ -140,7 +146,7 @@ public: virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); - bool mk_datatypes(unsigned num_datatypes, datatype_decl * const * datatypes, sort_ref_vector & new_sorts); + bool mk_datatypes(unsigned num_datatypes, datatype_decl * const * datatypes, unsigned num_params, sort* const* sort_params, sort_ref_vector & new_sorts); virtual expr * get_some_value(sort * s); @@ -152,6 +158,13 @@ public: virtual void get_op_names(svector & op_names, symbol const & logic); + static unsigned constructor_offset(sort const* s); + static unsigned constructor_offset(parameter const& p); + static unsigned constructor_offset(parameter const* ps); + + static unsigned constructor_offset(sort const* s, unsigned tid); + static unsigned constructor_offset(parameter const* ps, unsigned tid); + private: bool is_value_visit(expr * arg, ptr_buffer & todo) const; @@ -201,9 +214,18 @@ public: unsigned get_datatype_num_constructors(sort * ty) { SASSERT(is_datatype(ty)); unsigned tid = ty->get_parameter(1).get_int(); - unsigned o = ty->get_parameter(3 + 2 * tid).get_int(); + unsigned o = datatype_decl_plugin::constructor_offset(ty, tid); return ty->get_parameter(o).get_int(); } + unsigned get_datatype_num_parameter_sorts(sort * ty) { + SASSERT(is_datatype(ty)); + return ty->get_parameter(2).get_int(); + } + sort* get_datatype_parameter_sort(sort * ty, unsigned idx) { + SASSERT(is_datatype(ty)); + SASSERT(idx < get_datatype_num_parameter_sorts(ty)); + return to_sort(ty->get_parameter(3 + idx).get_ast()); + } unsigned get_constructor_idx(func_decl * f) const { SASSERT(is_constructor(f)); return f->get_parameter(1).get_int(); } unsigned get_recognizer_constructor_idx(func_decl * f) const { SASSERT(is_recognizer(f)); return f->get_parameter(1).get_int(); } func_decl * get_non_rec_constructor(sort * ty); @@ -218,6 +240,7 @@ public: void reset(); void display_datatype(sort *s, std::ostream& strm); + }; #endif /* DATATYPE_DECL_PLUGIN_H_ */ diff --git a/src/ast/expr_map.h b/src/ast/expr_map.h index ddd94ea13..2b49a4a30 100644 --- a/src/ast/expr_map.h +++ b/src/ast/expr_map.h @@ -35,6 +35,13 @@ class expr_map { obj_map m_expr2expr; obj_map m_expr2pr; public: + typedef obj_map Map; + typedef Map::iterator iterator; + typedef Map::key key; + typedef Map::value value; + typedef Map::data data; + typedef Map::entry entry; + expr_map(ast_manager & m); expr_map(ast_manager & m, bool store_proofs); ~expr_map(); @@ -44,6 +51,8 @@ public: void erase(expr * k); void reset(); void flush(); + iterator begin () const { return m_expr2expr.begin (); } + iterator end () const {return m_expr2expr.end (); } void set_store_proofs(bool f) { if (m_store_proofs != f) flush(); m_store_proofs = f; diff --git a/contrib/cmake/src/ast/fpa/CMakeLists.txt b/src/ast/fpa/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/fpa/CMakeLists.txt rename to src/ast/fpa/CMakeLists.txt diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 2c0ba1ce1..99b8c5ac8 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1632,8 +1632,6 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, res_exp = e_exp; - // Result could overflow into 4.xxx ... - family_id bvfid = m_bv_util.get_fid(); expr_ref res_sgn_c1(m), res_sgn_c2(m), res_sgn_c3(m); expr_ref not_e_sgn(m), not_f_sgn(m), not_sign_bv(m); @@ -1646,11 +1644,34 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, expr * res_sgn_or_args[3] = { res_sgn_c1, res_sgn_c2, res_sgn_c3 }; res_sgn = m_bv_util.mk_bv_or(3, res_sgn_or_args); + // Result could have overflown into 4.xxx. + SASSERT(m_bv_util.get_bv_size(sig_abs) == 2 * sbits + 2); + expr_ref ovfl_into_4(m); + ovfl_into_4 = m.mk_eq(m_bv_util.mk_extract(2 * sbits + 1, 2 * sbits, sig_abs), + m_bv_util.mk_numeral(1, 2)); + dbg_decouple("fpa2bv_fma_ovfl_into_4", ovfl_into_4); if (sbits > 5) { - sticky_raw = m_bv_util.mk_extract(sbits - 5, 0, sig_abs); - sticky = m_bv_util.mk_zero_extend(sbits + 3, m.mk_app(bvfid, OP_BREDOR, sticky_raw.get())); - expr * res_or_args[2] = { m_bv_util.mk_extract(2 * sbits - 1, sbits - 4, sig_abs), sticky }; - res_sig = m_bv_util.mk_bv_or(2, res_or_args); + expr_ref sticky_raw(m), sig_upper(m), sticky_redd(m), res_sig_norm(m); + sticky_raw = m_bv_util.mk_extract(sbits - 4, 0, sig_abs); + sig_upper = m_bv_util.mk_extract(2 * sbits, sbits - 3, sig_abs); + SASSERT(m_bv_util.get_bv_size(sig_upper) == sbits + 4); + sticky_redd = m.mk_app(bvfid, OP_BREDOR, sticky_raw.get()); + sticky = m_bv_util.mk_zero_extend(sbits + 3, sticky_redd); + expr * res_or_args[2] = { sig_upper, sticky }; + res_sig_norm = m_bv_util.mk_bv_or(2, res_or_args); + + expr_ref sticky_raw_ovfl(m), sig_upper_ovfl(m), sticky_redd_ovfl(m), sticky_ovfl(m), res_sig_ovfl(m); + sticky_raw_ovfl = m_bv_util.mk_extract(sbits - 4, 0, sig_abs); + sig_upper_ovfl = m_bv_util.mk_extract(2 * sbits, sbits - 3, sig_abs); + SASSERT(m_bv_util.get_bv_size(sig_upper_ovfl) == sbits + 4); + sticky_redd_ovfl = m.mk_app(bvfid, OP_BREDOR, sticky_raw_ovfl.get()); + sticky_ovfl = m_bv_util.mk_zero_extend(sbits + 3, sticky_redd_ovfl); + expr * res_or_args_ovfl[2] = { sig_upper_ovfl, sticky_ovfl }; + res_sig_ovfl = m_bv_util.mk_bv_or(2, res_or_args_ovfl); + + res_sig = m.mk_ite(ovfl_into_4, res_sig_ovfl, res_sig_norm); + res_exp = m.mk_ite(ovfl_into_4, m_bv_util.mk_bv_add(res_exp, m_bv_util.mk_numeral(1, ebits+2)), + res_exp); } else { unsigned too_short = 6 - sbits; @@ -1658,6 +1679,8 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, res_sig = m_bv_util.mk_extract(sbits + 3, 0, sig_abs); } dbg_decouple("fpa2bv_fma_add_sum_sticky", sticky); + dbg_decouple("fpa2bv_fma_sig_abs", sig_abs); + dbg_decouple("fpa2bv_fma_res_sig", res_sig); SASSERT(m_bv_util.get_bv_size(res_sig) == sbits + 4); expr_ref is_zero_sig(m), nil_sbits4(m); diff --git a/contrib/cmake/src/ast/macros/CMakeLists.txt b/src/ast/macros/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/macros/CMakeLists.txt rename to src/ast/macros/CMakeLists.txt diff --git a/contrib/cmake/src/ast/normal_forms/CMakeLists.txt b/src/ast/normal_forms/CMakeLists.txt similarity index 81% rename from contrib/cmake/src/ast/normal_forms/CMakeLists.txt rename to src/ast/normal_forms/CMakeLists.txt index 30702cd8c..69288d92b 100644 --- a/contrib/cmake/src/ast/normal_forms/CMakeLists.txt +++ b/src/ast/normal_forms/CMakeLists.txt @@ -8,4 +8,6 @@ z3_add_component(normal_forms rewriter PYG_FILES nnf_params.pyg + EXTRA_REGISTER_MODULE_HEADERS + nnf.h ) diff --git a/contrib/cmake/src/ast/pattern/CMakeLists.txt b/src/ast/pattern/CMakeLists.txt similarity index 92% rename from contrib/cmake/src/ast/pattern/CMakeLists.txt rename to src/ast/pattern/CMakeLists.txt index 59e0545a1..6e8301afc 100644 --- a/contrib/cmake/src/ast/pattern/CMakeLists.txt +++ b/src/ast/pattern/CMakeLists.txt @@ -2,7 +2,7 @@ # for other components then we should refactor this code into # z3_add_component() if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/database.h") - message(FATAL_ERROR "The generated file \"database.h\"" + message(FATAL_ERROR "The generated file \"${CMAKE_CURRENT_SOURCE_DIR}/database.h\"" ${z3_polluted_tree_msg}) endif() diff --git a/src/ast/pb_decl_plugin.h b/src/ast/pb_decl_plugin.h index 0750dcac7..36b1a9512 100644 --- a/src/ast/pb_decl_plugin.h +++ b/src/ast/pb_decl_plugin.h @@ -109,6 +109,7 @@ public: bool is_ge(func_decl* a) const; bool is_ge(expr* a) const { return is_app(a) && is_ge(to_app(a)->get_decl()); } bool is_ge(expr* a, rational& k) const; + bool is_aux_bool(func_decl* f) const { return is_decl_of(f, m_fid, OP_PB_AUX_BOOL); } bool is_aux_bool(expr* e) const { return is_app_of(e, m_fid, OP_PB_AUX_BOOL); } rational get_coeff(expr* a, unsigned index) const { return get_coeff(to_app(a)->get_decl(), index); } rational get_coeff(func_decl* a, unsigned index) const; diff --git a/contrib/cmake/src/ast/proof_checker/CMakeLists.txt b/src/ast/proof_checker/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/proof_checker/CMakeLists.txt rename to src/ast/proof_checker/CMakeLists.txt diff --git a/contrib/cmake/src/ast/rewriter/CMakeLists.txt b/src/ast/rewriter/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/rewriter/CMakeLists.txt rename to src/ast/rewriter/CMakeLists.txt diff --git a/src/ast/rewriter/arith_rewriter.cpp b/src/ast/rewriter/arith_rewriter.cpp index fa3d69602..b00e1eb6d 100644 --- a/src/ast/rewriter/arith_rewriter.cpp +++ b/src/ast/rewriter/arith_rewriter.cpp @@ -1030,7 +1030,7 @@ br_status arith_rewriter::mk_power_core(expr * arg1, expr * arg2, expr_ref & res br_status arith_rewriter::mk_to_int_core(expr * arg, expr_ref & result) { numeral a; - expr* x; + expr* x = 0; if (m_util.is_numeral(arg, a)) { result = m_util.mk_numeral(floor(a), true); return BR_DONE; diff --git a/contrib/cmake/src/ast/rewriter/bit_blaster/CMakeLists.txt b/src/ast/rewriter/bit_blaster/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/rewriter/bit_blaster/CMakeLists.txt rename to src/ast/rewriter/bit_blaster/CMakeLists.txt diff --git a/src/ast/rewriter/pb_rewriter.cpp b/src/ast/rewriter/pb_rewriter.cpp index 7d1eebb5c..8f8e82c49 100644 --- a/src/ast/rewriter/pb_rewriter.cpp +++ b/src/ast/rewriter/pb_rewriter.cpp @@ -196,6 +196,7 @@ void pb_rewriter::dump_pb_rewrite(expr* fml) { } br_status pb_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { + if (m_util.is_aux_bool(f)) return BR_FAILED; ast_manager& m = result.get_manager(); rational sum(0), maxsum(0); for (unsigned i = 0; i < num_args; ++i) { diff --git a/contrib/cmake/src/ast/simplifier/CMakeLists.txt b/src/ast/simplifier/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/simplifier/CMakeLists.txt rename to src/ast/simplifier/CMakeLists.txt diff --git a/contrib/cmake/src/ast/substitution/CMakeLists.txt b/src/ast/substitution/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/substitution/CMakeLists.txt rename to src/ast/substitution/CMakeLists.txt diff --git a/src/ast/substitution/substitution.cpp b/src/ast/substitution/substitution.cpp index eea1938a6..f741d3fd4 100644 --- a/src/ast/substitution/substitution.cpp +++ b/src/ast/substitution/substitution.cpp @@ -85,7 +85,7 @@ void substitution::apply(unsigned num_actual_offsets, unsigned const * deltas, e m_state = APPLY; unsigned j; - expr * e; + expr * e = 0; unsigned off; expr_offset n1; bool visited; @@ -214,7 +214,7 @@ void substitution::apply(unsigned num_actual_offsets, unsigned const * deltas, e } } SASSERT(m_apply_cache.contains(n)); - m_apply_cache.find(n, e); + VERIFY(m_apply_cache.find(n, e)); m_new_exprs.push_back(e); result = e; diff --git a/contrib/cmake/src/cmd_context/CMakeLists.txt b/src/cmd_context/CMakeLists.txt similarity index 88% rename from contrib/cmake/src/cmd_context/CMakeLists.txt rename to src/cmd_context/CMakeLists.txt index 8b2d10eec..f7b888343 100644 --- a/contrib/cmake/src/cmd_context/CMakeLists.txt +++ b/src/cmd_context/CMakeLists.txt @@ -18,4 +18,6 @@ z3_add_component(cmd_context interp rewriter solver + EXTRA_REGISTER_MODULE_HEADERS + context_params.h ) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 9886cc100..ea6d1c232 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -39,7 +39,7 @@ class help_cmd : public cmd { ctx.regular_stream() << " (" << s; if (usage) ctx.regular_stream() << " " << escaped(usage, true) << ")\n"; - else + else ctx.regular_stream() << ")\n"; if (descr) { ctx.regular_stream() << " " << escaped(descr, true, 4) << "\n"; @@ -62,7 +62,7 @@ public: } m_cmds.push_back(s); } - + typedef std::pair named_cmd; struct named_cmd_lt { bool operator()(named_cmd const & c1, named_cmd const & c2) const { return c1.first.str() < c2.first.str(); } @@ -104,14 +104,14 @@ class get_model_cmd : public cmd { unsigned m_index; public: get_model_cmd(): cmd("get-model"), m_index(0) {} - virtual char const * get_usage() const { return "[]"; } - virtual char const * get_descr(cmd_context & ctx) const { - return "retrieve model for the last check-sat command.\nSupply optional index if retrieving a model corresponding to a box optimization objective"; + virtual char const * get_usage() const { return "[]"; } + virtual char const * get_descr(cmd_context & ctx) const { + return "retrieve model for the last check-sat command.\nSupply optional index if retrieving a model corresponding to a box optimization objective"; } - virtual unsigned get_arity() const { return VAR_ARITY; } + virtual unsigned get_arity() const { return VAR_ARITY; } virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_UINT; } - virtual void set_next_arg(cmd_context & ctx, unsigned index) { m_index = index; } - virtual void execute(cmd_context & ctx) { + virtual void set_next_arg(cmd_context & ctx, unsigned index) { m_index = index; } + virtual void execute(cmd_context & ctx) { if (!ctx.is_model_available() || ctx.get_check_sat_result() == 0) throw cmd_exception("model is not available"); model_ref m; @@ -122,7 +122,7 @@ public: ctx.get_check_sat_result()->get_model(m); } ctx.display_model(m); - } + } virtual void reset(cmd_context& ctx) { m_index = 0; } @@ -149,7 +149,14 @@ ATOMIC_CMD(get_assignment_cmd, "get-assignment", "retrieve assignment", { first = false; else ctx.regular_stream() << " "; - ctx.regular_stream() << "(" << name << " " << (ctx.m().is_true(val) ? "true" : "false") << ")"; + ctx.regular_stream() << "("; + if (is_smt2_quoted_symbol(name)) { + ctx.regular_stream() << mk_smt2_quoted_symbol(name); + } + else { + ctx.regular_stream() << name; + } + ctx.regular_stream() << " " << (ctx.m().is_true(val) ? "true" : "false") << ")"; } } } @@ -160,11 +167,11 @@ class cmd_is_declared : public ast_smt_pp::is_declared { cmd_context& m_ctx; public: cmd_is_declared(cmd_context& ctx): m_ctx(ctx) {} - - virtual bool operator()(func_decl* d) const { + + virtual bool operator()(func_decl* d) const { return m_ctx.is_func_decl(d->get_name()); } - virtual bool operator()(sort* s) const { + virtual bool operator()(sort* s) const { return m_ctx.is_sort_decl(s->get_name()); } }; @@ -182,13 +189,13 @@ ATOMIC_CMD(get_proof_cmd, "get-proof", "retrieve proof", { if (ctx.well_sorted_check_enabled() && !is_well_sorted(ctx.m(), pr)) { throw cmd_exception("proof is not well sorted"); } - + pp_params params; if (params.pretty_proof()) { ctx.regular_stream() << mk_pp(pr, ctx.m()) << std::endl; } else { - // TODO: reimplement a new SMT2 pretty printer + // TODO: reimplement a new SMT2 pretty printer ast_smt_pp pp(ctx.m()); cmd_is_declared isd(ctx); pp.set_is_declared(&isd); @@ -199,19 +206,19 @@ ATOMIC_CMD(get_proof_cmd, "get-proof", "retrieve proof", { }); static void print_core(cmd_context& ctx) { - ptr_vector core; - ctx.get_check_sat_result()->get_unsat_core(core); - ctx.regular_stream() << "("; - ptr_vector::const_iterator it = core.begin(); - ptr_vector::const_iterator end = core.end(); - for (bool first = true; it != end; ++it) { - if (first) - first = false; - else - ctx.regular_stream() << " "; - ctx.regular_stream() << mk_ismt2_pp(*it, ctx.m()); - } - ctx.regular_stream() << ")" << std::endl; + ptr_vector core; + ctx.get_check_sat_result()->get_unsat_core(core); + ctx.regular_stream() << "("; + ptr_vector::const_iterator it = core.begin(); + ptr_vector::const_iterator end = core.end(); + for (bool first = true; it != end; ++it) { + if (first) + first = false; + else + ctx.regular_stream() << " "; + ctx.regular_stream() << mk_ismt2_pp(*it, ctx.m()); + } + ctx.regular_stream() << ")" << std::endl; } ATOMIC_CMD(get_unsat_core_cmd, "get-unsat-core", "retrieve unsat core", { @@ -251,9 +258,9 @@ ATOMIC_CMD(get_assertions_cmd, "get-assertions", "retrieve asserted terms when i -ATOMIC_CMD(reset_assertions_cmd, "reset-assertions", "reset all asserted formulas (but retain definitions and declarations)", ctx.reset_assertions();); +ATOMIC_CMD(reset_assertions_cmd, "reset-assertions", "reset all asserted formulas (but retain definitions and declarations)", ctx.reset_assertions(); ctx.print_success();); -UNARY_CMD(set_logic_cmd, "set-logic", "", "set the background logic.", CPK_SYMBOL, symbol const &, +UNARY_CMD(set_logic_cmd, "set-logic", "", "set the background logic.", CPK_SYMBOL, symbol const &, if (ctx.set_logic(arg)) ctx.print_success(); else { @@ -262,12 +269,14 @@ UNARY_CMD(set_logic_cmd, "set-logic", "", "set the background logic.", C } ); -UNARY_CMD(pp_cmd, "display", "", "display the given term.", CPK_EXPR, expr *, { +UNARY_CMD(pp_cmd, "display", "", "display the given term.", CPK_EXPR, expr *, { ctx.display(ctx.regular_stream(), arg); - ctx.regular_stream() << std::endl; + ctx.regular_stream() << std::endl; }); -UNARY_CMD(echo_cmd, "echo", "", "display the given string", CPK_STRING, char const *, ctx.regular_stream() << "\"" << arg << "\"" << std::endl;); +UNARY_CMD(echo_cmd, "echo", "", "display the given string", CPK_STRING, char const *, + bool smt2c = ctx.params().m_smtlib2_compliant; + ctx.regular_stream() << (smt2c ? "\"" : "") << arg << (smt2c ? "\"" : "") << std::endl;); class set_get_option_cmd : public cmd { @@ -298,18 +307,18 @@ protected: symbol m_reproducible_resource_limit; bool is_builtin_option(symbol const & s) const { - return - s == m_print_success || s == m_print_warning || s == m_expand_definitions || + return + s == m_print_success || s == m_print_warning || s == m_expand_definitions || s == m_interactive_mode || s == m_produce_proofs || s == m_produce_unsat_cores || s == m_produce_unsat_assumptions || s == m_produce_models || s == m_produce_assignments || s == m_produce_interpolants || - s == m_regular_output_channel || s == m_diagnostic_output_channel || + s == m_regular_output_channel || s == m_diagnostic_output_channel || s == m_random_seed || s == m_verbosity || s == m_global_decls || s == m_global_declarations || s == m_produce_assertions || s == m_reproducible_resource_limit; } public: set_get_option_cmd(char const * name): - cmd(name), + cmd(name), m_true("true"), m_false("false"), m_print_success(":print-success"), @@ -341,7 +350,7 @@ public: class set_option_cmd : public set_get_option_cmd { bool m_unsupported; symbol m_option; - + bool to_bool(symbol const & value) const { if (value != m_true && value != m_false) throw cmd_exception("invalid option value, true/false expected"); @@ -362,7 +371,7 @@ class set_option_cmd : public set_get_option_cmd { throw cmd_exception(msg); } } - + void set_param(cmd_context & ctx, char const * value) { try { gparams::set(m_option, value); @@ -459,11 +468,11 @@ public: virtual void prepare(cmd_context & ctx) { m_unsupported = false; m_option = symbol::null; } - virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return m_option == symbol::null ? CPK_KEYWORD : CPK_OPTION_VALUE; } - virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { + virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { if (m_option == symbol::null) { m_option = opt; } @@ -518,7 +527,7 @@ class get_option_cmd : public set_get_option_cmd { static void print_bool(cmd_context & ctx, bool b) { ctx.regular_stream() << (b ? "true" : "false") << std::endl; } - + static void print_unsigned(cmd_context & ctx, unsigned v) { ctx.regular_stream() << v << std::endl; } @@ -535,11 +544,11 @@ public: virtual char const * get_descr(cmd_context & ctx) const { return "get configuration option."; } virtual unsigned get_arity() const { return 1; } virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_KEYWORD; } - virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { + virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { if (opt == m_print_success) { - print_bool(ctx, ctx.print_success_enabled()); + print_bool(ctx, ctx.print_success_enabled()); } - // TODO: + // TODO: // else if (opt == m_print_warning) { // print_bool(ctx, ); // } @@ -629,7 +638,7 @@ public: virtual char const * get_descr(cmd_context & ctx) const { return "get information."; } virtual unsigned get_arity() const { return 1; } virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_KEYWORD; } - virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { + virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { if (opt == m_error_behavior) { if (ctx.exit_on_error()) ctx.regular_stream() << "(:error-behavior immediate-exit)" << std::endl; @@ -685,12 +694,12 @@ public: virtual char const * get_descr(cmd_context & ctx) const { return "set information."; } virtual unsigned get_arity() const { return 2; } virtual void prepare(cmd_context & ctx) { m_info = symbol::null; } - virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { - return m_info == symbol::null ? CPK_KEYWORD : CPK_OPTION_VALUE; + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { + return m_info == symbol::null ? CPK_KEYWORD : CPK_OPTION_VALUE; } virtual void set_next_arg(cmd_context & ctx, rational const & val) {} virtual void set_next_arg(cmd_context & ctx, char const * val) {} - virtual void set_next_arg(cmd_context & ctx, symbol const & s) { + virtual void set_next_arg(cmd_context & ctx, symbol const & s) { if (m_info == symbol::null) { m_info = s; } @@ -738,7 +747,7 @@ public: virtual char const * get_descr(cmd_context & ctx) const { return "declare a new array map operator with name using the given function declaration.\n ::= \n | ( (*) )\n | ((_ +) (*) )\nThe last two cases are used to disumbiguate between declarations with the same name and/or select (indexed) builtin declarations.\nFor more details about the the array map operator, see 'Generalized and Efficient Array Decision Procedures' (FMCAD 2009).\nExample: (declare-map set-union (Int) (or (Bool Bool) Bool))\nDeclares a new function (declare-fun set-union ((Array Int Bool) (Array Int Bool)) (Array Int Bool)).\nThe instance of the map axiom for this new declaration is:\n(forall ((a1 (Array Int Bool)) (a2 (Array Int Bool)) (i Int)) (= (select (set-union a1 a2) i) (or (select a1 i) (select a2 i))))"; } virtual unsigned get_arity() const { return 3; } virtual void prepare(cmd_context & ctx) { m_name = symbol::null; m_domain.reset(); } - virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { if (m_name == symbol::null) return CPK_SYMBOL; if (m_domain.empty()) return CPK_SORT_LIST; return CPK_FUNC_DECL; @@ -749,10 +758,10 @@ public: throw cmd_exception("invalid map declaration, empty sort list"); m_domain.append(num, slist); } - virtual void set_next_arg(cmd_context & ctx, func_decl * f) { - m_f = f; - if (m_f->get_arity() == 0) - throw cmd_exception("invalid map declaration, function declaration must have arity > 0"); + virtual void set_next_arg(cmd_context & ctx, func_decl * f) { + m_f = f; + if (m_f->get_arity() == 0) + throw cmd_exception("invalid map declaration, function declaration must have arity > 0"); } virtual void reset(cmd_context & ctx) { m_array_fid = null_family_id; @@ -791,7 +800,7 @@ public: virtual char const * get_descr(cmd_context & ctx) const { return "retrieve consequences that fix values for supplied variables"; } virtual unsigned get_arity() const { return 2; } virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_EXPR_LIST; } - virtual void set_next_arg(cmd_context & ctx, unsigned num, expr * const * tlist) { + virtual void set_next_arg(cmd_context & ctx, unsigned num, expr * const * tlist) { if (m_count == 0) { m_assumptions.append(num, tlist); ++m_count; @@ -851,7 +860,7 @@ void install_basic_cmds(cmd_context & ctx) { ctx.insert(alloc(builtin_cmd, "declare-fun", " (*) ", "declare a new function/constant.")); ctx.insert(alloc(builtin_cmd, "declare-const", " ", "declare a new constant.")); ctx.insert(alloc(builtin_cmd, "declare-datatypes", "(*) (+)", "declare mutually recursive datatypes.\n ::= ( +)\n ::= ( *)\n ::= ( )\nexample: (declare-datatypes (T) ((BinTree (leaf (value T)) (node (left BinTree) (right BinTree)))))")); - ctx.insert(alloc(builtin_cmd, "check-sat-asuming", "( hprop_literali* )", "check sat assuming a collection of literals")); + ctx.insert(alloc(builtin_cmd, "check-sat-assuming", "( hprop_literali* )", "check sat assuming a collection of literals")); ctx.insert(alloc(get_unsat_assumptions_cmd)); ctx.insert(alloc(reset_assertions_cmd)); diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index d4273d42d..45ad08a78 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -15,6 +15,7 @@ Author: Notes: --*/ + #include #include"tptr.h" #include"cmd_context.h" @@ -71,14 +72,22 @@ void func_decls::finalize(ast_manager & m) { m_decls = 0; } +bool func_decls::signatures_collide(func_decl* f, func_decl* g) const { + return f == g; +} + bool func_decls::contains(func_decl * f) const { if (GET_TAG(m_decls) == 0) { - return UNTAG(func_decl*, m_decls) == f; + func_decl* g = UNTAG(func_decl*, m_decls); + return g && signatures_collide(f, g); } else { func_decl_set * fs = UNTAG(func_decl_set *, m_decls); - return fs->contains(f); + for (func_decl* g : *fs) { + if (signatures_collide(f, g)) return true; + } } + return false; } bool func_decls::insert(ast_manager & m, func_decl * f) { @@ -249,6 +258,7 @@ protected: array_util m_arutil; fpa_util m_futil; seq_util m_sutil; + datatype_util m_dtutil; datalog::dl_decl_util m_dlutil; @@ -270,7 +280,7 @@ protected: } public: - pp_env(cmd_context & o):m_owner(o), m_autil(o.m()), m_bvutil(o.m()), m_arutil(o.m()), m_futil(o.m()), m_sutil(o.m()), m_dlutil(o.m()) {} + pp_env(cmd_context & o):m_owner(o), m_autil(o.m()), m_bvutil(o.m()), m_arutil(o.m()), m_futil(o.m()), m_sutil(o.m()), m_dtutil(o.m()), m_dlutil(o.m()) {} virtual ~pp_env() {} virtual ast_manager & get_manager() const { return m_owner.m(); } virtual arith_util & get_autil() { return m_autil; } @@ -278,6 +288,7 @@ public: virtual array_util & get_arutil() { return m_arutil; } virtual fpa_util & get_futil() { return m_futil; } virtual seq_util & get_sutil() { return m_sutil; } + virtual datatype_util & get_dtutil() { return m_dtutil; } virtual datalog::dl_decl_util& get_dlutil() { return m_dlutil; } virtual bool uses(symbol const & s) const { @@ -325,8 +336,8 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l): m_status(UNKNOWN), m_numeral_as_real(false), m_ignore_check(false), - m_exit_on_error(false), m_processing_pareto(false), + m_exit_on_error(false), m_manager(m), m_own_manager(m == 0), m_manager_initialized(false), @@ -1209,6 +1220,7 @@ void cmd_context::push() { scope & s = m_scopes.back(); s.m_func_decls_stack_lim = m_func_decls_stack.size(); s.m_psort_decls_stack_lim = m_psort_decls_stack.size(); + s.m_psort_inst_stack_lim = m_psort_inst_stack.size(); s.m_macros_stack_lim = m_macros_stack.size(); s.m_aux_pdecls_lim = m_aux_pdecls.size(); s.m_assertions_lim = m_assertions.size(); @@ -1223,7 +1235,7 @@ void cmd_context::push(unsigned n) { push(); } -void cmd_context::restore_func_decls(unsigned old_sz) { +void cmd_context::restore_func_decls(unsigned old_sz) { SASSERT(old_sz <= m_func_decls_stack.size()); svector::iterator it = m_func_decls_stack.begin() + old_sz; svector::iterator end = m_func_decls_stack.end(); @@ -1234,6 +1246,14 @@ void cmd_context::restore_func_decls(unsigned old_sz) { m_func_decls_stack.resize(old_sz); } +void cmd_context::restore_psort_inst(unsigned old_sz) { + for (unsigned i = old_sz; i < m_psort_inst_stack.size(); ++i) { + pdecl * s = m_psort_inst_stack[i]; + s->reset_cache(*m_pmanager); + } + m_psort_inst_stack.resize(old_sz); +} + void cmd_context::restore_psort_decls(unsigned old_sz) { SASSERT(old_sz <= m_psort_decls_stack.size()); svector::iterator it = m_psort_decls_stack.begin() + old_sz; @@ -1241,9 +1261,7 @@ void cmd_context::restore_psort_decls(unsigned old_sz) { for (; it != end; ++it) { symbol const & s = *it; psort_decl * d = 0; - if (!m_psort_decls.find(s, d)) { - UNREACHABLE(); - } + VERIFY(m_psort_decls.find(s, d)); pm().dec_ref(d); m_psort_decls.erase(s); } @@ -1257,9 +1275,7 @@ void cmd_context::restore_macros(unsigned old_sz) { for (; it != end; ++it) { symbol const & s = *it; macro _m; - if (!m_macros.find(s, _m)) { - UNREACHABLE(); - } + VERIFY (m_macros.find(s, _m)); m().dec_ref(_m.second); m_macros.erase(s); } @@ -1322,7 +1338,9 @@ void cmd_context::pop(unsigned n) { restore_macros(s.m_macros_stack_lim); restore_aux_pdecls(s.m_aux_pdecls_lim); restore_assertions(s.m_assertions_lim); + restore_psort_inst(s.m_psort_inst_stack_lim); m_scopes.shrink(new_lvl); + } void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions) { @@ -1359,7 +1377,6 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions throw ex; } catch (z3_exception & ex) { - get_opt()->display_assignment(regular_stream()); throw cmd_exception(ex.msg()); } if (m_processing_pareto && r != l_true) { @@ -1397,7 +1414,7 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions } validate_check_sat_result(r); if (was_opt && r != l_false && !m_processing_pareto) { - get_opt()->display_assignment(regular_stream()); + // get_opt()->display_assignment(regular_stream()); } if (r == l_true && m_params.m_dump_models) { @@ -1802,7 +1819,7 @@ cmd_context::dt_eh::dt_eh(cmd_context & owner): cmd_context::dt_eh::~dt_eh() { } -void cmd_context::dt_eh::operator()(sort * dt) { +void cmd_context::dt_eh::operator()(sort * dt, pdecl* pd) { TRACE("new_dt_eh", tout << "new datatype: "; m_owner.pm().display(tout, dt); tout << "\n";); ptr_vector const * constructors = m_dt_util.get_datatype_constructors(dt); unsigned num_constructors = constructors->size(); @@ -1821,8 +1838,13 @@ void cmd_context::dt_eh::operator()(sort * dt) { TRACE("new_dt_eh", tout << "new accessor: " << a->get_name() << "\n";); } } + if (m_owner.m_scopes.size() > 0) { + m_owner.m_psort_inst_stack.push_back(pd); + + } } + std::ostream & operator<<(std::ostream & out, cmd_context::status st) { switch (st) { case cmd_context::UNSAT: out << "unsat"; break; diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index ed92ab909..171d59a21 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -42,6 +42,7 @@ Notes: class func_decls { func_decl * m_decls; + bool signatures_collide(func_decl* f, func_decl* g) const; public: func_decls():m_decls(0) {} func_decls(ast_manager & m, func_decl * f); @@ -159,7 +160,7 @@ protected: bool m_produce_assignments; status m_status; bool m_numeral_as_real; - bool m_ignore_check; // used by the API to disable check-sat() commands when parsing SMT 2.0 files. + bool m_ignore_check; // used by the API to disable check-sat() commands when parsing SMT 2.0 files. bool m_processing_pareto; // used when re-entering check-sat for pareto front. bool m_exit_on_error; @@ -189,6 +190,8 @@ protected: svector m_func_decls_stack; svector m_psort_decls_stack; svector m_macros_stack; + ptr_vector m_psort_inst_stack; + // ptr_vector m_aux_pdecls; ptr_vector m_assertions; @@ -200,6 +203,7 @@ protected: unsigned m_psort_decls_stack_lim; unsigned m_macros_stack_lim; unsigned m_aux_pdecls_lim; + unsigned m_psort_inst_stack_lim; // only m_assertions_lim is relevant when m_global_decls = true unsigned m_assertions_lim; }; @@ -219,7 +223,7 @@ protected: public: dt_eh(cmd_context & owner); virtual ~dt_eh(); - virtual void operator()(sort * dt); + virtual void operator()(sort * dt, pdecl* pd); }; friend class dt_eh; @@ -245,6 +249,7 @@ protected: void restore_macros(unsigned old_sz); void restore_aux_pdecls(unsigned old_sz); void restore_assertions(unsigned old_sz); + void restore_psort_inst(unsigned old_sz); void erase_func_decl_core(symbol const & s, func_decl * f); void erase_psort_decl_core(symbol const & s); diff --git a/contrib/cmake/src/cmd_context/extra_cmds/CMakeLists.txt b/src/cmd_context/extra_cmds/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/cmd_context/extra_cmds/CMakeLists.txt rename to src/cmd_context/extra_cmds/CMakeLists.txt diff --git a/src/cmd_context/interpolant_cmds.cpp b/src/cmd_context/interpolant_cmds.cpp index 53da91d1e..2bfdd9848 100644 --- a/src/cmd_context/interpolant_cmds.cpp +++ b/src/cmd_context/interpolant_cmds.cpp @@ -46,20 +46,14 @@ static void show_interpolant_and_maybe_check(cmd_context & ctx, m_params.set_bool("flat", true); th_rewriter s(ctx.m(), m_params); + ctx.regular_stream() << "(interpolants"; for(unsigned i = 0; i < interps.size(); i++){ - expr_ref r(ctx.m()); proof_ref pr(ctx.m()); s(to_expr(interps[i]),r,pr); - - ctx.regular_stream() << mk_pp(r.get(), ctx.m()) << std::endl; -#if 0 - ast_smt_pp pp(ctx.m()); - pp.set_logic(ctx.get_logic().str().c_str()); - pp.display_smt2(ctx.regular_stream(), to_expr(interps[i])); - ctx.regular_stream() << std::endl; -#endif + ctx.regular_stream() << "\n " << r; } + ctx.regular_stream() << ")\n"; s.cleanup(); diff --git a/src/cmd_context/pdecl.cpp b/src/cmd_context/pdecl.cpp index 08a29e381..bd2ef849a 100644 --- a/src/cmd_context/pdecl.cpp +++ b/src/cmd_context/pdecl.cpp @@ -123,6 +123,10 @@ sort * psort::find(sort * const * s) const { } void psort::finalize(pdecl_manager & m) { + reset_cache(m); +} + +void psort::reset_cache(pdecl_manager& m) { m.del_inst_cache(m_inst_cache); m_inst_cache = 0; } @@ -171,10 +175,11 @@ public: if (other->hcons_kind() != hcons_kind()) return false; return get_num_params() == other->get_num_params() && m_idx == static_cast(other)->m_idx; - } + } virtual void display(std::ostream & out) const { out << "s_" << m_idx; } + unsigned idx() const { return m_idx; } }; class psort_app : public psort { @@ -268,6 +273,10 @@ psort_decl::psort_decl(unsigned id, unsigned num_params, pdecl_manager & m, symb } void psort_decl::finalize(pdecl_manager & m) { + reset_cache(m); +} + +void psort_decl::reset_cache(pdecl_manager& m) { m.del_inst_cache(m_inst_cache); m_inst_cache = 0; } @@ -284,6 +293,27 @@ sort * psort_decl::find(sort * const * s) { return m_inst_cache->find(s); } +#if 0 +psort_dt_decl::psort_dt_decl(unsigned id, unsigned num_params, pdecl_manager& m, symbol const& n): + psort_decl(id, num_params, m, n) { +} + +void psort_dt_decl::finalize(pdecl_manager& m) { + psort_decl::finalize(m); +} + + +sort * psort_dt_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * s) { + UNREACHABLE(); + return 0; +} + +void psort_dt_decl::display(std::ostream & out) const { + out << get_name() << " " << get_num_params(); +} +#endif + + psort_user_decl::psort_user_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n, psort * p): psort_decl(id, num_params, m, n), m_def(p) { @@ -389,13 +419,15 @@ paccessor_decl::paccessor_decl(unsigned id, unsigned num_params, pdecl_manager & pdecl(id, num_params), m_name(n), m_type(r) { - if (m_type.kind() == PTR_PSORT) + if (m_type.kind() == PTR_PSORT) { m.inc_ref(r.get_psort()); + } } void paccessor_decl::finalize(pdecl_manager & m) { - if (m_type.kind() == PTR_PSORT) - m.lazy_dec_ref(m_type.get_psort()); + if (m_type.kind() == PTR_PSORT) { + m.lazy_dec_ref(m_type.get_psort()); + } } bool paccessor_decl::has_missing_refs(symbol & missing) const { @@ -576,13 +608,13 @@ sort * pdatatype_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * dts.m_buffer.push_back(instantiate_decl(m, s)); datatype_decl * d_ptr = dts.m_buffer[0]; sort_ref_vector sorts(m.m()); - bool is_ok = m.get_dt_plugin()->mk_datatypes(1, &d_ptr, sorts); + bool is_ok = m.get_dt_plugin()->mk_datatypes(1, &d_ptr, m_num_params, s, sorts); TRACE("pdatatype_decl", tout << "instantiating " << m_name << " is_ok: " << is_ok << "\n";); if (is_ok) { r = sorts.get(0); cache(m, s, r); m.save_info(r, this, n, s); - m.notify_new_dt(r); + m.notify_new_dt(r, this); return r; } } @@ -651,7 +683,7 @@ bool pdatatypes_decl::instantiate(pdecl_manager & m, sort * const * s) { dts.m_buffer.push_back((*it)->instantiate_decl(m, s)); } sort_ref_vector sorts(m.m()); - bool is_ok = m.get_dt_plugin()->mk_datatypes(dts.m_buffer.size(), dts.m_buffer.c_ptr(), sorts); + bool is_ok = m.get_dt_plugin()->mk_datatypes(dts.m_buffer.size(), dts.m_buffer.c_ptr(), m_num_params, s, sorts); if (!is_ok) return false; it = m_datatypes.begin(); @@ -659,7 +691,7 @@ bool pdatatypes_decl::instantiate(pdecl_manager & m, sort * const * s) { sort * new_dt = sorts.get(i); (*it)->cache(m, s, new_dt); m.save_info(new_dt, *it, m_num_params, s); - m.notify_new_dt(new_dt); + m.notify_new_dt(new_dt, *it); } return true; } @@ -853,6 +885,11 @@ psort_decl * pdecl_manager::mk_psort_user_decl(unsigned num_params, symbol const return new (a().allocate(sizeof(psort_user_decl))) psort_user_decl(m_id_gen.mk(), num_params, *this, n, def); } + +//psort_decl * pdecl_manager::mk_psort_dt_decl(unsigned num_params, symbol const & n) { +// return new (a().allocate(sizeof(psort_dt_decl))) psort_dt_decl(m_id_gen.mk(), num_params, *this, n); +//} + psort_decl * pdecl_manager::mk_psort_builtin_decl(symbol const & n, family_id fid, decl_kind k) { return new (a().allocate(sizeof(psort_builtin_decl))) psort_builtin_decl(m_id_gen.mk(), *this, n, fid, k); } @@ -862,6 +899,7 @@ sort * pdecl_manager::instantiate(psort * p, unsigned num, sort * const * args) return p->instantiate(*this, args); } + void pdecl_manager::del_decl_core(pdecl * p) { TRACE("pdecl_manager", tout << "del_decl_core:\n"; diff --git a/src/cmd_context/pdecl.h b/src/cmd_context/pdecl.h index f03d1b901..31005fe0d 100644 --- a/src/cmd_context/pdecl.h +++ b/src/cmd_context/pdecl.h @@ -46,6 +46,7 @@ public: unsigned get_ref_count() const { return m_ref_count; } unsigned hash() const { return m_id; } virtual void display(std::ostream & out) const {} + virtual void reset_cache(pdecl_manager& m) {} }; class psort_inst_cache; @@ -75,6 +76,7 @@ public: virtual char const * hcons_kind() const = 0; virtual unsigned hcons_hash() const = 0; virtual bool hcons_eq(psort const * other) const = 0; + virtual void reset_cache(pdecl_manager& m); }; // for hash consing @@ -102,6 +104,7 @@ public: // Only builtin declarations can have a variable number of parameters. bool has_var_params() const { return m_num_params == PSORT_DECL_VAR_PARAMS; } symbol const & get_name() const { return m_name; } + virtual void reset_cache(pdecl_manager& m); }; class psort_user_decl : public psort_decl { @@ -131,6 +134,20 @@ public: virtual void display(std::ostream & out) const; }; +#if 0 +class psort_dt_decl : public psort_decl { +protected: + friend class pdecl_manager; + psort_dt_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n); + virtual size_t obj_size() const { return sizeof(psort_dt_decl); } + virtual void finalize(pdecl_manager & m); + virtual ~psort_dt_decl() {} +public: + virtual sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s); + virtual void display(std::ostream & out) const; +}; +#endif + class datatype_decl_plugin; class datatype_decl; class constructor_decl; @@ -246,7 +263,7 @@ public: class new_datatype_eh { public: virtual ~new_datatype_eh() {} - virtual void operator()(sort * dt) = 0; + virtual void operator()(sort * dt, pdecl* pd) = 0; }; class pdecl_manager { @@ -279,10 +296,11 @@ public: small_object_allocator & a() const { return m_allocator; } family_id get_datatype_fid() const { return m_datatype_fid; } void set_new_datatype_eh(new_datatype_eh * eh) { m_new_dt_eh = eh; } - psort * mk_psort_cnst(sort * s); + psort * mk_psort_cnst(sort * s); psort * mk_psort_var(unsigned num_params, unsigned vidx); psort * mk_psort_app(unsigned num_params, psort_decl * d, unsigned num_args, psort * const * args); psort * mk_psort_app(psort_decl * d); + // psort_decl * mk_psort_dt_decl(unsigned num_params, symbol const & n); psort_decl * mk_psort_user_decl(unsigned num_params, symbol const & n, psort * def); psort_decl * mk_psort_builtin_decl(symbol const & n, family_id fid, decl_kind k); paccessor_decl * mk_paccessor_decl(unsigned num_params, symbol const & s, ptype const & p); @@ -304,7 +322,7 @@ public: void dec_ref(unsigned num, T * const * ps) { lazy_dec_ref(num, ps); del_decls(); } psort_inst_cache * mk_inst_cache(unsigned num_params); void del_inst_cache(psort_inst_cache * c); - void notify_new_dt(sort * dt) { if (m_new_dt_eh) (*m_new_dt_eh)(dt); } + void notify_new_dt(sort * dt, pdecl* pd) { if (m_new_dt_eh) (*m_new_dt_eh)(dt, pd); } datatype_decl_plugin * get_dt_plugin() const; void save_info(sort * s, psort_decl * d, unsigned num_args, sort * const * args); diff --git a/src/cmd_context/tactic_cmds.cpp b/src/cmd_context/tactic_cmds.cpp index 2b60486f7..119deec8c 100644 --- a/src/cmd_context/tactic_cmds.cpp +++ b/src/cmd_context/tactic_cmds.cpp @@ -308,6 +308,9 @@ public: } virtual void execute(cmd_context & ctx) { + if (!m_tactic) { + throw cmd_exception("apply needs a tactic argument"); + } params_ref p = ctx.params().merge_default_params(ps()); tactic_ref tref = using_params(sexpr2tactic(ctx, m_tactic), p); { diff --git a/contrib/cmake/src/duality/CMakeLists.txt b/src/duality/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/duality/CMakeLists.txt rename to src/duality/CMakeLists.txt diff --git a/contrib/cmake/src/interp/CMakeLists.txt b/src/interp/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/interp/CMakeLists.txt rename to src/interp/CMakeLists.txt diff --git a/contrib/cmake/src/math/automata/CMakeLists.txt b/src/math/automata/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/automata/CMakeLists.txt rename to src/math/automata/CMakeLists.txt diff --git a/contrib/cmake/src/math/euclid/CMakeLists.txt b/src/math/euclid/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/euclid/CMakeLists.txt rename to src/math/euclid/CMakeLists.txt diff --git a/contrib/cmake/src/math/grobner/CMakeLists.txt b/src/math/grobner/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/grobner/CMakeLists.txt rename to src/math/grobner/CMakeLists.txt diff --git a/contrib/cmake/src/math/hilbert/CMakeLists.txt b/src/math/hilbert/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/hilbert/CMakeLists.txt rename to src/math/hilbert/CMakeLists.txt diff --git a/contrib/cmake/src/math/interval/CMakeLists.txt b/src/math/interval/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/interval/CMakeLists.txt rename to src/math/interval/CMakeLists.txt diff --git a/contrib/cmake/src/math/polynomial/CMakeLists.txt b/src/math/polynomial/CMakeLists.txt similarity index 85% rename from contrib/cmake/src/math/polynomial/CMakeLists.txt rename to src/math/polynomial/CMakeLists.txt index 1d320d751..8c7d9ec02 100644 --- a/contrib/cmake/src/math/polynomial/CMakeLists.txt +++ b/src/math/polynomial/CMakeLists.txt @@ -11,5 +11,7 @@ z3_add_component(polynomial util PYG_FILES algebraic_params.pyg + EXTRA_REGISTER_MODULE_HEADERS + polynomial.h ) diff --git a/contrib/cmake/src/math/realclosure/CMakeLists.txt b/src/math/realclosure/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/realclosure/CMakeLists.txt rename to src/math/realclosure/CMakeLists.txt diff --git a/contrib/cmake/src/math/simplex/CMakeLists.txt b/src/math/simplex/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/simplex/CMakeLists.txt rename to src/math/simplex/CMakeLists.txt diff --git a/src/math/simplex/model_based_opt.cpp b/src/math/simplex/model_based_opt.cpp index c31eabb62..f12918bfe 100644 --- a/src/math/simplex/model_based_opt.cpp +++ b/src/math/simplex/model_based_opt.cpp @@ -18,8 +18,9 @@ Revision History: --*/ -#include "model_based_opt.h" -#include "uint_set.h" +#include "math/simplex/model_based_opt.h" +#include "util/uint_set.h" +#include "util/z3_exception.h" std::ostream& operator<<(std::ostream& out, opt::ineq_type ie) { switch (ie) { @@ -868,6 +869,9 @@ namespace opt { for (unsigned i = 0; i < mod_rows.size(); ++i) { D = lcm(D, m_rows[mod_rows[i]].m_mod); } + if (D.is_zero()) { + throw default_exception("modulo 0 is not defined"); + } TRACE("opt", display(tout << "lcm: " << D << " tableau\n");); rational val_x = m_var2value[x]; rational u = mod(val_x, D); @@ -954,7 +958,8 @@ namespace opt { row& r1 = m_rows[row_id1]; vector coeffs; mk_coeffs_without(coeffs, r1.m_vars, x); - add_divides(coeffs, r1.m_coeff, abs(a)); + rational c = r1.m_coeff; + add_divides(coeffs, c, abs(a)); } unsigned_vector const& row_ids = m_var2row_ids[x]; uint_set visited; diff --git a/contrib/cmake/src/math/subpaving/CMakeLists.txt b/src/math/subpaving/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/subpaving/CMakeLists.txt rename to src/math/subpaving/CMakeLists.txt diff --git a/contrib/cmake/src/math/subpaving/tactic/CMakeLists.txt b/src/math/subpaving/tactic/CMakeLists.txt similarity index 78% rename from contrib/cmake/src/math/subpaving/tactic/CMakeLists.txt rename to src/math/subpaving/tactic/CMakeLists.txt index eedb0ed4d..8873a1021 100644 --- a/contrib/cmake/src/math/subpaving/tactic/CMakeLists.txt +++ b/src/math/subpaving/tactic/CMakeLists.txt @@ -5,4 +5,6 @@ z3_add_component(subpaving_tactic COMPONENT_DEPENDENCIES core_tactics subpaving + TACTIC_HEADERS + subpaving_tactic.h ) diff --git a/contrib/cmake/src/model/CMakeLists.txt b/src/model/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/model/CMakeLists.txt rename to src/model/CMakeLists.txt diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index 61da4b3a0..805ed8e5d 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -125,7 +125,6 @@ struct evaluator_cfg : public default_rewriter_cfg { expr * val = m_model.get_const_interp(f); if (val != 0) { result = val; - expand_value(result); return BR_DONE; } @@ -202,8 +201,8 @@ struct evaluator_cfg : public default_rewriter_cfg { void expand_value(expr_ref& val) { vector stores; expr_ref else_case(m()); - bool args_are_unique; - if (m_ar.is_array(val) && extract_array_func_interp(val, stores, else_case, args_are_unique)) { + bool _unused; + if (m_ar.is_array(val) && extract_array_func_interp(val, stores, else_case, _unused)) { sort* srt = m().get_sort(val); val = m_ar.mk_const_array(srt, else_case); for (unsigned i = stores.size(); i > 0; ) { @@ -213,7 +212,7 @@ struct evaluator_cfg : public default_rewriter_cfg { args.append(stores[i].size(), stores[i].c_ptr()); val = m_ar.mk_store(args.size(), args.c_ptr()); } - } + } } bool get_macro(func_decl * f, expr * & def, quantifier * & q, proof * & def_pr) { @@ -274,7 +273,6 @@ struct evaluator_cfg : public default_rewriter_cfg { return BR_FAILED; } - // disabled until made more efficient vector stores1, stores2; bool args_are_unique1, args_are_unique2; expr_ref else1(m()), else2(m()); @@ -291,13 +289,13 @@ struct evaluator_cfg : public default_rewriter_cfg { else { conj.push_back(m().mk_eq(else1, else2)); } - args1.push_back(a); - args2.push_back(b); if (args_are_unique1 && args_are_unique2 && !stores1.empty()) { - return mk_array_eq(stores1, else1, stores2, else2, conj, result); + return mk_array_eq_core(stores1, else1, stores2, else2, conj, result); } // TBD: this is too inefficient. + args1.push_back(a); + args2.push_back(b); stores1.append(stores2); for (unsigned i = 0; i < stores1.size(); ++i) { args1.resize(1); args1.append(stores1[i].size() - 1, stores1[i].c_ptr()); @@ -338,20 +336,22 @@ struct evaluator_cfg : public default_rewriter_cfg { typedef hashtable args_table; - br_status mk_array_eq(vector const& stores1, expr* else1, - vector const& stores2, expr* else2, - expr_ref_vector& conj, expr_ref& result) { + br_status mk_array_eq_core(vector const& stores1, expr* else1, + vector const& stores2, expr* else2, + expr_ref_vector& conj, expr_ref& result) { unsigned arity = stores1[0].size()-1; // TBD: fix arity. args_hash ah(arity); args_eq ae(arity); args_table table1(DEFAULT_HASHTABLE_INITIAL_CAPACITY, ah, ae); args_table table2(DEFAULT_HASHTABLE_INITIAL_CAPACITY, ah, ae); - for (unsigned i = 0; i < stores1.size(); ++i) { - table1.insert(stores1[i].c_ptr()); - } - for (unsigned i = stores2.size(); i > 0; ) { + // stores with smaller index take precedence + for (unsigned i = stores1.size(); i > 0; ) { --i; + table1.insert(stores1[i].c_ptr()); + } + + for (unsigned i = 0, sz = stores2.size(); i < sz; ++i) { if (table2.contains(stores2[i].c_ptr())) { // first insertion takes precedence. continue; @@ -361,7 +361,7 @@ struct evaluator_cfg : public default_rewriter_cfg { expr* val = stores2[i][arity]; if (table1.find(stores2[i].c_ptr(), args)) { switch (compare(args[arity], val)) { - case l_true: table1.remove(stores2[i].c_ptr()); break; + case l_true: table1.remove(args); break; case l_false: result = m().mk_false(); return BR_DONE; default: conj.push_back(m().mk_eq(val, args[arity])); break; } @@ -389,10 +389,10 @@ struct evaluator_cfg : public default_rewriter_cfg { lbool compare(expr* a, expr* b) { if (m().are_equal(a, b)) return l_true; if (m().are_distinct(a, b)) return l_false; - return l_undef; + return l_undef; } - + bool args_are_values(expr_ref_vector const& store, bool& are_unique) { bool are_values = true; for (unsigned j = 0; are_values && j + 1 < store.size(); ++j) { @@ -402,7 +402,7 @@ struct evaluator_cfg : public default_rewriter_cfg { SASSERT(!are_unique || are_values); return are_values; } - + bool extract_array_func_interp(expr* a, vector& stores, expr_ref& else_case, bool& are_unique) { SASSERT(m_ar.is_array(a)); @@ -417,14 +417,14 @@ struct evaluator_cfg : public default_rewriter_cfg { stores.push_back(store); a = to_app(a)->get_arg(0); } - + if (m_ar.is_const(a)) { else_case = to_app(a)->get_arg(0); return true; } - + if (!m_ar.is_as_array(a)) { - TRACE("model_evaluator", tout << "no translation: " << mk_pp(a, m()) << "\n";); + TRACE("model_evaluator", tout << "no translation: " << mk_pp(a, m()) << "\n";); return false; } @@ -432,6 +432,7 @@ struct evaluator_cfg : public default_rewriter_cfg { func_interp* g = m_model.get_func_interp(f); unsigned sz = g->num_entries(); unsigned arity = f->get_arity(); + unsigned base_sz = stores.size(); for (unsigned i = 0; i < sz; ++i) { expr_ref_vector store(m()); func_entry const* fe = g->get_entry(i); @@ -444,7 +445,7 @@ struct evaluator_cfg : public default_rewriter_cfg { } } stores.push_back(store); - } + } else_case = g->get_else(); if (!else_case) { TRACE("model_evaluator", tout << "no else case " << mk_pp(a, m()) << "\n"; @@ -456,7 +457,7 @@ struct evaluator_cfg : public default_rewriter_cfg { TRACE("model_evaluator", tout << "non-ground else case " << mk_pp(a, m()) << "\n" << else_case << "\n";); return false; } - for (unsigned i = stores.size(); are_values && i > 0; ) { + for (unsigned i = stores.size(); are_values && i > base_sz; ) { --i; if (m().are_equal(else_case, stores[i].back())) { for (unsigned j = i + 1; j < stores.size(); ++j) { @@ -487,6 +488,10 @@ struct model_evaluator::imp : public rewriter_tpl { m_cfg(md.get_manager(), md, p) { set_cancel_check(false); } + + void expand_value (expr_ref &val) { + m_cfg.expand_value (val); + } }; model_evaluator::model_evaluator(model_core & md, params_ref const & p) { @@ -524,7 +529,7 @@ unsigned model_evaluator::get_num_steps() const { void model_evaluator::cleanup(params_ref const & p) { model_core & md = m_imp->cfg().m_model; dealloc(m_imp); - m_imp = alloc(imp, md, p); + m_imp = alloc(imp, md, p); } void model_evaluator::reset(params_ref const & p) { @@ -535,14 +540,12 @@ void model_evaluator::reset(params_ref const & p) { void model_evaluator::operator()(expr * t, expr_ref & result) { TRACE("model_evaluator", tout << mk_ismt2_pp(t, m()) << "\n";); m_imp->operator()(t, result); + m_imp->expand_value(result); } expr_ref model_evaluator::operator()(expr * t) { TRACE("model_evaluator", tout << mk_ismt2_pp(t, m()) << "\n";); expr_ref result(m()); - m_imp->operator()(t, result); + this->operator()(t, result); return result; } - - - diff --git a/contrib/cmake/src/muz/base/CMakeLists.txt b/src/muz/base/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/base/CMakeLists.txt rename to src/muz/base/CMakeLists.txt diff --git a/src/muz/base/dl_rule.cpp b/src/muz/base/dl_rule.cpp index ffb964f47..27d62538e 100644 --- a/src/muz/base/dl_rule.cpp +++ b/src/muz/base/dl_rule.cpp @@ -784,7 +784,7 @@ namespace datalog { SASSERT(tail.size()==tail_neg.size()); rule_ref old_r = r; - r = mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr()); + r = mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr(), old_r->name()); r->set_accounting_parent_object(m_ctx, old_r); } @@ -1003,6 +1003,7 @@ namespace datalog { void rule::display(context & ctx, std::ostream & out) const { ast_manager & m = ctx.get_manager(); + out << m_name.str () << ":\n"; //out << mk_pp(m_head, m); output_predicate(ctx, m_head, out); if (m_tail_size == 0) { diff --git a/src/muz/base/dl_rule.h b/src/muz/base/dl_rule.h index f7dc18b5e..856814531 100644 --- a/src/muz/base/dl_rule.h +++ b/src/muz/base/dl_rule.h @@ -298,7 +298,7 @@ namespace datalog { static unsigned get_obj_size(unsigned n) { return sizeof(rule) + n * sizeof(app *); } - rule() : m_ref_cnt(0) {} + rule() : m_ref_cnt(0), m_name(symbol::null) {} ~rule() {} void deallocate(ast_manager & m); @@ -355,7 +355,12 @@ namespace datalog { void display(context & ctx, std::ostream & out) const; - symbol const& name() const { return m_name; } + /** + \brief Return the name(s) associated with this rule. Plural for preprocessed (e.g. obtained by inlining) rules. + + This possibly returns a ";"-separated list of names. + */ + symbol const& name() const { return m_name; } ; unsigned hash() const; diff --git a/src/muz/base/dl_rule_set.cpp b/src/muz/base/dl_rule_set.cpp index e9b383b56..229db4d27 100644 --- a/src/muz/base/dl_rule_set.cpp +++ b/src/muz/base/dl_rule_set.cpp @@ -668,7 +668,7 @@ namespace datalog { T * el = it->m_key; item_set * out_edges = it->m_value; - unsigned el_comp; + unsigned el_comp = 0; VERIFY( m_component_nums.find(el, el_comp) ); item_set::iterator eit = out_edges->begin(); diff --git a/src/muz/base/rule_properties.cpp b/src/muz/base/rule_properties.cpp index 518e848c4..247519d63 100644 --- a/src/muz/base/rule_properties.cpp +++ b/src/muz/base/rule_properties.cpp @@ -51,7 +51,8 @@ void rule_properties::collect(rule_set const& rules) { for (unsigned i = 0; m_inf_sort.empty() && i < r->get_decl()->get_arity(); ++i) { sort* d = r->get_decl()->get_domain(i); sort_size sz = d->get_num_elements(); - if (!sz.is_finite()) { + if (!sz.is_finite() && !m_dl.is_rule_sort(d)) { + TRACE("dl", tout << "sort " << mk_pp(d, m) << " is not finite " << sz << "\n";); m_inf_sort.push_back(m_rule); } } diff --git a/contrib/cmake/src/muz/bmc/CMakeLists.txt b/src/muz/bmc/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/bmc/CMakeLists.txt rename to src/muz/bmc/CMakeLists.txt diff --git a/src/muz/bmc/dl_bmc_engine.cpp b/src/muz/bmc/dl_bmc_engine.cpp index a7df8db77..8cc5c4f60 100644 --- a/src/muz/bmc/dl_bmc_engine.cpp +++ b/src/muz/bmc/dl_bmc_engine.cpp @@ -979,7 +979,7 @@ namespace datalog { sort_ref_vector new_sorts(m); family_id dfid = m.mk_family_id("datatype"); datatype_decl_plugin* dtp = static_cast(m.get_plugin(dfid)); - VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts)); + VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), 0, 0, new_sorts)); it = b.m_rules.begin_grouped_rules(); for (unsigned i = 0; it != end; ++it, ++i) { @@ -1021,7 +1021,7 @@ namespace datalog { cnstrs.push_back(mk_constructor_decl(name, is_name, accs.size(), accs.c_ptr())); } dts.push_back(mk_datatype_decl(symbol("Path"), cnstrs.size(), cnstrs.c_ptr())); - VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts)); + VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), 0, 0, new_sorts)); m_path_sort = new_sorts[0].get(); } } diff --git a/contrib/cmake/src/muz/clp/CMakeLists.txt b/src/muz/clp/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/clp/CMakeLists.txt rename to src/muz/clp/CMakeLists.txt diff --git a/contrib/cmake/src/muz/dataflow/CMakeLists.txt b/src/muz/dataflow/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/dataflow/CMakeLists.txt rename to src/muz/dataflow/CMakeLists.txt diff --git a/contrib/cmake/src/muz/ddnf/CMakeLists.txt b/src/muz/ddnf/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/ddnf/CMakeLists.txt rename to src/muz/ddnf/CMakeLists.txt diff --git a/contrib/cmake/src/muz/duality/CMakeLists.txt b/src/muz/duality/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/duality/CMakeLists.txt rename to src/muz/duality/CMakeLists.txt diff --git a/contrib/cmake/src/muz/fp/CMakeLists.txt b/src/muz/fp/CMakeLists.txt similarity index 86% rename from contrib/cmake/src/muz/fp/CMakeLists.txt rename to src/muz/fp/CMakeLists.txt index 239c4df12..4a7c4d018 100644 --- a/contrib/cmake/src/muz/fp/CMakeLists.txt +++ b/src/muz/fp/CMakeLists.txt @@ -13,4 +13,6 @@ z3_add_component(fp pdr rel tab + TACTIC_HEADERS + horn_tactic.h ) diff --git a/src/muz/fp/dl_cmds.cpp b/src/muz/fp/dl_cmds.cpp index 49632b39c..a98143aed 100644 --- a/src/muz/fp/dl_cmds.cpp +++ b/src/muz/fp/dl_cmds.cpp @@ -374,12 +374,9 @@ class dl_declare_rel_cmd : public cmd { unsigned m_arg_idx; mutable unsigned m_query_arg_idx; symbol m_rel_name; - scoped_ptr m_domain; + ptr_vector m_domain; svector m_kinds; - void ensure_domain(cmd_context& ctx) { - if (!m_domain) m_domain = alloc(sort_ref_vector, ctx.m()); - } public: dl_declare_rel_cmd(dl_context * dl_ctx): @@ -395,7 +392,7 @@ public: ctx.m(); // ensure manager is initialized. m_arg_idx = 0; m_query_arg_idx = 0; - m_domain = 0; + m_domain.reset(); m_kinds.reset(); } virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { @@ -406,8 +403,8 @@ public: } } virtual void set_next_arg(cmd_context & ctx, unsigned num, sort * const * slist) { - ensure_domain(ctx); - m_domain->append(num, slist); + m_domain.reset(); + m_domain.append(num, slist); m_arg_idx++; } virtual void set_next_arg(cmd_context & ctx, symbol const & s) { @@ -424,14 +421,12 @@ public: if(m_arg_idx<2) { throw cmd_exception("at least 2 arguments expected"); } - ensure_domain(ctx); ast_manager& m = ctx.m(); func_decl_ref pred( - m.mk_func_decl(m_rel_name, m_domain->size(), m_domain->c_ptr(), m.mk_bool_sort()), m); + m.mk_func_decl(m_rel_name, m_domain.size(), m_domain.c_ptr(), m.mk_bool_sort()), m); ctx.insert(pred); m_dl_ctx->register_predicate(pred, m_kinds.size(), m_kinds.c_ptr()); - m_domain = 0; } }; diff --git a/contrib/cmake/src/muz/pdr/CMakeLists.txt b/src/muz/pdr/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/pdr/CMakeLists.txt rename to src/muz/pdr/CMakeLists.txt diff --git a/contrib/cmake/src/muz/rel/CMakeLists.txt b/src/muz/rel/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/rel/CMakeLists.txt rename to src/muz/rel/CMakeLists.txt diff --git a/src/muz/rel/dl_mk_similarity_compressor.cpp b/src/muz/rel/dl_mk_similarity_compressor.cpp index 75caba6ae..b65ed455c 100644 --- a/src/muz/rel/dl_mk_similarity_compressor.cpp +++ b/src/muz/rel/dl_mk_similarity_compressor.cpp @@ -426,7 +426,7 @@ namespace datalog { new_negs.push_back(false); rule * new_rule = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), - new_negs.c_ptr()); + new_negs.c_ptr(), r->name()); m_result_rules.push_back(new_rule); //TODO: allow for a rule to have multiple parent objects diff --git a/src/muz/rel/dl_mk_simple_joins.cpp b/src/muz/rel/dl_mk_simple_joins.cpp index e428fdd2e..a8e54085d 100644 --- a/src/muz/rel/dl_mk_simple_joins.cpp +++ b/src/muz/rel/dl_mk_simple_joins.cpp @@ -726,7 +726,7 @@ namespace datalog { } rule * new_rule = m_context.get_rule_manager().mk(orig_r->get_head(), tail.size(), tail.c_ptr(), - negs.c_ptr()); + negs.c_ptr(), orig_r->name()); new_rule->set_accounting_parent_object(m_context, orig_r); m_context.get_rule_manager().mk_rule_rewrite_proof(*orig_r, *new_rule); diff --git a/src/muz/rel/dl_relation_manager.cpp b/src/muz/rel/dl_relation_manager.cpp index 74206a1f6..5bb47c5c3 100644 --- a/src/muz/rel/dl_relation_manager.cpp +++ b/src/muz/rel/dl_relation_manager.cpp @@ -36,13 +36,10 @@ namespace datalog { void relation_manager::reset_relations() { - relation_map::iterator it=m_relations.begin(); - relation_map::iterator end=m_relations.end(); - for(;it!=end;++it) { - func_decl * pred = it->m_key; + for (auto const& kv : m_relations) { + func_decl * pred = kv.m_key; get_context().get_manager().dec_ref(pred); //inc_ref in get_relation - relation_base * r=(*it).m_value; - r->deallocate(); + kv.m_value->deallocate(); } m_relations.reset(); } @@ -119,35 +116,25 @@ namespace datalog { } void relation_manager::collect_non_empty_predicates(decl_set & res) const { - relation_map::iterator it = m_relations.begin(); - relation_map::iterator end = m_relations.end(); - for(; it!=end; ++it) { - if(!it->m_value->fast_empty()) { - res.insert(it->m_key); + for (auto const& kv : m_relations) { + if (!kv.m_value->fast_empty()) { + res.insert(kv.m_key); } } } void relation_manager::restrict_predicates(const decl_set & preds) { - typedef ptr_vector fd_vector; - fd_vector to_remove; + ptr_vector to_remove; - relation_map::iterator rit = m_relations.begin(); - relation_map::iterator rend = m_relations.end(); - for(; rit!=rend; ++rit) { - func_decl * pred = rit->m_key; + for (auto const& kv : m_relations) { + func_decl* pred = kv.m_key; if (!preds.contains(pred)) { to_remove.insert(pred); } } - fd_vector::iterator pit = to_remove.begin(); - fd_vector::iterator pend = to_remove.end(); - for(; pit!=pend; ++pit) { - func_decl * pred = *pit; - relation_base * rel; - VERIFY( m_relations.find(pred, rel) ); - rel->deallocate(); + for (func_decl* pred : to_remove) { + m_relations.find(pred)->deallocate(); m_relations.remove(pred); get_context().get_manager().dec_ref(pred); } @@ -283,18 +270,16 @@ namespace datalog { } table_plugin * relation_manager::get_table_plugin(symbol const& k) { - table_plugin_vector::iterator tpit = m_table_plugins.begin(); - table_plugin_vector::iterator tpend = m_table_plugins.end(); - for(; tpit!=tpend; ++tpit) { - if((*tpit)->get_name()==k) { - return *tpit; + for (table_plugin * tp : m_table_plugins) { + if (tp->get_name()==k) { + return tp; } } return 0; } table_relation_plugin & relation_manager::get_table_relation_plugin(table_plugin & tp) { - table_relation_plugin * res; + table_relation_plugin * res = 0; VERIFY( m_table_relation_plugins.find(&tp, res) ); return *res; } @@ -341,10 +326,9 @@ namespace datalog { return res; } - for (unsigned i = 0; i < m_relation_plugins.size(); ++i) { - p = m_relation_plugins[i]; - if (p->can_handle_signature(s)) { - return p->mk_empty(s); + for (relation_plugin* p1 : m_relation_plugins) { + if (p1->can_handle_signature(s)) { + return p1->mk_empty(s); } } diff --git a/contrib/cmake/src/muz/tab/CMakeLists.txt b/src/muz/tab/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/tab/CMakeLists.txt rename to src/muz/tab/CMakeLists.txt diff --git a/contrib/cmake/src/muz/transforms/CMakeLists.txt b/src/muz/transforms/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/transforms/CMakeLists.txt rename to src/muz/transforms/CMakeLists.txt diff --git a/src/muz/transforms/dl_mk_filter_rules.cpp b/src/muz/transforms/dl_mk_filter_rules.cpp index b112f4c99..0d118a589 100644 --- a/src/muz/transforms/dl_mk_filter_rules.cpp +++ b/src/muz/transforms/dl_mk_filter_rules.cpp @@ -140,7 +140,7 @@ namespace datalog { if (rule_modified) { remove_duplicate_tails(new_tail, new_is_negated); SASSERT(new_tail.size() == new_is_negated.size()); - rule * new_rule = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), new_is_negated.c_ptr()); + rule * new_rule = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), new_is_negated.c_ptr(), r->name()); new_rule->set_accounting_parent_object(m_context, m_current); m_result->add_rule(new_rule); m_context.get_rule_manager().mk_rule_rewrite_proof(*r, *new_rule); diff --git a/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp b/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp index 455b06d3d..1ed847e89 100644 --- a/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp +++ b/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp @@ -84,7 +84,7 @@ namespace datalog { mk_rule_inliner::remove_duplicate_tails(m_tail, m_neg); SASSERT(m_tail.size() == m_neg.size()); - res = m_context.get_rule_manager().mk(m_head, m_tail.size(), m_tail.c_ptr(), m_neg.c_ptr()); + res = m_context.get_rule_manager().mk(m_head, m_tail.size(), m_tail.c_ptr(), m_neg.c_ptr(),m_rule->name()); res->set_accounting_parent_object(m_context, m_rule); res->norm_vars(res.get_manager()); } @@ -250,7 +250,7 @@ namespace datalog { bool detect_equivalences(expr_ref_vector& v, bool inside_disjunction) { bool have_pair = false; - unsigned prev_pair_idx; + unsigned prev_pair_idx = 0; arg_pair ap; unsigned read_idx = 0; @@ -296,21 +296,20 @@ namespace datalog { br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { - if (m.is_not(f) && (m.is_and(args[0]) || m.is_or(args[0]))) { - SASSERT(num==1); + SASSERT(num == 1); expr_ref tmp(m); app* a = to_app(args[0]); m_app_args.reset(); - for (unsigned i = 0; i < a->get_num_args(); ++i) { - m_brwr.mk_not(a->get_arg(i), tmp); + for (expr* arg : *a) { + m_brwr.mk_not(arg, tmp); m_app_args.push_back(tmp); } if (m.is_and(args[0])) { - result = m.mk_or(m_app_args.size(), m_app_args.c_ptr()); + result = mk_or(m_app_args); } else { - result = m.mk_and(m_app_args.size(), m_app_args.c_ptr()); + result = mk_and(m_app_args); } return BR_REWRITE2; } @@ -557,7 +556,7 @@ namespace datalog { } SASSERT(m_tail.size() == m_tail_neg.size()); - res = m_context.get_rule_manager().mk(head, m_tail.size(), m_tail.c_ptr(), m_tail_neg.c_ptr()); + res = m_context.get_rule_manager().mk(head, m_tail.size(), m_tail.c_ptr(), m_tail_neg.c_ptr(), r->name()); res->set_accounting_parent_object(m_context, r); } else { diff --git a/src/muz/transforms/dl_mk_magic_sets.cpp b/src/muz/transforms/dl_mk_magic_sets.cpp index 048decaf9..19dccf417 100644 --- a/src/muz/transforms/dl_mk_magic_sets.cpp +++ b/src/muz/transforms/dl_mk_magic_sets.cpp @@ -280,7 +280,7 @@ namespace datalog { new_tail.push_back(create_magic_literal(new_head)); negations.push_back(false); - rule * nr = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), negations.c_ptr()); + rule * nr = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), negations.c_ptr(), r->name()); result.add_rule(nr); nr->set_accounting_parent_object(m_context, r); } diff --git a/src/muz/transforms/dl_mk_quantifier_abstraction.cpp b/src/muz/transforms/dl_mk_quantifier_abstraction.cpp index caff79d2e..a22a67416 100644 --- a/src/muz/transforms/dl_mk_quantifier_abstraction.cpp +++ b/src/muz/transforms/dl_mk_quantifier_abstraction.cpp @@ -142,7 +142,8 @@ namespace datalog { m(ctx.get_manager()), m_ctx(ctx), a(m), - m_refs(m) { + m_refs(m), + m_mc(NULL){ } mk_quantifier_abstraction::~mk_quantifier_abstraction() { @@ -341,7 +342,7 @@ namespace datalog { head = mk_head(source, *result, r.get_head(), cnt); fml = m.mk_implies(m.mk_and(tail.size(), tail.c_ptr()), head); proof_ref pr(m); - rm.mk_rule(fml, pr, *result); + rm.mk_rule(fml, pr, *result, r.name()); TRACE("dl", result->last()->display(m_ctx, tout);); } diff --git a/src/muz/transforms/dl_mk_quantifier_instantiation.cpp b/src/muz/transforms/dl_mk_quantifier_instantiation.cpp index 5d36d26cc..586c52cd6 100644 --- a/src/muz/transforms/dl_mk_quantifier_instantiation.cpp +++ b/src/muz/transforms/dl_mk_quantifier_instantiation.cpp @@ -232,7 +232,7 @@ namespace datalog { rule_set added_rules(m_ctx); proof_ref pr(m); - rm.mk_rule(fml, pr, added_rules); + rm.mk_rule(fml, pr, added_rules, r.name()); if (r.get_proof()) { // use def-axiom to encode that new rule is a weakening of the original. proof* p1 = r.get_proof(); diff --git a/src/muz/transforms/dl_mk_rule_inliner.cpp b/src/muz/transforms/dl_mk_rule_inliner.cpp index 7dabece2f..c6b3e8be7 100644 --- a/src/muz/transforms/dl_mk_rule_inliner.cpp +++ b/src/muz/transforms/dl_mk_rule_inliner.cpp @@ -114,7 +114,10 @@ namespace datalog { apply(src, false, UINT_MAX, tail, tail_neg); mk_rule_inliner::remove_duplicate_tails(tail, tail_neg); SASSERT(tail.size()==tail_neg.size()); - res = m_rm.mk(new_head, tail.size(), tail.c_ptr(), tail_neg.c_ptr(), tgt.name(), m_normalize); + std::ostringstream comb_name; + comb_name << tgt.name().str() << ";" << src.name().str(); + symbol combined_rule_name = symbol(comb_name.str().c_str()); + res = m_rm.mk(new_head, tail.size(), tail.c_ptr(), tail_neg.c_ptr(), combined_rule_name, m_normalize); res->set_accounting_parent_object(m_context, const_cast(&tgt)); TRACE("dl", tgt.display(m_context, tout << "tgt (" << tail_index << "): \n"); diff --git a/src/muz/transforms/dl_mk_slice.cpp b/src/muz/transforms/dl_mk_slice.cpp index 2f7d0d475..cefda74e8 100644 --- a/src/muz/transforms/dl_mk_slice.cpp +++ b/src/muz/transforms/dl_mk_slice.cpp @@ -22,7 +22,7 @@ Revision History: input: x, z output: x, y - Let x_i, y_i, z_i be incides into the vectors x, y, z. + Let x_i, y_i, z_i be indices into the vectors x, y, z. Suppose that positions in P and R are annotated with what is slicable. @@ -789,7 +789,7 @@ namespace datalog { tail.push_back(to_app(e)); } - new_rule = rm.mk(head.get(), tail.size(), tail.c_ptr(), (const bool*) 0); + new_rule = rm.mk(head.get(), tail.size(), tail.c_ptr(), (const bool*) 0, r.name()); rm.fix_unbound_vars(new_rule, false); diff --git a/src/muz/transforms/dl_mk_subsumption_checker.cpp b/src/muz/transforms/dl_mk_subsumption_checker.cpp index 1967fdc93..8fae4ee35 100644 --- a/src/muz/transforms/dl_mk_subsumption_checker.cpp +++ b/src/muz/transforms/dl_mk_subsumption_checker.cpp @@ -159,7 +159,7 @@ namespace datalog { } SASSERT(tail.size()==tail_neg.size()); - res = m_context.get_rule_manager().mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr()); + res = m_context.get_rule_manager().mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr(), r->name()); res->set_accounting_parent_object(m_context, r); m_context.get_rule_manager().fix_unbound_vars(res, true); m_context.get_rule_manager().mk_rule_rewrite_proof(*r, *res.get()); diff --git a/src/muz/transforms/dl_mk_unbound_compressor.cpp b/src/muz/transforms/dl_mk_unbound_compressor.cpp index 41b181450..78133aab7 100644 --- a/src/muz/transforms/dl_mk_unbound_compressor.cpp +++ b/src/muz/transforms/dl_mk_unbound_compressor.cpp @@ -173,7 +173,7 @@ namespace datalog { return l_false; } else { - rule_ref new_rule(m_context.get_rule_manager().mk(r, chead), m_context.get_rule_manager()); + rule_ref new_rule(m_context.get_rule_manager().mk(r, chead, r->name()), m_context.get_rule_manager()); new_rule->set_accounting_parent_object(m_context, r); m_head_occurrence_ctr.dec(m_rules.get(rule_index)->get_decl()); diff --git a/contrib/cmake/src/nlsat/CMakeLists.txt b/src/nlsat/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/nlsat/CMakeLists.txt rename to src/nlsat/CMakeLists.txt diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp index 92a80375e..5d9491da2 100644 --- a/src/nlsat/nlsat_explain.cpp +++ b/src/nlsat/nlsat_explain.cpp @@ -1190,6 +1190,7 @@ namespace nlsat { info.m_lc = lc_eq.get(); info.m_lc_sign = sign(lc_eq); info.m_lc_add = false; + info.m_lc_add_ineq = false; info.m_lc_const = m_pm.is_const(lc_eq); SASSERT(info.m_lc != 0); scoped_literal new_lit(m_solver); diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index 7582c8389..7ffb1b0a5 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -623,6 +623,7 @@ namespace nlsat { unsigned sz = cs.size(); for (unsigned i = 0; i < sz; i++) del_clause(cs[i]); + cs.reset(); } void del_clauses() { diff --git a/contrib/cmake/src/nlsat/tactic/CMakeLists.txt b/src/nlsat/tactic/CMakeLists.txt similarity index 74% rename from contrib/cmake/src/nlsat/tactic/CMakeLists.txt rename to src/nlsat/tactic/CMakeLists.txt index 9ea26a0c5..3be3bcfb7 100644 --- a/contrib/cmake/src/nlsat/tactic/CMakeLists.txt +++ b/src/nlsat/tactic/CMakeLists.txt @@ -7,4 +7,7 @@ z3_add_component(nlsat_tactic arith_tactics nlsat sat_tactic + TACTIC_HEADERS + nlsat_tactic.h + qfnra_nlsat_tactic.h ) diff --git a/contrib/cmake/src/opt/CMakeLists.txt b/src/opt/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/opt/CMakeLists.txt rename to src/opt/CMakeLists.txt diff --git a/src/opt/opt_cmds.cpp b/src/opt/opt_cmds.cpp index 571c26e2d..0264a6a24 100644 --- a/src/opt/opt_cmds.cpp +++ b/src/opt/opt_cmds.cpp @@ -100,6 +100,7 @@ public: rational weight = ps().get_rat(symbol("weight"), rational::one()); symbol id = ps().get_sym(symbol("id"), symbol::null); get_opt(ctx, m_opt).add_soft_constraint(m_formula, weight, id); + ctx.print_success(); reset(ctx); } @@ -131,6 +132,7 @@ public: throw cmd_exception("malformed objective term: it cannot be a quantifier or bound variable"); } get_opt(ctx, m_opt).add_objective(to_app(t), m_is_max); + ctx.print_success(); } virtual void failure_cleanup(cmd_context & ctx) { @@ -141,12 +143,35 @@ public: } }; +class get_objectives_cmd : public cmd { + opt::context* m_opt; +public: + get_objectives_cmd(opt::context* opt): + cmd("get-objectives"), + m_opt(opt) + {} + + virtual void reset(cmd_context & ctx) { } + virtual char const * get_usage() const { return "(get-objectives)"; } + virtual char const * get_descr(cmd_context & ctx) const { return "retrieve the objective values (after optimization)"; } + virtual unsigned get_arity() const { return 0; } + virtual void prepare(cmd_context & ctx) {} + virtual void failure_cleanup(cmd_context & ctx) { + reset(ctx); + } + + virtual void execute(cmd_context & ctx) { + get_opt(ctx, m_opt).display_assignment(ctx.regular_stream()); + } +}; + void install_opt_cmds(cmd_context & ctx, opt::context* opt) { ctx.insert(alloc(assert_soft_cmd, opt)); ctx.insert(alloc(min_maximize_cmd, true, opt)); ctx.insert(alloc(min_maximize_cmd, false, opt)); + ctx.insert(alloc(get_objectives_cmd, opt)); } diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp index 94313b13b..5cff5d06f 100644 --- a/src/opt/opt_context.cpp +++ b/src/opt/opt_context.cpp @@ -1317,17 +1317,18 @@ namespace opt { rational r = n.get_rational(); rational eps = n.get_infinitesimal(); expr_ref_vector args(m); + bool is_int = eps.is_zero() && r.is_int(); if (!inf.is_zero()) { - expr* oo = m.mk_const(symbol("oo"), m_arith.mk_int()); + expr* oo = m.mk_const(symbol("oo"), is_int ? m_arith.mk_int() : m_arith.mk_real()); if (inf.is_one()) { args.push_back(oo); } else { - args.push_back(m_arith.mk_mul(m_arith.mk_numeral(inf, inf.is_int()), oo)); + args.push_back(m_arith.mk_mul(m_arith.mk_numeral(inf, is_int), oo)); } } if (!r.is_zero()) { - args.push_back(m_arith.mk_numeral(r, r.is_int())); + args.push_back(m_arith.mk_numeral(r, is_int)); } if (!eps.is_zero()) { expr* ep = m.mk_const(symbol("epsilon"), m_arith.mk_real()); @@ -1335,7 +1336,7 @@ namespace opt { args.push_back(ep); } else { - args.push_back(m_arith.mk_mul(m_arith.mk_numeral(eps, eps.is_int()), ep)); + args.push_back(m_arith.mk_mul(m_arith.mk_numeral(eps, is_int), ep)); } } switch(args.size()) { diff --git a/src/opt/wmax.cpp b/src/opt/wmax.cpp index 58d319a63..15b723c8c 100644 --- a/src/opt/wmax.cpp +++ b/src/opt/wmax.cpp @@ -216,7 +216,7 @@ namespace opt { rational remove_negations(smt::theory_wmaxsat& th, expr_ref_vector const& core, ptr_vector& keys, vector& weights) { rational min_weight(-1); for (unsigned i = 0; i < core.size(); ++i) { - expr* e; + expr* e = 0; VERIFY(m.is_not(core[i], e)); keys.push_back(m_keys[e]); rational weight = m_weights[e]; diff --git a/contrib/cmake/src/parsers/smt/CMakeLists.txt b/src/parsers/smt/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/parsers/smt/CMakeLists.txt rename to src/parsers/smt/CMakeLists.txt diff --git a/contrib/cmake/src/parsers/smt2/CMakeLists.txt b/src/parsers/smt2/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/parsers/smt2/CMakeLists.txt rename to src/parsers/smt2/CMakeLists.txt diff --git a/src/parsers/smt2/smt2parser.cpp b/src/parsers/smt2/smt2parser.cpp index 1486f6e6c..c948389ee 100644 --- a/src/parsers/smt2/smt2parser.cpp +++ b/src/parsers/smt2/smt2parser.cpp @@ -53,6 +53,8 @@ namespace smt2 { dictionary m_sort_id2param_idx; dictionary m_dt_name2idx; + dictionary m_dt_name2arity; + svector m_dt_names; scoped_ptr m_psort_stack; scoped_ptr m_sort_stack; @@ -97,6 +99,8 @@ namespace smt2 { symbol m_define_sort; symbol m_declare_sort; symbol m_declare_datatypes; + symbol m_declare_datatype; + symbol m_par; symbol m_push; symbol m_pop; symbol m_get_value; @@ -367,6 +371,13 @@ namespace smt2 { symbol const & curr_id() const { return m_scanner.get_id(); } rational curr_numeral() const { return m_scanner.get_number(); } + unsigned curr_unsigned() { + rational n = curr_numeral(); + if (!n.is_unsigned()) + throw parser_exception("invalid indexed identifier, index is too big to fit in an unsigned machine integer"); + return n.get_unsigned(); + } + bool curr_is_identifier() const { return curr() == scanner::SYMBOL_TOKEN; } bool curr_is_keyword() const { return curr() == scanner::KEYWORD_TOKEN; } @@ -400,6 +411,8 @@ namespace smt2 { void check_int(char const * msg) { if (!curr_is_int()) throw parser_exception(msg); } void check_int_or_float(char const * msg) { if (!curr_is_int() && !curr_is_float()) throw parser_exception(msg); } void check_float(char const * msg) { if (!curr_is_float()) throw parser_exception(msg); } + symbol check_identifier_next(char const * msg) { check_identifier(msg); symbol s = curr_id(); next(); return s; } + char const * m_current_file; void set_current_file(char const * s) { m_current_file = s; } @@ -550,7 +563,7 @@ namespace smt2 { return r; } - psort * parse_psort_name(bool ignore_unknow_sort = false) { + psort * parse_psort_name(bool ignore_unknown_sort = false) { SASSERT(curr_is_identifier()); symbol id = curr_id(); psort_decl * d = m_ctx.find_psort_decl(id); @@ -567,10 +580,10 @@ namespace smt2 { return pm().mk_psort_var(m_sort_id2param_idx.size(), idx); } else { - if (ignore_unknow_sort) - return 0; - unknown_sort(id); - UNREACHABLE(); + if (!ignore_unknown_sort) { + unknown_sort(id); + UNREACHABLE(); + } return 0; } } @@ -580,19 +593,15 @@ namespace smt2 { SASSERT(curr_is_identifier()); SASSERT(curr_id_is_underscore()); next(); - check_identifier("invalid indexed sort, symbol expected"); - symbol id = curr_id(); + symbol id = check_identifier_next("invalid indexed sort, symbol expected"); psort_decl * d = m_ctx.find_psort_decl(id); if (d == 0) unknown_sort(id); - next(); sbuffer args; while (!curr_is_rparen()) { check_int("invalid indexed sort, integer or ')' expected"); - rational n = curr_numeral(); - if (!n.is_unsigned()) - throw parser_exception("invalid indexed sort, index is too big to fit in an unsigned machine integer"); - args.push_back(n.get_unsigned()); + unsigned u = curr_unsigned(); + args.push_back(u); next(); } if (args.empty()) @@ -608,8 +617,17 @@ namespace smt2 { SASSERT(curr_is_identifier()); symbol id = curr_id(); psort_decl * d = m_ctx.find_psort_decl(id); - if (d == 0) - unknown_sort(id); + int idx = 0; + if (d == 0) { + if (m_dt_name2idx.find(id, idx)) { + throw parser_exception("smtlib 2.6 parametric datatype sorts are not supported"); + // unsigned num_params = m_dt_name2arity.find(id); + // d = pm().mk_psort_dt_decl(num_params, id); + } + else { + unknown_sort(id); + } + } next(); void * mem = m_stack.allocate(sizeof(psort_frame)); new (mem) psort_frame(*this, d, psort_stack().size()); @@ -627,6 +645,7 @@ namespace smt2 { TRACE("smt2parser", tout << "num: " << num << ", d->get_num_params(): " << d->get_num_params() << "\n";); throw parser_exception("invalid number of parameters to sort constructor"); } + psort * r = pm().mk_psort_app(m_sort_id2param_idx.size(), d, num, psort_stack().c_ptr() + spos); psort_stack().shrink(spos); psort_stack().push_back(r); @@ -634,13 +653,13 @@ namespace smt2 { next(); } - void parse_psort() { + void parse_psort(bool ignore_unknown_sort = false) { unsigned stack_pos = psort_stack().size(); (void)stack_pos; unsigned num_frames = 0; do { if (curr_is_identifier()) { - psort_stack().push_back(parse_psort_name()); + psort_stack().push_back(parse_psort_name(false)); } else if (curr_is_rparen()) { if (num_frames == 0) @@ -743,43 +762,46 @@ namespace smt2 { unsigned parse_symbols() { unsigned sz = 0; check_lparen_next("invalid list of symbols, '(' expected"); - while (!curr_is_rparen()) { - check_identifier("invalid list of symbols, symbol or ')' expected"); - m_symbol_stack.push_back(curr_id()); - next(); + while (!curr_is_rparen()) { + m_symbol_stack.push_back(check_identifier_next("invalid list of symbols, symbol or ')' expected")); sz++; } next(); return sz; } + ptype parse_ptype() { + SASSERT(curr_is_identifier()); + psort * p = parse_psort_name(true); + ptype result; + if (p != 0) { + result = ptype(p); + } + else { + // parse_psort_name failed, identifier was not consumed. + int idx; + if (m_dt_name2idx.find(curr_id(), idx)) { + result = ptype(idx); + } + else { + result = ptype(curr_id()); + } + SASSERT(curr_is_identifier()); + next(); + } + return result; + } + // [ '(' identifier sort ')' ]+ void parse_accessor_decls(paccessor_decl_ref_buffer & a_decls) { while (!curr_is_rparen()) { check_lparen_next("invalid datatype declaration, '(' or ')' expected"); - check_identifier("invalid accessor declaration, symbol (accessor name) expected"); - symbol a_name = curr_id(); - next(); - if (curr_is_identifier()) { - psort * p = parse_psort_name(true); - if (p != 0) { - a_decls.push_back(pm().mk_paccessor_decl(m_sort_id2param_idx.size(), a_name, ptype(p))); - } - else { - // parse_psort_name failed, identifier was not consumed. - int idx; - if (m_dt_name2idx.find(curr_id(), idx)) { - a_decls.push_back(pm().mk_paccessor_decl(m_sort_id2param_idx.size(), a_name, ptype(idx))); - } - else { - a_decls.push_back(pm().mk_paccessor_decl(m_sort_id2param_idx.size(), a_name, ptype(curr_id()))); - } - SASSERT(curr_is_identifier()); - next(); - } + symbol a_name = check_identifier_next("invalid accessor declaration, symbol (accessor name) expected"); + if (curr_is_identifier()) { + a_decls.push_back(pm().mk_paccessor_decl(m_sort_id2param_idx.size(), a_name, parse_ptype())); } else { - parse_psort(); + parse_psort(true); a_decls.push_back(pm().mk_paccessor_decl(m_sort_id2param_idx.size(), a_name, ptype(psort_stack().back()))); psort_stack().pop_back(); } @@ -816,46 +838,53 @@ namespace smt2 { if (ct_decls.empty()) throw parser_exception("invalid datatype declaration, datatype does not have any constructors"); } - + void parse_declare_datatypes() { SASSERT(curr_is_identifier()); SASSERT(curr_id() == m_declare_datatypes); next(); unsigned line = m_scanner.get_line(); unsigned pos = m_scanner.get_pos(); - parse_sort_decl_params(); m_dt_name2idx.reset(); + bool is_smt2_6 = parse_sort_decl_or_params(); unsigned i = 0; pdatatype_decl_ref_buffer new_dt_decls(pm()); check_lparen_next("invalid datatype declaration, '(' expected"); + pdatatype_decl_ref d(pm()); while (!curr_is_rparen()) { - check_lparen_next("invalid datatype declaration, '(' or ')' expected"); - check_identifier("invalid datatype declaration, symbol (datatype name) expected"); - symbol dt_name = curr_id(); - next(); - m_dt_name2idx.insert(dt_name, i); pconstructor_decl_ref_buffer new_ct_decls(pm()); - parse_constructor_decls(new_ct_decls); - new_dt_decls.push_back(pm().mk_pdatatype_decl(m_sort_id2param_idx.size(), dt_name, new_ct_decls.size(), new_ct_decls.c_ptr())); - check_rparen_next("invalid datatype declaration, ')' expected"); + if (is_smt2_6) { + if (i >= m_dt_names.size()) { + throw parser_exception("invalid datatype declaration, too many data-type bodies defined"); + } + symbol dt_name = m_dt_names[i]; + parse_datatype_dec(new_ct_decls); + d = pm().mk_pdatatype_decl(m_dt_name2arity.find(dt_name), dt_name, new_ct_decls.size(), new_ct_decls.c_ptr()); + } + else { + check_lparen_next("invalid datatype declaration, '(' or ')' expected"); + symbol dt_name = check_identifier_next("invalid datatype declaration, symbol (datatype name) expected"); + m_dt_name2idx.insert(dt_name, i); + parse_constructor_decls(new_ct_decls); + d = pm().mk_pdatatype_decl(m_sort_id2param_idx.size(), dt_name, new_ct_decls.size(), new_ct_decls.c_ptr()); + check_rparen_next("invalid datatype declaration, ')' expected"); + } + new_dt_decls.push_back(d); i++; } + if (i < m_dt_names.size()) { + throw parser_exception("invalid datatype declaration, too few datatype definitions compared to declared sorts"); + } next(); check_rparen("invalid datatype declaration"); unsigned sz = new_dt_decls.size(); if (sz == 0) { - m_ctx.print_success(); - next(); + m_ctx.print_success(); + next(); return; - } + } else if (sz == 1) { - symbol missing; - if (new_dt_decls[0]->has_missing_refs(missing)) { - std::string err_msg = "invalid datatype declaration, unknown sort '"; - err_msg += missing.str(); - err_msg += "'"; - throw parser_exception(err_msg, line, pos); - } + check_missing(new_dt_decls[0], line, pos); } else { SASSERT(sz > 1); @@ -874,12 +903,7 @@ namespace smt2 { pdatatype_decl * d = new_dt_decls[i]; SASSERT(d != 0); symbol duplicated; - if (d->has_duplicate_accessors(duplicated)) { - std::string err_msg = "invalid datatype declaration, repeated accessor identifier '"; - err_msg += duplicated.str(); - err_msg += "'"; - throw parser_exception(err_msg, line, pos); - } + check_duplicate(d, line, pos); m_ctx.insert(d); if (d->get_num_params() == 0) { // if datatype is not parametric... then force instantiation to register accessor, recognizers and constructors... @@ -890,7 +914,78 @@ namespace smt2 { TRACE("declare_datatypes", tout << "i: " << i << " new_dt_decls.size(): " << sz << "\n"; for (unsigned i = 0; i < sz; i++) tout << new_dt_decls[i]->get_name() << "\n";); m_ctx.print_success(); - next(); + next(); + } + + // ( declare-datatype symbol datatype_dec) + void parse_declare_datatype() { + SASSERT(curr_is_identifier()); + SASSERT(curr_id() == m_declare_datatype); + next(); + unsigned line = m_scanner.get_line(); + unsigned pos = m_scanner.get_pos(); + symbol dt_name = curr_id(); + next(); + + m_dt_name2idx.reset(); + m_dt_name2idx.insert(dt_name, 0); + + m_sort_id2param_idx.reset(); + + pdatatype_decl_ref d(pm()); + pconstructor_decl_ref_buffer new_ct_decls(pm()); + parse_datatype_dec(new_ct_decls); + d = pm().mk_pdatatype_decl(m_sort_id2param_idx.size(), dt_name, new_ct_decls.size(), new_ct_decls.c_ptr()); + + check_missing(d, line, pos); + check_duplicate(d, line, pos); + + m_ctx.insert(d); + if (d->get_num_params() == 0) { + // if datatype is not parametric... then force instantiation to register accessor, recognizers and constructors... + sort_ref s(m()); + s = d->instantiate(pm(), 0, 0); + } + check_rparen_next("invalid end of datatype declaration, ')' expected"); + m_ctx.print_success(); + } + + + // datatype_dec ::= ( constructor_dec+ ) | ( par ( symbol+ ) ( constructor_dec+ ) ) + + void parse_datatype_dec(pconstructor_decl_ref_buffer & ct_decls) { + check_lparen_next("invalid datatype declaration, '(' expected"); + if (curr_id() == m_par) { + next(); + parse_sort_decl_params(); + check_lparen_next("invalid constructor declaration after par, '(' expected"); + parse_constructor_decls(ct_decls); + check_rparen_next("invalid datatype declaration, ')' expected"); + } + else { + parse_constructor_decls(ct_decls); + } + check_rparen_next("invalid datatype declaration, ')' expected"); + } + + void check_missing(pdatatype_decl* d, unsigned line, unsigned pos) { + symbol missing; + if (d->has_missing_refs(missing)) { + std::string err_msg = "invalid datatype declaration, unknown sort '"; + err_msg += missing.str(); + err_msg += "'"; + throw parser_exception(err_msg, line, pos); + } + } + + void check_duplicate(pdatatype_decl* d, unsigned line, unsigned pos) { + symbol duplicated; + if (d->has_duplicate_accessors(duplicated)) { + std::string err_msg = "invalid datatype declaration, repeated accessor identifier '"; + err_msg += duplicated.str(); + err_msg += "'"; + throw parser_exception(err_msg, line, pos); + } } void name_expr(expr * n, symbol const & s) { @@ -970,10 +1065,8 @@ namespace smt2 { fr->m_last_symbol = symbol::null; TRACE("consume_attributes", tout << "id: " << id << ", expr_stack().size(): " << expr_stack().size() << "\n";); if (id == m_named) { - next(); - check_identifier("invalid attribute value, symbol expected"); - name_expr(expr_stack().back(), curr_id()); - next(); + next(); + name_expr(expr_stack().back(), check_identifier_next("invalid attribute value, symbol expected")); } else if (id == m_lblpos || id == m_lblneg) { next(); @@ -989,18 +1082,13 @@ namespace smt2 { check_in_quant_ctx(fr); next(); check_int("invalid weight attribute, integer expected"); - rational n = curr_numeral(); - if (!n.is_unsigned()) - throw parser_exception("invalid weight attribute, value is too big to fit in an unsigned machine integer"); - store_weight(fr, n.get_unsigned()); + store_weight(fr, curr_unsigned()); next(); } else if (id == m_skid) { check_in_quant_ctx(fr); - next(); - check_identifier("invalid attribute value, symbol expected"); - store_skid(fr, curr_id()); - next(); + next(); + store_skid(fr, check_identifier_next("invalid attribute value, symbol expected")); } else if (id == m_qid) { check_in_quant_ctx(fr); @@ -1207,10 +1295,8 @@ namespace smt2 { unsigned num_indices = 0; while (!curr_is_rparen()) { if (curr_is_int()) { - rational n = curr_numeral(); - if (!n.is_unsigned()) - throw parser_exception("invalid indexed identifier, index is too big to fit in an unsigned machine integer"); - m_param_stack.push_back(parameter(n.get_unsigned())); + unsigned u = curr_unsigned(); + m_param_stack.push_back(parameter(u)); next(); } else if (curr_is_identifier() || curr_is_lparen()) { @@ -1570,7 +1656,9 @@ namespace smt2 { fr->m_in_decls = false; SASSERT(symbol_stack().size() >= fr->m_sym_spos); SASSERT(expr_stack().size() >= fr->m_expr_spos); - SASSERT(symbol_stack().size() - fr->m_sym_spos == expr_stack().size() - fr->m_expr_spos); + if (symbol_stack().size() - fr->m_sym_spos != expr_stack().size() - fr->m_expr_spos) { + throw parser_exception("malformed let expression"); + } unsigned num_decls = expr_stack().size() - fr->m_expr_spos; symbol * sym_it = symbol_stack().c_ptr() + fr->m_sym_spos; expr ** expr_it = expr_stack().c_ptr() + fr->m_expr_spos; @@ -1786,8 +1874,8 @@ namespace smt2 { } void parse_sort_decl_params() { - check_lparen_next("invalid sort declaration, parameters missing"); m_sort_id2param_idx.reset(); + check_lparen_next("invalid sort declaration, parameters missing"); unsigned i = 0; while (!curr_is_rparen()) { check_identifier("invalid sort parameter, symbol or ')' expected"); @@ -1795,7 +1883,43 @@ namespace smt2 { i++; next(); } - next(); + next(); + } + + bool parse_sort_decl_or_params() { + m_sort_id2param_idx.reset(); + m_dt_name2arity.reset(); + m_dt_name2idx.reset(); + m_dt_names.reset(); + check_lparen_next("invalid sort declaration, parameters missing"); + unsigned i = 0; + bool first = true; + bool is_decl = false; + while (!curr_is_rparen()) { + if (first) { + is_decl = curr_is_lparen(); + first = false; + } + if (is_decl) { + check_lparen_next("invalid sort declaration, '(' expected"); + symbol dt_name = check_identifier_next("invalid sort name, identified expected"); + check_int("invalid sort declaration, arity expected"); + unsigned u = curr_unsigned(); + next(); + m_dt_name2idx.insert(dt_name, i); + m_dt_name2arity.insert(dt_name, u); + m_dt_names.push_back(dt_name); + check_rparen("invalid sort declaration, ')' expected"); + } + else { + check_identifier("invalid sort parameter, symbol or ')' expected"); + m_sort_id2param_idx.insert(curr_id(), i); + } + i++; + next(); + } + next(); + return is_decl; } void parse_declare_sort() { @@ -1814,10 +1938,8 @@ namespace smt2 { } else { check_int("invalid sort declaration, arity () or ')' expected"); - rational n = curr_numeral(); - if (!n.is_unsigned()) - throw parser_exception("invalid sort declaration, arity is too big to fit in an unsigned machine integer"); - psort_decl * decl = pm().mk_psort_user_decl(n.get_unsigned(), id, 0); + unsigned u = curr_unsigned(); + psort_decl * decl = pm().mk_psort_user_decl(u, id, 0); m_ctx.insert(decl); next(); check_rparen("invalid sort declaration, ')' expected"); @@ -2118,6 +2240,9 @@ namespace smt2 { m_assert_expr = m_scanner.cached_str(0, m_cache_end); m_scanner.stop_caching(); } + if (expr_stack().empty()) { + throw cmd_exception("invalid assert command, expression required as argument"); + } expr * f = expr_stack().back(); if (!m().is_bool(f)) throw cmd_exception("invalid assert command, term is not Boolean"); @@ -2222,9 +2347,7 @@ namespace smt2 { if (curr_is_keyword() && (curr_id() == ":model-index" || curr_id() == ":model_index")) { next(); check_int("integer index expected to indexed model evaluation"); - if (!curr_numeral().is_unsigned()) - throw parser_exception("expected unsigned integer index to model evaluation"); - index = curr_numeral().get_unsigned(); + index = curr_unsigned(); next(); } @@ -2315,10 +2438,8 @@ namespace smt2 { next(); while (!curr_is_rparen()) { check_int("invalid indexed function declaration reference, integer or ')' expected"); - rational n = curr_numeral(); - if (!n.is_unsigned()) - throw parser_exception("invalid indexed function declaration reference, index is too big to fit in an unsigned machine integer"); - indices.push_back(n.get_unsigned()); + unsigned u = curr_unsigned(); + indices.push_back(u); next(); } if (indices.empty()) @@ -2350,10 +2471,8 @@ namespace smt2 { switch (k) { case CPK_UINT: { check_int("invalid command argument, unsigned integer expected"); - rational n = curr_numeral(); - if (!n.is_unsigned()) - throw parser_exception("invalid command argument, numeral is too big to fit in an unsigned machine integer"); - m_curr_cmd->set_next_arg(m_ctx, n.get_unsigned()); + unsigned u = curr_unsigned(); + m_curr_cmd->set_next_arg(m_ctx, u); next(); break; } @@ -2554,6 +2673,10 @@ namespace smt2 { parse_declare_datatypes(); return; } + if (s == m_declare_datatype) { + parse_declare_datatype(); + return; + } if (s == m_get_value) { parse_get_value(); return; @@ -2610,6 +2733,8 @@ namespace smt2 { m_define_sort("define-sort"), m_declare_sort("declare-sort"), m_declare_datatypes("declare-datatypes"), + m_declare_datatype("declare-datatype"), + m_par("par"), m_push("push"), m_pop("pop"), m_get_value("get-value"), diff --git a/src/parsers/smt2/smt2scanner.cpp b/src/parsers/smt2/smt2scanner.cpp index fb2f9f34a..1763a4fa5 100644 --- a/src/parsers/smt2/smt2scanner.cpp +++ b/src/parsers/smt2/smt2scanner.cpp @@ -23,7 +23,7 @@ namespace smt2 { void scanner::next() { if (m_cache_input) - m_cache.push_back(m_curr); + m_cache.push_back(m_curr); SASSERT(!m_at_eof); if (m_interactive) { m_curr = m_stream.get(); @@ -293,11 +293,11 @@ namespace smt2 { } scanner::token scanner::scan() { - while (true) { + while (true) { signed char c = curr(); m_pos = m_spos; - if (m_at_eof) + if (m_at_eof) return EOF_TOKEN; switch (m_normalized[(unsigned char) c]) { diff --git a/contrib/cmake/src/parsers/util/CMakeLists.txt b/src/parsers/util/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/parsers/util/CMakeLists.txt rename to src/parsers/util/CMakeLists.txt diff --git a/contrib/cmake/src/qe/CMakeLists.txt b/src/qe/CMakeLists.txt similarity index 77% rename from contrib/cmake/src/qe/CMakeLists.txt rename to src/qe/CMakeLists.txt index 6e82e2c96..2d2cf9579 100644 --- a/contrib/cmake/src/qe/CMakeLists.txt +++ b/src/qe/CMakeLists.txt @@ -23,6 +23,13 @@ z3_add_component(qe nlsat_tactic nlsat sat - smt - tactic + smt + tactic + TACTIC_HEADERS + nlqsat.h + qe_lite.h + qe_sat_tactic.h + qe_tactic.h + qsat.h + vsubst_tactic.h ) diff --git a/src/qe/qe_arith.cpp b/src/qe/qe_arith.cpp index d98f36d7d..4490d83db 100644 --- a/src/qe/qe_arith.cpp +++ b/src/qe/qe_arith.cpp @@ -90,8 +90,8 @@ namespace qe { rational r1, r2; expr_ref val1 = eval(e1); expr_ref val2 = eval(e2); - VERIFY(a.is_numeral(val1, r1)); - VERIFY(a.is_numeral(val2, r2)); + if (!a.is_numeral(val1, r1)) return false; + if (!a.is_numeral(val2, r2)) return false; SASSERT(r1 != r2); if (r1 < r2) { std::swap(e1, e2); @@ -107,7 +107,7 @@ namespace qe { vector > nums; for (unsigned i = 0; i < alit->get_num_args(); ++i) { val = eval(alit->get_arg(i)); - VERIFY(a.is_numeral(val, r)); + if (!a.is_numeral(val, r)) return false; nums.push_back(std::make_pair(alit->get_arg(i), r)); } std::sort(nums.begin(), nums.end(), compare_second()); @@ -129,7 +129,7 @@ namespace qe { expr* arg1 = to_app(lit)->get_arg(i), *arg2 = 0; rational r; expr_ref val = eval(arg1); - VERIFY(a.is_numeral(val, r)); + if (!a.is_numeral(val, r)) return false; if (values.find(r, arg2)) { ty = opt::t_eq; linearize(mbo, eval, mul, arg1, c, fmls, ts, tids); @@ -196,7 +196,7 @@ namespace qe { linearize(mbo, eval, mul, t3, c, fmls, ts, tids); } } - else if (a.is_mod(t, t1, t2) && is_numeral(t2, mul1)) { + else if (a.is_mod(t, t1, t2) && is_numeral(t2, mul1) && !mul1.is_zero()) { rational r; val = eval(t); VERIFY(a.is_numeral(val, r)); diff --git a/src/qe/qe_arith_plugin.cpp b/src/qe/qe_arith_plugin.cpp index 4281ec909..d8ae75256 100644 --- a/src/qe/qe_arith_plugin.cpp +++ b/src/qe/qe_arith_plugin.cpp @@ -2503,7 +2503,7 @@ public: } virtual void subst(contains_app& x, rational const& vl, expr_ref& fml, expr_ref* def) { - nlarith::branch_conditions *brs; + nlarith::branch_conditions *brs = 0; VERIFY (m_cache.find(x.x(), fml, brs)); SASSERT(vl.is_unsigned()); SASSERT(vl.get_unsigned() < brs->size()); diff --git a/src/qe/qe_lite.cpp b/src/qe/qe_lite.cpp index eccc2d0c7..ce182a97b 100644 --- a/src/qe/qe_lite.cpp +++ b/src/qe/qe_lite.cpp @@ -36,44 +36,7 @@ Revision History: #include "cooperate.h" #include "datatype_decl_plugin.h" -class is_variable_proc { -public: - virtual bool operator()(expr* e) const = 0; -}; - -class is_variable_test : public is_variable_proc { - enum is_var_kind { BY_VAR_SET, BY_VAR_SET_COMPLEMENT, BY_NUM_DECLS }; - uint_set m_var_set; - unsigned m_num_decls; - is_var_kind m_var_kind; -public: - is_variable_test(uint_set const& vars, bool index_of_bound) : - m_var_set(vars), - m_num_decls(0), - m_var_kind(index_of_bound?BY_VAR_SET:BY_VAR_SET_COMPLEMENT) {} - - is_variable_test(unsigned num_decls) : - m_num_decls(num_decls), - m_var_kind(BY_NUM_DECLS) {} - - virtual bool operator()(expr* e) const { - if (!is_var(e)) { - return false; - } - unsigned idx = to_var(e)->get_idx(); - switch(m_var_kind) { - case BY_VAR_SET: - return m_var_set.contains(idx); - case BY_VAR_SET_COMPLEMENT: - return !m_var_set.contains(idx); - case BY_NUM_DECLS: - return idx < m_num_decls; - } - UNREACHABLE(); - return false; - } -}; - +#include "qe_vartest.h" namespace eq { class der { @@ -86,6 +49,7 @@ namespace eq { ptr_vector m_map; int_vector m_pos2var; + int_vector m_var2pos; ptr_vector m_inx2var; unsigned_vector m_order; expr_ref_vector m_subst_map; @@ -578,6 +542,7 @@ namespace eq { largest_vinx = 0; m_map.reset(); m_pos2var.reset(); + m_var2pos.reset(); m_inx2var.reset(); m_pos2var.reserve(num_args, -1); @@ -597,10 +562,48 @@ namespace eq { m_map[idx] = t; m_inx2var[idx] = v; m_pos2var[i] = idx; + m_var2pos.reserve(idx + 1, -1); + m_var2pos[idx] = i; def_count++; largest_vinx = std::max(idx, largest_vinx); m_new_exprs.push_back(t); } + else if (!m.is_value(m_map[idx])) { + // check if the new definition is simpler + expr *old_def = m_map[idx]; + + // -- prefer values + if (m.is_value(t)) { + m_pos2var[m_var2pos[idx]] = -1; + m_pos2var[i] = idx; + m_var2pos[idx] = i; + m_map[idx] = t; + m_new_exprs.push_back(t); + } + // -- prefer ground + else if (is_app(t) && to_app(t)->is_ground() && + (!is_app(old_def) || + !to_app(old_def)->is_ground())) { + m_pos2var[m_var2pos[idx]] = -1; + m_pos2var[i] = idx; + m_var2pos[idx] = i; + m_map[idx] = t; + m_new_exprs.push_back(t); + } + // -- prefer constants + else if (is_uninterp_const(t) + /* && !is_uninterp_const(old_def) */){ + m_pos2var[m_var2pos[idx]] = -1; + m_pos2var[i] = idx; + m_var2pos[idx] = i; + m_map[idx] = t; + m_new_exprs.push_back(t); + } + TRACE ("qe_def", + tout << "Replacing definition of VAR " << idx << " from " + << mk_pp(old_def, m) << " to " << mk_pp(t, m) + << " inferred from: " << mk_pp(args[i], m) << "\n";); + } } } } @@ -825,12 +828,13 @@ namespace ar { } /** - Ex A. A[x] = t & Phi where x \not\in A, t. A \not\in t, x + Ex A. A[x] = t & Phi[A] where x \not\in A, t. A \not\in t, x => Ex A. Phi[store(A,x,t)] + (Not implemented) Perhaps also: - Ex A. store(A,y,z)[x] = t & Phi where x \not\in A, t, y, z, A \not\in y z, t + Ex A. store(A,y,z)[x] = t & Phi[A] where x \not\in A, t, y, z, A \not\in y z, t => Ex A, v . (x = y => z = t) & Phi[store(store(A,x,t),y,v)] @@ -859,7 +863,8 @@ namespace ar { expr_safe_replace rep(m); rep.insert(A, B); expr_ref tmp(m); - std::cout << mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n"; + TRACE("qe_lite", + tout << mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";); for (unsigned j = 0; j < conjs.size(); ++j) { if (i == j) { conjs[j] = m.mk_true(); @@ -1491,8 +1496,10 @@ namespace fm { unsigned sz = g.size(); for (unsigned i = 0; i < sz; i++) { expr * f = g[i]; - if (is_occ(f)) + if (is_occ(f)) { + TRACE("qe_lite", tout << "OCC: " << mk_ismt2_pp(f, m) << "\n";); continue; + } TRACE("qe_lite", tout << "not OCC:\n" << mk_ismt2_pp(f, m) << "\n";); quick_for_each_expr(proc, visited, f); } @@ -2221,6 +2228,9 @@ namespace fm { void operator()(expr_ref_vector& fmls) { init(fmls); init_use_list(fmls); + for (auto & f : fmls) { + if (has_quantifiers(f)) return; + } if (m_inconsistent) { m_new_fmls.reset(); m_new_fmls.push_back(m.mk_false()); diff --git a/src/qe/qe_vartest.h b/src/qe/qe_vartest.h new file mode 100644 index 000000000..b2b4be649 --- /dev/null +++ b/src/qe/qe_vartest.h @@ -0,0 +1,63 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + qe_vartest.h + +Abstract: + + Utilities for quantifiers. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-08-28 + +Revision History: + +--*/ +#ifndef QE_VARTEST_H_ +#define QE_VARTEST_H_ + +#include "ast.h" +#include "uint_set.h" + +class is_variable_proc { +public: + virtual bool operator()(expr* e) const = 0; +}; + +class is_variable_test : public is_variable_proc { + enum is_var_kind { BY_VAR_SET, BY_VAR_SET_COMPLEMENT, BY_NUM_DECLS }; + uint_set m_var_set; + unsigned m_num_decls; + is_var_kind m_var_kind; +public: + is_variable_test(uint_set const& vars, bool index_of_bound) : + m_var_set(vars), + m_num_decls(0), + m_var_kind(index_of_bound?BY_VAR_SET:BY_VAR_SET_COMPLEMENT) {} + + is_variable_test(unsigned num_decls) : + m_num_decls(num_decls), + m_var_kind(BY_NUM_DECLS) {} + + virtual bool operator()(expr* e) const { + if (!is_var(e)) { + return false; + } + unsigned idx = to_var(e)->get_idx(); + switch(m_var_kind) { + case BY_VAR_SET: + return m_var_set.contains(idx); + case BY_VAR_SET_COMPLEMENT: + return !m_var_set.contains(idx); + case BY_NUM_DECLS: + return idx < m_num_decls; + } + UNREACHABLE(); + return false; + } +}; + +#endif diff --git a/contrib/cmake/src/sat/CMakeLists.txt b/src/sat/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/sat/CMakeLists.txt rename to src/sat/CMakeLists.txt diff --git a/src/sat/ba_solver.cpp b/src/sat/ba_solver.cpp index 242ecb590..0b28c21a7 100644 --- a/src/sat/ba_solver.cpp +++ b/src/sat/ba_solver.cpp @@ -2309,14 +2309,14 @@ namespace sat { // ---------------------------------- // lp based relaxation - void ba_solver::lp_add_var(int coeff, lean::var_index v, lhs_t& lhs, rational& rhs) { + void ba_solver::lp_add_var(int coeff, lp::var_index v, lhs_t& lhs, rational& rhs) { if (coeff < 0) { rhs += rational(coeff); } lhs.push_back(std::make_pair(rational(coeff), v)); } - void ba_solver::lp_add_clause(lean::lar_solver& s, svector const& vars, clause const& c) { + void ba_solver::lp_add_clause(lp::lar_solver& s, svector const& vars, clause const& c) { lhs_t lhs; rational rhs; if (c.frozen()) return; @@ -2324,26 +2324,26 @@ namespace sat { for (literal l : c) { lp_add_var(l.sign() ? -1 : 1, vars[l.var()], lhs, rhs); } - s.add_constraint(lhs, lean::GE, rhs); + s.add_constraint(lhs, lp::GE, rhs); } void ba_solver::lp_lookahead_reduction() { - lean::lar_solver solver; + lp::lar_solver solver; solver.settings().set_message_ostream(&std::cout); solver.settings().set_debug_ostream(&std::cout); solver.settings().print_statistics = true; solver.settings().report_frequency = 1000; - // solver.settings().simplex_strategy() = lean::simplex_strategy_enum::lu; - runs out of memory + // solver.settings().simplex_strategy() = lp::simplex_strategy_enum::lu; - runs out of memory // TBD: set rlimit on the solver - svector vars; + svector vars; for (unsigned i = 0; i < s().num_vars(); ++i) { - lean::var_index v = solver.add_var(i, false); + lp::var_index v = solver.add_var(i, false); vars.push_back(v); - solver.add_var_bound(v, lean::GE, rational::zero()); - solver.add_var_bound(v, lean::LE, rational::one()); + solver.add_var_bound(v, lp::GE, rational::zero()); + solver.add_var_bound(v, lp::LE, rational::one()); switch (value(v)) { - case l_true: solver.add_var_bound(v, lean::GE, rational::one()); break; - case l_false: solver.add_var_bound(v, lean::LE, rational::zero()); break; + case l_true: solver.add_var_bound(v, lp::GE, rational::one()); break; + case l_false: solver.add_var_bound(v, lp::LE, rational::zero()); break; default: break; } } @@ -2368,7 +2368,7 @@ namespace sat { int co = p.get_coeff(i); lp_add_var(l.sign() ? -co : co, vars[l.var()], lhs, rhs); } - solver.add_constraint(lhs, lean::GE, rhs); + solver.add_constraint(lhs, lp::GE, rhs); break; } default: @@ -2379,8 +2379,8 @@ namespace sat { std::cout << "lp solve\n"; std::cout.flush(); - lean::lp_status st = solver.solve(); - if (st == lean::INFEASIBLE) { + lp::lp_status st = solver.solve(); + if (st == lp::lp_status::INFEASIBLE) { std::cout << "infeasible\n"; s().set_conflict(justification()); return; @@ -2388,30 +2388,30 @@ namespace sat { std::cout << "feasible\n"; std::cout.flush(); for (unsigned i = 0; i < s().num_vars(); ++i) { - lean::var_index v = vars[i]; + lp::var_index v = vars[i]; if (value(v) != l_undef) continue; // TBD: take initial model into account to limit queries. std::cout << "solve v" << v << "\n"; std::cout.flush(); solver.push(); - solver.add_var_bound(v, lean::GE, rational::one()); + solver.add_var_bound(v, lp::GE, rational::one()); st = solver.solve(); solver.pop(1); - if (st == lean::INFEASIBLE) { + if (st == lp::lp_status::INFEASIBLE) { std::cout << "found unit: " << literal(v, true) << "\n"; s().assign(literal(v, true), justification()); - solver.add_var_bound(v, lean::LE, rational::zero()); + solver.add_var_bound(v, lp::LE, rational::zero()); continue; } solver.push(); - solver.add_var_bound(v, lean::LE, rational::zero()); + solver.add_var_bound(v, lp::LE, rational::zero()); st = solver.solve(); solver.pop(1); - if (st == lean::INFEASIBLE) { + if (st == lp::lp_status::INFEASIBLE) { std::cout << "found unit: " << literal(v, false) << "\n"; s().assign(literal(v, false), justification()); - solver.add_var_bound(v, lean::GE, rational::zero()); + solver.add_var_bound(v, lp::GE, rational::zero()); continue; } } diff --git a/src/sat/ba_solver.h b/src/sat/ba_solver.h index 2496de593..d40611dfe 100644 --- a/src/sat/ba_solver.h +++ b/src/sat/ba_solver.h @@ -269,10 +269,10 @@ namespace sat { void gc_half(char const* _method); void mutex_reduction(); - typedef vector> lhs_t; + typedef vector> lhs_t; void lp_lookahead_reduction(); - void lp_add_var(int coeff, lean::var_index v, lhs_t& lhs, rational& rhs); - void lp_add_clause(lean::lar_solver& s, svector const& vars, clause const& c); + void lp_add_var(int coeff, lp::var_index v, lhs_t& lhs, rational& rhs); + void lp_add_clause(lp::lar_solver& s, svector const& vars, clause const& c); unsigned use_count(literal lit) const { return m_cnstr_use_list[lit.index()].size() + m_clause_use_list.get(lit).size(); } diff --git a/src/sat/sat_model_converter.cpp b/src/sat/sat_model_converter.cpp index 45429805c..96ac70a48 100644 --- a/src/sat/sat_model_converter.cpp +++ b/src/sat/sat_model_converter.cpp @@ -59,6 +59,7 @@ namespace sat { sat = false; continue; } + if (sat) continue; bool sign = l.sign(); @@ -126,7 +127,7 @@ namespace sat { } return ok; } - + model_converter::entry & model_converter::mk(kind k, bool_var v) { m_entries.push_back(entry(k, v)); entry & e = m_entries.back(); @@ -210,7 +211,7 @@ namespace sat { out << l; } out << ")"; - } + } out << ")\n"; } @@ -223,4 +224,22 @@ namespace sat { for (entry const & e : m_entries) s.insert(e.m_var); } + unsigned model_converter::max_var(unsigned min) const { + unsigned result = min; + vector::const_iterator it = m_entries.begin(); + vector::const_iterator end = m_entries.end(); + for (; it != end; ++it) { + literal_vector::const_iterator lvit = it->m_clauses.begin(); + literal_vector::const_iterator lvend = it->m_clauses.end(); + for (; lvit != lvend; ++lvit) { + literal l = *lvit; + if (l != null_literal) { + if (l.var() > result) + result = l.var(); + } + } + } + return result; + } + }; diff --git a/src/sat/sat_model_converter.h b/src/sat/sat_model_converter.h index e35f2a0aa..5a3c15ffc 100644 --- a/src/sat/sat_model_converter.h +++ b/src/sat/sat_model_converter.h @@ -26,7 +26,7 @@ namespace sat { \brief Stores eliminated variables and Blocked clauses. It uses these clauses to extend/patch the model produced for the simplified CNF formula. - + This information may also be used to support incremental solving. If new clauses are asserted into the SAT engine, then we can restore the state by re-asserting all clauses in the model @@ -50,7 +50,7 @@ namespace sat { m_kind(src.m_kind), m_clauses(src.m_clauses) { } - bool_var var() const { return m_var; } + bool_var var() const { return m_var; } kind get_kind() const { return static_cast(m_kind); } }; private: @@ -75,8 +75,9 @@ namespace sat { void copy(model_converter const & src); void collect_vars(bool_var_set & s) const; + unsigned max_var(unsigned min) const; }; - + }; #endif diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index 85b1d7e50..f98175823 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -2884,7 +2884,7 @@ namespace sat { unsigned j = 0; for (unsigned i = 0; i < clauses.size(); ++i) { clause & c = *(clauses[i]); - if (c.contains(lit)) { + if (c.contains(lit) || c.contains(~lit)) { detach_clause(c); del_clause(c); } @@ -2940,6 +2940,7 @@ namespace sat { w = max_var(m_clauses, w); w = max_var(true, w); w = max_var(false, w); + v = m_mc.max_var(w); for (unsigned i = 0; i < m_trail.size(); ++i) { if (m_trail[i].var() > w) w = m_trail[i].var(); } @@ -3430,9 +3431,9 @@ namespace sat { } } } - + // Algorithm 7: Corebased Algorithm with Chunking - + static void back_remove(sat::literal_vector& lits, sat::literal l) { for (unsigned i = lits.size(); i > 0; ) { --i; @@ -3456,7 +3457,7 @@ namespace sat { } } } - + static lbool core_chunking(sat::solver& s, model const& m, sat::bool_var_vector const& vars, sat::literal_vector const& asms, vector& conseq, unsigned K) { sat::literal_vector lambda; for (unsigned i = 0; i < vars.size(); i++) { @@ -3656,7 +3657,7 @@ namespace sat { SASSERT(search_lvl() == 1); unsigned num_iterations = 0; - extract_fixed_consequences(unfixed_lits, assumptions, unfixed_vars, conseq); + extract_fixed_consequences(unfixed_lits, assumptions, unfixed_vars, conseq); update_unfixed_literals(unfixed_lits, unfixed_vars); while (!unfixed_lits.empty()) { if (scope_lvl() > search_lvl()) { @@ -3671,7 +3672,7 @@ namespace sat { unsigned num_assigned = 0; lbool is_sat = l_true; for (; it != end; ++it) { - literal lit = *it; + literal lit = *it; if (value(lit) != l_undef) { ++num_fixed; if (lvl(lit) <= 1 && value(lit) == l_true) { @@ -3726,8 +3727,8 @@ namespace sat { << " iterations: " << num_iterations << " variables: " << unfixed_lits.size() << " fixed: " << conseq.size() - << " status: " << is_sat - << " pre-assigned: " << num_fixed + << " status: " << is_sat + << " pre-assigned: " << num_fixed << " unfixed: " << lits.size() - conseq.size() - unfixed_lits.size() << ")\n";); diff --git a/contrib/cmake/src/sat/sat_solver/CMakeLists.txt b/src/sat/sat_solver/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/sat/sat_solver/CMakeLists.txt rename to src/sat/sat_solver/CMakeLists.txt diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index 07042b682..0fc5cff25 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -155,7 +155,7 @@ public: } bool is_literal(expr* e) const { - return + return is_uninterp_const(e) || (m.is_not(e, e) && is_uninterp_const(e)); } @@ -179,7 +179,7 @@ public: asm2fml.insert(assumptions[i], assumptions[i]); } } - + TRACE("sat", tout << _assumptions << "\n";); dep2asm_t dep2asm; m_model = 0; @@ -192,7 +192,7 @@ public: init_reason_unknown(); r = m_solver.check(m_asms.size(), m_asms.c_ptr()); - + switch (r) { case l_true: if (sz > 0) { @@ -385,14 +385,14 @@ public: return r; } - // build map from bound variables to + // build map from bound variables to // the consequences that cover them. u_map bool_var2conseq; for (unsigned i = 0; i < lconseq.size(); ++i) { TRACE("sat", tout << lconseq[i] << "\n";); bool_var2conseq.insert(lconseq[i][0].var(), i); } - + // extract original fixed variables u_map asm2dep; extract_asm2dep(dep2asm, asm2dep); @@ -583,7 +583,7 @@ private: lbool internalize_vars(expr_ref_vector const& vars, sat::bool_var_vector& bvars) { for (unsigned i = 0; i < vars.size(); ++i) { - internalize_var(vars[i], bvars); + internalize_var(vars[i], bvars); } return l_true; } @@ -595,7 +595,7 @@ private: bool internalized = false; if (is_uninterp_const(v) && m.is_bool(v)) { sat::bool_var b = m_map.to_bool_var(v); - + if (b != sat::null_bool_var) { bvars.push_back(b); internalized = true; @@ -621,7 +621,7 @@ private: else if (is_uninterp_const(v) && bvutil.is_bv(v)) { // variable does not occur in assertions, so is unconstrained. } - CTRACE("sat", !internalized, tout << "unhandled variable " << mk_pp(v, m) << "\n";); + CTRACE("sat", !internalized, tout << "unhandled variable " << mk_pp(v, m) << "\n";); return internalized; } @@ -648,7 +648,7 @@ private: } expr_ref val(m); expr_ref_vector conj(m); - internalize_value(value, v, val); + internalize_value(value, v, val); while (!premises.empty()) { expr* e = 0; VERIFY(asm2dep.find(premises.pop().index(), e)); @@ -739,16 +739,14 @@ private: extract_asm2dep(dep2asm, asm2dep); sat::literal_vector const& core = m_solver.get_core(); TRACE("sat", - dep2asm_t::iterator it2 = dep2asm.begin(); - dep2asm_t::iterator end2 = dep2asm.end(); - for (; it2 != end2; ++it2) { - tout << mk_pp(it2->m_key, m) << " |-> " << sat::literal(it2->m_value) << "\n"; + for (auto kv : dep2asm) { + tout << mk_pp(kv.m_key, m) << " |-> " << sat::literal(kv.m_value) << "\n"; } - tout << "core: "; - for (unsigned i = 0; i < core.size(); ++i) { - tout << core[i] << " "; + tout << "asm2fml: "; + for (auto kv : asm2fml) { + tout << mk_pp(kv.m_key, m) << " |-> " << mk_pp(kv.m_value, m) << "\n"; } - tout << "\n"; + tout << "core: "; for (auto c : core) tout << c << " "; tout << "\n"; ); m_core.reset(); diff --git a/contrib/cmake/src/sat/tactic/CMakeLists.txt b/src/sat/tactic/CMakeLists.txt similarity index 80% rename from contrib/cmake/src/sat/tactic/CMakeLists.txt rename to src/sat/tactic/CMakeLists.txt index 74aeba8b9..fed6a89c8 100644 --- a/contrib/cmake/src/sat/tactic/CMakeLists.txt +++ b/src/sat/tactic/CMakeLists.txt @@ -6,4 +6,6 @@ z3_add_component(sat_tactic COMPONENT_DEPENDENCIES sat tactic + TACTIC_HEADERS + sat_tactic.h ) diff --git a/contrib/cmake/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/shell/CMakeLists.txt rename to src/shell/CMakeLists.txt diff --git a/src/shell/lp_frontend.cpp b/src/shell/lp_frontend.cpp index 8bed24c83..83f5e9e2e 100644 --- a/src/shell/lp_frontend.cpp +++ b/src/shell/lp_frontend.cpp @@ -17,7 +17,7 @@ Author: #include "gparams.h" #include -static lean::lp_solver* g_solver = 0; +static lp::lp_solver* g_solver = 0; static void display_statistics() { if (g_solver && g_solver->settings().print_statistics) { @@ -42,7 +42,7 @@ static void on_timeout() { } } -struct front_end_resource_limit : public lean::lp_resource_limit { +struct front_end_resource_limit : public lp::lp_resource_limit { reslimit& m_reslim; front_end_resource_limit(reslimit& lim): @@ -64,14 +64,14 @@ void run_solver(lp_params & params, char const * mps_file_name) { scoped_timer timer(timeout, &eh); std::string fn(mps_file_name); - lean::mps_reader reader(fn); + lp::mps_reader reader(fn); reader.set_message_stream(&std::cout); // can be redirected reader.read(); if (!reader.is_ok()) { std::cerr << "cannot process " << mps_file_name << std::endl; return; } - lean::lp_solver * solver = reader.create_solver(false); // false - to create the primal solver + lp::lp_solver * solver = reader.create_solver(false); // false - to create the primal solver solver->settings().set_resource_limit(lp_limit); g_solver = solver; if (params.min()) { @@ -80,10 +80,11 @@ void run_solver(lp_params & params, char const * mps_file_name) { solver->settings().set_message_ostream(&std::cout); solver->settings().report_frequency = params.rep_freq(); solver->settings().print_statistics = params.print_stats(); + solver->settings().simplex_strategy() = lp::simplex_strategy_enum::lu; solver->find_maximal_solution(); *(solver->settings().get_message_ostream()) << "status is " << lp_status_to_string(solver->get_status()) << std::endl; - if (solver->get_status() == lean::OPTIMAL) { + if (solver->get_status() == lp::lp_status::OPTIMAL) { if (params.min()) { solver->flip_costs(); } diff --git a/contrib/cmake/src/smt/CMakeLists.txt b/src/smt/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/smt/CMakeLists.txt rename to src/smt/CMakeLists.txt diff --git a/src/smt/cached_var_subst.cpp b/src/smt/cached_var_subst.cpp index 1db3aa0a6..c36eb6dd2 100644 --- a/src/smt/cached_var_subst.cpp +++ b/src/smt/cached_var_subst.cpp @@ -23,7 +23,7 @@ bool cached_var_subst::key_eq_proc::operator()(cached_var_subst::key * k1, cache return false; if (k1->m_num_bindings != k2->m_num_bindings) return false; - for (unsigned i = 0; i < k1->m_num_bindings; i++) + for (unsigned i = 0; i < k1->m_num_bindings; i++) if (k1->m_bindings[i] != k2->m_bindings[i]) return false; return true; @@ -49,9 +49,9 @@ void cached_var_subst::operator()(quantifier * qa, unsigned num_bindings, smt::e new_key->m_qa = qa; new_key->m_num_bindings = num_bindings; - for (unsigned i = 0; i < num_bindings; i++) + for (unsigned i = 0; i < num_bindings; i++) new_key->m_bindings[i] = bindings[i]->get_owner(); - + instances::entry * entry = m_instances.insert_if_not_there2(new_key, 0); if (entry->get_data().m_key != new_key) { SASSERT(entry->get_data().m_value != 0); @@ -60,20 +60,27 @@ void cached_var_subst::operator()(quantifier * qa, unsigned num_bindings, smt::e result = entry->get_data().m_value; return; } - - m_proc(qa->get_expr(), new_key->m_num_bindings, new_key->m_bindings, result); + + SASSERT(entry->get_data().m_value == 0); + try { + m_proc(qa->get_expr(), new_key->m_num_bindings, new_key->m_bindings, result); + } + catch (...) { + // CMW: The var_subst reducer was interrupted and m_instances is + // in an inconsistent state; we need to remove (new_key, 0). + m_instances.remove(new_key); + throw; // Throw on to smt::qi_queue/smt::solver. + } + // cache result entry->get_data().m_value = result; // remove key from cache m_new_keys[num_bindings] = 0; - + // increment reference counters m_refs.push_back(qa); for (unsigned i = 0; i < new_key->m_num_bindings; i++) m_refs.push_back(new_key->m_bindings[i]); m_refs.push_back(result); } - - - diff --git a/contrib/cmake/src/smt/params/CMakeLists.txt b/src/smt/params/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/smt/params/CMakeLists.txt rename to src/smt/params/CMakeLists.txt diff --git a/contrib/cmake/src/smt/proto_model/CMakeLists.txt b/src/smt/proto_model/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/smt/proto_model/CMakeLists.txt rename to src/smt/proto_model/CMakeLists.txt diff --git a/src/smt/qi_queue.cpp b/src/smt/qi_queue.cpp index 530d0ec88..70a3041d2 100644 --- a/src/smt/qi_queue.cpp +++ b/src/smt/qi_queue.cpp @@ -41,7 +41,7 @@ namespace smt { init_parser_vars(); m_vals.resize(15, 0.0f); } - + qi_queue::~qi_queue() { } @@ -50,7 +50,7 @@ namespace smt { if (!m_parser.parse_string(m_params.m_qi_cost.c_str(), m_cost_function)) { // it is not reasonable to abort here during the creation of smt::context just because an invalid option was provided. // throw default_exception("invalid cost function %s", m_params.m_qi_cost.c_str()); - + // using warning message instead warning_msg("invalid cost function '%s', switching to default one", m_params.m_qi_cost.c_str()); // Trying again with default function @@ -107,7 +107,7 @@ namespace smt { m_vals[SIZE] = static_cast(stat->get_size()); m_vals[DEPTH] = static_cast(stat->get_depth()); m_vals[GENERATION] = static_cast(generation); - m_vals[QUANT_GENERATION] = static_cast(stat->get_generation()); + m_vals[QUANT_GENERATION] = static_cast(stat->get_generation()); m_vals[WEIGHT] = static_cast(q->get_weight()); m_vals[VARS] = static_cast(q->get_num_decls()); m_vals[PATTERN_WIDTH] = pat ? static_cast(pat->get_num_args()) : 1.0f; @@ -118,7 +118,7 @@ namespace smt { TRACE("qi_queue_detail", for (unsigned i = 0; i < m_vals.size(); i++) { tout << m_vals[i] << " "; } tout << "\n";); return stat; } - + float qi_queue::get_cost(quantifier * q, app * pat, unsigned generation, unsigned min_top_generation, unsigned max_top_generation) { quantifier_stat * stat = set_values(q, pat, generation, min_top_generation, max_top_generation, 0); float r = m_evaluator(m_cost_function, m_vals.size(), m_vals.c_ptr()); @@ -132,11 +132,11 @@ namespace smt { float r = m_evaluator(m_new_gen_function, m_vals.size(), m_vals.c_ptr()); return static_cast(r); } - + void qi_queue::insert(fingerprint * f, app * pat, unsigned generation, unsigned min_top_generation, unsigned max_top_generation) { quantifier * q = static_cast(f->get_data()); float cost = get_cost(q, pat, generation, min_top_generation, max_top_generation); - TRACE("qi_queue_detail", + TRACE("qi_queue_detail", tout << "new instance of " << q->get_qid() << ", weight " << q->get_weight() << ", generation: " << generation << ", scope_level: " << m_context.get_scope_level() << ", cost: " << cost << "\n"; for (unsigned i = 0; i < f->get_num_args(); i++) { @@ -157,7 +157,7 @@ namespace smt { quantifier * qa = static_cast(f->get_data()); if (curr.m_cost <= m_eager_cost_threshold) { - instantiate(curr); + instantiate(curr); } else if (m_params.m_qi_promote_unsat && m_checker.is_unsat(qa->get_expr(), f->get_num_args(), f->get_args())) { // do not delay instances that produce a conflict. @@ -193,7 +193,7 @@ namespace smt { // This nasty side-effect may change the behavior of Z3. m_manager.trace_stream() << " #" << bindings[i]->get_owner_id(); } - + #endif if (m_manager.proofs_enabled()) m_manager.trace_stream() << " #" << proof_id; @@ -233,7 +233,7 @@ namespace smt { if (m_manager.is_true(s_instance)) { TRACE("checker", tout << "reduced to true, before:\n" << mk_ll_pp(instance, m_manager);); - if (m_manager.has_trace_stream()) + if (m_manager.has_trace_stream()) m_manager.trace_stream() << "[end-of-instance]\n"; return; @@ -278,7 +278,7 @@ namespace smt { pr1 = m_manager.mk_modus_ponens(qi_pr, rw); } else { - app * bare_s_lemma = m_manager.mk_or(m_manager.mk_not(q), s_instance); + app * bare_s_lemma = m_manager.mk_or(m_manager.mk_not(q), s_instance); proof * prs[1] = { pr.get() }; proof * cg = m_manager.mk_congruence(bare_lemma, bare_s_lemma, 1, prs); proof * rw = m_manager.mk_rewrite(bare_s_lemma, lemma); @@ -331,13 +331,13 @@ namespace smt { s.m_instances_lim = m_instances.size(); s.m_instantiated_trail_lim = m_instantiated_trail.size(); } - + void qi_queue::pop_scope(unsigned num_scopes) { unsigned new_lvl = m_scopes.size() - num_scopes; scope & s = m_scopes[new_lvl]; unsigned old_sz = s.m_instantiated_trail_lim; unsigned sz = m_instantiated_trail.size(); - for (unsigned i = old_sz; i < sz; i++) + for (unsigned i = old_sz; i < sz; i++) m_delayed_entries[m_instantiated_trail[i]].m_instantiated = false; m_instantiated_trail.shrink(old_sz); m_delayed_entries.shrink(s.m_delayed_entries_lim); @@ -359,7 +359,7 @@ namespace smt { } bool qi_queue::final_check_eh() { - TRACE("qi_queue", display_delayed_instances_stats(tout); tout << "lazy threshold: " << m_params.m_qi_lazy_threshold + TRACE("qi_queue", display_delayed_instances_stats(tout); tout << "lazy threshold: " << m_params.m_qi_lazy_threshold << ", scope_level: " << m_context.get_scope_level() << "\n";); if (m_params.m_qi_conservative_final_check) { bool init = false; @@ -379,7 +379,7 @@ namespace smt { entry & e = m_delayed_entries[i]; TRACE("qi_queue", tout << e.m_qb << ", cost: " << e.m_cost << ", instantiated: " << e.m_instantiated << "\n";); if (!e.m_instantiated && e.m_cost <= min_cost) { - TRACE("qi_queue", + TRACE("qi_queue", tout << "lazy quantifier instantiation...\n" << mk_pp(static_cast(e.m_qb->get_data()), m_manager) << "\ncost: " << e.m_cost << "\n";); result = false; m_instantiated_trail.push_back(i); @@ -389,13 +389,13 @@ namespace smt { } return result; } - + bool result = true; for (unsigned i = 0; i < m_delayed_entries.size(); i++) { entry & e = m_delayed_entries[i]; TRACE("qi_queue", tout << e.m_qb << ", cost: " << e.m_cost << ", instantiated: " << e.m_instantiated << "\n";); if (!e.m_instantiated && e.m_cost <= m_params.m_qi_lazy_threshold) { - TRACE("qi_queue", + TRACE("qi_queue", tout << "lazy quantifier instantiation...\n" << mk_pp(static_cast(e.m_qb->get_data()), m_manager) << "\ncost: " << e.m_cost << "\n";); result = false; m_instantiated_trail.push_back(i); @@ -443,7 +443,7 @@ namespace smt { quantifier * qa = *it2; delayed_qa_info info; qa2info.find(qa, info); - out << qa->get_qid() << ": " << info.m_num << " [" << info.m_min_cost << ", " << info.m_max_cost << "]\n"; + out << qa->get_qid() << ": " << info.m_num << " [" << info.m_min_cost << ", " << info.m_max_cost << "]\n"; } } @@ -482,6 +482,6 @@ namespace smt { } #endif } - + }; diff --git a/src/smt/smt_case_split_queue.cpp b/src/smt/smt_case_split_queue.cpp index 41a269820..c461b130b 100644 --- a/src/smt/smt_case_split_queue.cpp +++ b/src/smt/smt_case_split_queue.cpp @@ -51,9 +51,9 @@ namespace smt { if (!m_theory_var_priority.find(v2, p_v2)) { p_v2 = 0.0; } - // add clause activity - p_v1 += m_activity[v1]; - p_v2 += m_activity[v2]; + // add clause activity + p_v1 += m_activity[v1]; + p_v2 += m_activity[v2]; return p_v1 > p_v2; } }; @@ -82,6 +82,7 @@ namespace smt { virtual void mk_var_eh(bool_var v) { m_queue.reserve(v+1); + SASSERT(!m_queue.contains(v)); m_queue.insert(v); } @@ -130,10 +131,7 @@ namespace smt { virtual void display(std::ostream & out) { bool first = true; - bool_var_act_queue::const_iterator it = m_queue.begin(); - bool_var_act_queue::const_iterator end = m_queue.end(); - for (; it != end ; ++it) { - unsigned v = *it; + for (unsigned v : m_queue) { if (m_context.get_assignment(v) == l_undef) { if (first) { out << "remaining case-splits:\n"; @@ -143,8 +141,7 @@ namespace smt { } } if (!first) - out << "\n"; - + out << "\n"; } virtual ~act_case_split_queue() {}; @@ -166,11 +163,15 @@ namespace smt { act_case_split_queue::activity_increased_eh(v); if (m_queue.contains(v)) m_queue.decreased(v); + if (m_delayed_queue.contains(v)) + m_delayed_queue.decreased(v); } virtual void mk_var_eh(bool_var v) { m_queue.reserve(v+1); m_delayed_queue.reserve(v+1); + SASSERT(!m_delayed_queue.contains(v)); + SASSERT(!m_queue.contains(v)); if (m_context.is_searching()) m_delayed_queue.insert(v); else @@ -1099,8 +1100,6 @@ namespace smt { #endif GOAL_STOP(); - - //std::cout << "goal set, time " << m_goal_time.get_seconds() << "\n"; } void set_global_generation() diff --git a/src/smt/smt_conflict_resolution.cpp b/src/smt/smt_conflict_resolution.cpp index 8d90f9583..ade667e34 100644 --- a/src/smt/smt_conflict_resolution.cpp +++ b/src/smt/smt_conflict_resolution.cpp @@ -1405,6 +1405,7 @@ namespace smt { switch (js.get_kind()) { case b_justification::CLAUSE: { clause * cls = js.get_clause(); + TRACE("unsat_core_bug", m_ctx.display_clause_detail(tout, cls);); unsigned num_lits = cls->get_num_literals(); unsigned i = 0; if (consequent != false_literal) { @@ -1422,8 +1423,9 @@ namespace smt { process_antecedent_for_unsat_core(~l); } justification * js = cls->get_justification(); - if (js) + if (js) { process_justification_for_unsat_core(js); + } break; } case b_justification::BIN_CLAUSE: diff --git a/src/smt/smt_consequences.cpp b/src/smt/smt_consequences.cpp index 65272207e..20813602e 100644 --- a/src/smt/smt_consequences.cpp +++ b/src/smt/smt_consequences.cpp @@ -103,6 +103,7 @@ namespace smt { void context::justify(literal lit, index_set& s) { ast_manager& m = m_manager; + (void)m; b_justification js = get_justification(lit.var()); switch (js.get_kind()) { case b_justification::CLAUSE: { diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 48ea6849c..e6f7e1859 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -1826,6 +1826,7 @@ namespace smt { } void context::rescale_bool_var_activity() { + TRACE("case_split", tout << "rescale\n";); svector::iterator it = m_activity.begin(); svector::iterator end = m_activity.end(); for (; it != end; ++it) @@ -4345,10 +4346,9 @@ namespace smt { ); failure fl = get_last_search_failure(); if (fl == MEMOUT || fl == CANCELED || fl == TIMEOUT || fl == NUM_CONFLICTS || fl == RESOURCE_LIMIT) { - return; + TRACE("get_model", tout << "last search failure: " << fl << "\n";); } - - if (m_fparams.m_model || m_fparams.m_model_on_final_check || m_qmanager->model_based()) { + else if (m_fparams.m_model || m_fparams.m_model_on_final_check || m_qmanager->model_based()) { m_model_generator->reset(); m_proto_model = m_model_generator->mk_model(); m_qmanager->adjust_model(m_proto_model.get()); @@ -4359,6 +4359,9 @@ namespace smt { if (m_fparams.m_model_compact) m_proto_model->compress(); TRACE("mbqi_bug", tout << "after cleanup:\n"; model_pp(tout, *m_proto_model);); + } + else { + } } diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index ce81bb1cb..3c2dad061 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -1047,6 +1047,7 @@ namespace smt { if (act > ACTIVITY_LIMIT) rescale_bool_var_activity(); m_case_split_queue->activity_increased_eh(v); + TRACE("case_split", tout << "v" << v << " " << m_bvar_inc << " -> " << act << "\n";); } protected: diff --git a/src/smt/smt_internalizer.cpp b/src/smt/smt_internalizer.cpp index a0905cf3b..613d5e88d 100644 --- a/src/smt/smt_internalizer.cpp +++ b/src/smt/smt_internalizer.cpp @@ -1034,8 +1034,10 @@ namespace smt { lbool val = get_assignment(curr); switch(val) { case l_false: + TRACE("simplify_aux_clause_literals", display_literal(tout << get_assign_level(curr) << " " << get_scope_level() << " ", curr); tout << "\n"; ); simp_lits.push_back(~curr); - break; // ignore literal + break; // ignore literal + // fall through case l_undef: if (curr == ~prev) return false; // clause is equivalent to true diff --git a/src/smt/smt_quantifier.cpp b/src/smt/smt_quantifier.cpp index 10e2df988..1c8f94edf 100644 --- a/src/smt/smt_quantifier.cpp +++ b/src/smt/smt_quantifier.cpp @@ -135,7 +135,7 @@ namespace smt { m_qi_queue.insert(f, pat, max_generation, min_top_generation, max_top_generation); // TODO m_num_instances++; } - TRACE("quantifier", + TRACE("quantifier", tout << mk_pp(q, m()) << " "; for (unsigned i = 0; i < num_bindings; ++i) { tout << mk_pp(bindings[i]->get_owner(), m()) << " "; @@ -372,7 +372,7 @@ namespace smt { quantifier_manager_plugin * plugin = m_imp->m_plugin->mk_fresh(); m_imp->~imp(); m_imp = new (m_imp) imp(*this, ctx, p, plugin); - plugin->set_manager(*this); + plugin->set_manager(*this); } void quantifier_manager::display(std::ostream & out) const { diff --git a/src/smt/smt_quantifier.h b/src/smt/smt_quantifier.h index 6dcf20583..96af9909a 100644 --- a/src/smt/smt_quantifier.h +++ b/src/smt/smt_quantifier.h @@ -75,7 +75,7 @@ namespace smt { }; bool model_based() const; - bool mbqi_enabled(quantifier *q) const; // can mbqi instantiate this quantifier? + bool mbqi_enabled(quantifier *q) const; // can mbqi instantiate this quantifier? void adjust_model(proto_model * m); check_model_result check_model(proto_model * m, obj_map const & root2value); @@ -167,7 +167,7 @@ namespace smt { virtual void push() = 0; virtual void pop(unsigned num_scopes) = 0; - + }; }; diff --git a/contrib/cmake/src/smt/tactic/CMakeLists.txt b/src/smt/tactic/CMakeLists.txt similarity index 62% rename from contrib/cmake/src/smt/tactic/CMakeLists.txt rename to src/smt/tactic/CMakeLists.txt index b7525bda8..6187f9c18 100644 --- a/contrib/cmake/src/smt/tactic/CMakeLists.txt +++ b/src/smt/tactic/CMakeLists.txt @@ -5,4 +5,8 @@ z3_add_component(smt_tactic unit_subsumption_tactic.cpp COMPONENT_DEPENDENCIES smt + TACTIC_HEADERS + ctx_solver_simplify_tactic.h + smt_tactic.h + unit_subsumption_tactic.h ) diff --git a/src/smt/tactic/smt_tactic.cpp b/src/smt/tactic/smt_tactic.cpp index 9e3eddafa..64bae0a48 100644 --- a/src/smt/tactic/smt_tactic.cpp +++ b/src/smt/tactic/smt_tactic.cpp @@ -253,7 +253,7 @@ public: if (m_ctx->canceled()) { throw tactic_exception(Z3_CANCELED_MSG); } - if (m_fail_if_inconclusive) { + if (m_fail_if_inconclusive && !m_candidate_models) { std::stringstream strm; strm << "smt tactic failed to show goal to be sat/unsat " << m_ctx->last_failure_as_string(); throw tactic_exception(strm.str().c_str()); diff --git a/src/smt/theory_arith_aux.h b/src/smt/theory_arith_aux.h index 54b617152..f94de7eba 100644 --- a/src/smt/theory_arith_aux.h +++ b/src/smt/theory_arith_aux.h @@ -1458,7 +1458,7 @@ namespace smt { normalize_gain(min_gain.get_rational(), max_gain); } - if (is_int(x_i) && !max_gain.is_rational()) { + if (is_int(x_i) && !max_gain.is_int()) { max_gain = inf_numeral(floor(max_gain)); normalize_gain(min_gain.get_rational(), max_gain); } @@ -1483,7 +1483,7 @@ namespace smt { } } TRACE("opt", - tout << "v" << x_i << " a_ij " << a_ij << " " + tout << "v" << x_i << (is_int(x_i)?" int":" real") << " a_ij " << a_ij << " " << "min gain: " << min_gain << " " << "max gain: " << max_gain << " tighter: " << (is_tighter?"true":"false") << "\n";); @@ -1696,6 +1696,7 @@ namespace smt { if (lower(x_j)) tout << "lower x_j: " << lower_bound(x_j) << " "; tout << "value x_j: " << get_value(x_j) << "\n"; ); + pivot(x_i, x_j, a_ij, false); SASSERT(is_non_base(x_i)); diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index 5c652414a..bee744c34 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -1716,7 +1716,7 @@ namespace smt { CASSERT("arith", check_null_var_pos()); r1.save_var_pos(m_var_pos); - + // // loop over variables in row2, // add terms in row2 to row1. @@ -1769,7 +1769,7 @@ namespace smt { ADD_ROW(r_entry.m_coeff = it->m_coeff; r_entry.m_coeff *= coeff, r_entry.m_coeff += it->m_coeff * coeff); } - + r1.reset_var_pos(m_var_pos); CASSERT("arith", check_null_var_pos()); CASSERT("row_assignment_bug", valid_row_assignment(r1)); @@ -1778,7 +1778,7 @@ namespace smt { theory_var v = r1.get_base_var(); if (is_int(v) && !get_value(v).is_int()) gcd_test(r1); - } + } } /** @@ -1797,6 +1797,7 @@ namespace smt { SASSERT(!is_non_base(v)); add_row(r1, c, get_var_row(v), false); } + get_manager().limit().inc(sz); } // ----------------------------------- @@ -1852,6 +1853,7 @@ namespace smt { if (is_base(v) && !m_to_patch.contains(v) && (below_lower(v) || above_upper(v))) { m_to_patch.insert(v); } + get_manager().limit().inc(); } /** @@ -1928,6 +1930,8 @@ namespace smt { DIVIDE_ROW(it->m_coeff /= tmp); } + get_manager().limit().inc(r.size()); + set_var_row(x_i, -1); set_var_row(x_j, r_id); @@ -1937,7 +1941,7 @@ namespace smt { set_var_kind(x_i, NON_BASE); set_var_kind(x_j, BASE); - eliminate(x_j, apply_gcd_test); + eliminate(x_j, apply_gcd_test); CASSERT("arith", wf_rows()); CASSERT("arith", wf_columns()); @@ -1972,6 +1976,7 @@ namespace smt { int s_pos = -1; for (; it != end; ++it, ++i) { if (!it->is_dead()) { + unsigned r1_sz = m_rows[r_id].size(); if (it->m_row_id != static_cast(r_id)) { row & r2 = m_rows[it->m_row_id]; theory_var s2 = r2.m_base_var; @@ -1979,13 +1984,14 @@ namespace smt { a_kj = r2[it->m_row_idx].m_coeff; a_kj.neg(); add_row(it->m_row_id, a_kj, r_id, apply_gcd_test); + get_manager().limit().inc((r1_sz + r2.size()) * (a_kj.storage_size())); } } else { s_pos = i; } } - } + } CTRACE("eliminate", !Lazy && c.size() != 1, tout << "eliminating v" << x_i << ", Lazy: " << Lazy << ", c.size: " << c.size() << "\n"; display(tout);); diff --git a/src/smt/theory_arith_int.h b/src/smt/theory_arith_int.h index e6e9e863c..ca3a485c6 100644 --- a/src/smt/theory_arith_int.h +++ b/src/smt/theory_arith_int.h @@ -201,10 +201,12 @@ namespace smt { SASSERT(is_int(v)); SASSERT(!get_value(v).is_int()); m_stats.m_branches++; - TRACE("arith_int", tout << "branching v" << v << " = " << get_value(v) << "\n"; - display_var(tout, v);); numeral k = ceil(get_value(v)); rational _k = k.to_rational(); + TRACE("arith_int", tout << "branching v" << v << " = " << get_value(v) << "\n"; + display_var(tout, v); + tout << "k = " << k << ", _k = "<< _k << std::endl; + ); expr_ref bound(get_manager()); expr* e = get_enode(v)->get_owner(); bound = m_util.mk_ge(e, m_util.mk_numeral(_k, m_util.is_int(e))); diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index a075f3072..e9bb13b8e 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -37,8 +37,10 @@ Revision History: #include "util/nat_set.h" #include "util/lp/nra_solver.h" #include "tactic/filter_model_converter.h" +#include "math/polynomial/algebraic_numbers.h" +#include "math/polynomial/polynomial.h" -namespace lp { +namespace lp_api { enum bound_kind { lower_t, upper_t }; std::ostream& operator<<(std::ostream& out, bound_kind const& k) { @@ -52,13 +54,15 @@ namespace lp { class bound { smt::bool_var m_bv; smt::theory_var m_var; + bool m_is_int; rational m_value; bound_kind m_bound_kind; public: - bound(smt::bool_var bv, smt::theory_var v, rational const & val, bound_kind k): + bound(smt::bool_var bv, smt::theory_var v, bool is_int, rational const & val, bound_kind k): m_bv(bv), m_var(v), + m_is_int(is_int), m_value(val), m_bound_kind(k) { } @@ -66,11 +70,18 @@ namespace lp { smt::theory_var get_var() const { return m_var; } smt::bool_var get_bv() const { return m_bv; } bound_kind get_bound_kind() const { return m_bound_kind; } + bool is_int() const { return m_is_int; } rational const& get_value() const { return m_value; } inf_rational get_value(bool is_true) const { if (is_true) return inf_rational(m_value); // v >= value or v <= value - if (m_bound_kind == lower_t) return inf_rational(m_value, false); // v <= value - epsilon - return inf_rational(m_value, true); // v >= value + epsilon + if (m_is_int) { + if (m_bound_kind == lower_t) return inf_rational(m_value - rational::one()); // v <= value - 1 + return inf_rational(m_value + rational::one()); // v >= value + 1 + } + else { + if (m_bound_kind == lower_t) return inf_rational(m_value, false); // v <= value - epsilon + return inf_rational(m_value, true); // v >= value + epsilon + } } virtual std::ostream& display(std::ostream& out) const { return out << "v" << get_var() << " " << get_bound_kind() << " " << m_value; @@ -88,16 +99,13 @@ namespace lp { unsigned m_bounds_propagations; unsigned m_num_iterations; unsigned m_num_iterations_with_no_progress; - unsigned m_num_factorizations; unsigned m_need_to_solve_inf; unsigned m_fixed_eqs; unsigned m_conflicts; unsigned m_bound_propagations1; unsigned m_bound_propagations2; unsigned m_assert_diseq; - unsigned m_make_feasible; - unsigned m_max_cols; - unsigned m_max_rows; + unsigned m_gomory_cuts; stats() { reset(); } void reset() { memset(this, 0, sizeof(*this)); @@ -111,7 +119,7 @@ namespace lp { namespace smt { - typedef ptr_vector lp_bounds; + typedef ptr_vector lp_bounds; class theory_lra::imp { @@ -119,9 +127,6 @@ namespace smt { unsigned m_bounds_lim; unsigned m_asserted_qhead; unsigned m_asserted_atoms_lim; - unsigned m_delayed_terms_lim; - unsigned m_delayed_equalities_lim; - unsigned m_delayed_defs_lim; unsigned m_underspecified_lim; unsigned m_var_trail_lim; expr* m_not_handled; @@ -133,7 +138,7 @@ namespace smt { delayed_atom(unsigned b, bool t): m_bv(b), m_is_true(t) {} }; - class resource_limit : public lean::lp_resource_limit { + class resource_limit : public lp::lp_resource_limit { imp& m_imp; public: resource_limit(imp& i): m_imp(i) { } @@ -198,21 +203,13 @@ namespace smt { } }; - typedef vector> var_coeffs; - struct delayed_def { - vector m_coeffs; - svector m_vars; - rational m_coeff; - theory_var m_var; - delayed_def(svector const& vars, vector const& coeffs, rational const& r, theory_var v): - m_coeffs(coeffs), m_vars(vars), m_coeff(r), m_var(v) {} - }; + typedef vector> var_coeffs; - svector m_theory_var2var_index; // translate from theory variables to lar vars + svector m_theory_var2var_index; // translate from theory variables to lar vars svector m_var_index2theory_var; // reverse map from lp_solver variables to theory variables svector m_term_index2theory_var; // reverse map from lp_solver variables to theory variables var_coeffs m_left_side; // constraint left side - mutable std::unordered_map m_variable_values; // current model + mutable std::unordered_map m_variable_values; // current model enum constraint_source { inequality_source, @@ -225,18 +222,14 @@ namespace smt { svector m_equalities; // asserted rows corresponding to equalities. svector m_definitions; // asserted rows corresponding to definitions - bool m_delay_constraints; // configuration svector m_asserted_atoms; - app_ref_vector m_delayed_terms; - svector> m_delayed_equalities; - vector m_delayed_defs; expr* m_not_handled; ptr_vector m_underspecified; unsigned_vector m_var_trail; - vector > m_use_list; // bounds where variables are used. + vector > m_use_list; // bounds where variables are used. // attributes for incremental version: - u_map m_bool_var2bound; + u_map m_bool_var2bound; vector m_bounds; unsigned_vector m_unassigned_bounds; unsigned_vector m_bounds_trail; @@ -249,26 +242,44 @@ namespace smt { unsigned m_num_conflicts; + // non-linear arithmetic scoped_ptr m_nra; bool m_use_nra_model; + scoped_ptr m_a1, m_a2; + + // integer arithmetic + scoped_ptr m_lia; + struct var_value_eq { imp & m_th; var_value_eq(imp & th):m_th(th) {} - bool operator()(theory_var v1, theory_var v2) const { return m_th.get_ivalue(v1) == m_th.get_ivalue(v2) && m_th.is_int(v1) == m_th.is_int(v2); } + bool operator()(theory_var v1, theory_var v2) const { + if (m_th.is_int(v1) != m_th.is_int(v2)) { + return false; + } + return m_th.is_eq(v1, v2); + } }; struct var_value_hash { imp & m_th; var_value_hash(imp & th):m_th(th) {} - unsigned operator()(theory_var v) const { return (unsigned)std::hash()(m_th.get_ivalue(v)); } + unsigned operator()(theory_var v) const { + if (m_th.m_use_nra_model) { + return m_th.is_int(v); + } + else { + return (unsigned)std::hash()(m_th.get_ivalue(v)); + } + } }; int_hashtable m_model_eqs; svector m_scopes; - lp::stats m_stats; + lp_api::stats m_stats; arith_factory* m_factory; - scoped_ptr m_solver; + scoped_ptr m_solver; resource_limit m_resource_limit; lp_bounds m_new_bounds; @@ -284,14 +295,15 @@ namespace smt { void init_solver() { if (m_solver) return; lp_params lp(ctx().get_params()); - m_solver = alloc(lean::lar_solver); + m_solver = alloc(lp::lar_solver); m_theory_var2var_index.reset(); m_solver->settings().set_resource_limit(m_resource_limit); - m_solver->settings().simplex_strategy() = static_cast(lp.simplex_strategy()); + m_solver->settings().simplex_strategy() = static_cast(lp.simplex_strategy()); reset_variable_values(); m_solver->settings().bound_propagation() = BP_NONE != propagation_mode(); m_solver->set_propagate_bounds_on_pivoted_rows_mode(lp.bprop_on_pivoted_rows()); //m_solver->settings().set_ostream(0); + m_lia = alloc(lp::int_solver, m_solver.get()); } void ensure_nra() { @@ -305,11 +317,14 @@ namespace smt { void found_not_handled(expr* n) { + if (a.is_div0(n)) { + return; + } m_not_handled = n; if (is_app(n) && is_underspecified(to_app(n))) { + TRACE("arith", tout << "Unhandled: " << mk_pp(n, m) << "\n";); m_underspecified.push_back(to_app(n)); } - TRACE("arith", tout << "Unhandled: " << mk_pp(n, m) << "\n";); } bool is_numeral(expr* term, rational& r) { @@ -409,9 +424,6 @@ namespace smt { if (is_app(n)) { internalize_args(to_app(n)); } - if (a.is_int(n)) { - found_not_handled(n); - } theory_var v = mk_var(n); coeffs[vars.size()] = coeffs[index]; vars.push_back(v); @@ -446,7 +458,7 @@ namespace smt { r = rational::one(); rational r1; v = mk_var(t); - svector vars; + svector vars; ptr_vector todo; todo.push_back(t); while (!todo.empty()) { @@ -548,13 +560,13 @@ namespace smt { return v; } - lean::var_index get_var_index(theory_var v) { - lean::var_index result = UINT_MAX; + lp::var_index get_var_index(theory_var v) { + lp::var_index result = UINT_MAX; if (m_theory_var2var_index.size() > static_cast(v)) { result = m_theory_var2var_index[v]; } if (result == UINT_MAX) { - result = m_solver->add_var(v, false); + result = m_solver->add_var(v, is_int(v)); m_theory_var2var_index.setx(v, result, UINT_MAX); m_var_index2theory_var.setx(result, v, UINT_MAX); m_var_trail.push_back(v); @@ -590,40 +602,32 @@ namespace smt { } bool all_zeros(vector const& v) const { - for (unsigned i = 0; i < v.size(); ++i) { - if (!v[i].is_zero()) { + for (rational const& r : v) { + if (!r.is_zero()) { return false; } } return true; } - void add_eq_constraint(lean::constraint_index index, enode* n1, enode* n2) { + void add_eq_constraint(lp::constraint_index index, enode* n1, enode* n2) { m_constraint_sources.setx(index, equality_source, null_source); m_equalities.setx(index, enode_pair(n1, n2), enode_pair(0, 0)); ++m_stats.m_add_rows; } - void add_ineq_constraint(lean::constraint_index index, literal lit) { + void add_ineq_constraint(lp::constraint_index index, literal lit) { m_constraint_sources.setx(index, inequality_source, null_source); m_inequalities.setx(index, lit, null_literal); ++m_stats.m_add_rows; TRACE("arith", m_solver->print_constraint(index, tout); tout << "\n";); } - void add_def_constraint(lean::constraint_index index, theory_var v) { + void add_def_constraint(lp::constraint_index index, theory_var v) { m_constraint_sources.setx(index, definition_source, null_source); m_definitions.setx(index, v, null_theory_var); ++m_stats.m_add_rows; } - - void internalize_eq(delayed_def const& d) { - scoped_internalize_state st(*this); - st.vars().append(d.m_vars); - st.coeffs().append(d.m_coeffs); - init_left_side(st); - add_def_constraint(m_solver->add_constraint(m_left_side, lean::EQ, -d.m_coeff), d.m_var); - } void internalize_eq(theory_var v1, theory_var v2) { enode* n1 = get_enode(v1); @@ -634,7 +638,7 @@ namespace smt { st.coeffs().push_back(rational::one()); st.coeffs().push_back(rational::minus_one()); init_left_side(st); - add_eq_constraint(m_solver->add_constraint(m_left_side, lean::EQ, rational::zero()), n1, n2); + add_eq_constraint(m_solver->add_constraint(m_left_side, lp::EQ, rational::zero()), n1, n2); TRACE("arith", tout << "v" << v1 << " = " << "v" << v2 << ": " << mk_pp(n1->get_owner(), m) << " = " << mk_pp(n2->get_owner(), m) << "\n";); @@ -644,7 +648,7 @@ namespace smt { for (unsigned i = m_bounds_trail.size(); i > old_size; ) { --i; unsigned v = m_bounds_trail[i]; - lp::bound* b = m_bounds[v].back(); + lp_api::bound* b = m_bounds[v].back(); // del_use_lists(b); dealloc(b); m_bounds[v].pop_back(); @@ -687,7 +691,7 @@ namespace smt { else { init_left_side(st); theory_var v = mk_var(term); - lean::var_index vi = m_theory_var2var_index.get(v, UINT_MAX); + lp::var_index vi = m_theory_var2var_index.get(v, UINT_MAX); if (vi == UINT_MAX) { vi = m_solver->add_term(m_left_side, st.coeff()); m_theory_var2var_index.setx(v, vi, UINT_MAX); @@ -717,16 +721,14 @@ namespace smt { a(m), m_arith_eq_adapter(th, ap, a), m_internalize_head(0), - m_delay_constraints(false), - m_delayed_terms(m), m_not_handled(0), m_asserted_qhead(0), m_assume_eq_head(0), m_num_conflicts(0), + m_use_nra_model(false), m_model_eqs(DEFAULT_HASHTABLE_INITIAL_CAPACITY, var_value_hash(*this), var_value_eq(*this)), m_solver(0), - m_resource_limit(*this), - m_use_nra_model(false) { + m_resource_limit(*this) { } ~imp() { @@ -739,12 +741,8 @@ namespace smt { } bool internalize_atom(app * atom, bool gate_ctx) { - if (m_delay_constraints) { - return internalize_atom_lazy(atom, gate_ctx); - } - else { - return internalize_atom_strict(atom, gate_ctx); - } + return internalize_atom_strict(atom, gate_ctx); + } bool internalize_atom_strict(app * atom, bool gate_ctx) { @@ -753,22 +751,22 @@ namespace smt { ctx().set_var_theory(bv, get_id()); expr* n1, *n2; rational r; - lp::bound_kind k; + lp_api::bound_kind k; theory_var v = null_theory_var; if (a.is_le(atom, n1, n2) && is_numeral(n2, r) && is_app(n1)) { v = internalize_def(to_app(n1)); - k = lp::upper_t; + k = lp_api::upper_t; } else if (a.is_ge(atom, n1, n2) && is_numeral(n2, r) && is_app(n1)) { v = internalize_def(to_app(n1)); - k = lp::lower_t; + k = lp_api::lower_t; } else { TRACE("arith", tout << "Could not internalize " << mk_pp(atom, m) << "\n";); found_not_handled(atom); return true; } - lp::bound* b = alloc(lp::bound, bv, v, r, k); + lp_api::bound* b = alloc(lp_api::bound, bv, v, is_int(v), r, k); m_bounds[v].push_back(b); updt_unassigned_bounds(v, +1); m_bounds_trail.push_back(v); @@ -778,54 +776,11 @@ namespace smt { //add_use_lists(b); return true; } - - bool internalize_atom_lazy(app * atom, bool gate_ctx) { - SASSERT(!ctx().b_internalized(atom)); - bool_var bv = ctx().mk_bool_var(atom); - ctx().set_var_theory(bv, get_id()); - expr* n1, *n2; - rational r; - lp::bound_kind k; - theory_var v = null_theory_var; - scoped_internalize_state st(*this); - if (a.is_le(atom, n1, n2) && is_numeral(n2, r) && is_app(n1)) { - v = internalize_def(to_app(n1), st); - k = lp::upper_t; - } - else if (a.is_ge(atom, n1, n2) && is_numeral(n2, r) && is_app(n1)) { - v = internalize_def(to_app(n1), st); - k = lp::lower_t; - } - else { - TRACE("arith", tout << "Could not internalize " << mk_pp(atom, m) << "\n";); - found_not_handled(atom); - return true; - } - lp::bound* b = alloc(lp::bound, bv, v, r, k); - m_bounds[v].push_back(b); - updt_unassigned_bounds(v, +1); - m_bounds_trail.push_back(v); - m_bool_var2bound.insert(bv, b); - TRACE("arith", tout << "Internalized " << mk_pp(atom, m) << "\n";); - if (!is_unit_var(st) && m_bounds[v].size() == 1) { - m_delayed_defs.push_back(delayed_def(st.vars(), st.coeffs(), st.coeff(), v)); - } - return true; - } bool internalize_term(app * term) { if (ctx().e_internalized(term) && th.is_attached_to_var(ctx().get_enode(term))) { // skip } - else if (m_delay_constraints) { - scoped_internalize_state st(*this); - linearize_term(term, st); // ensure that a theory_var was created. - SASSERT(ctx().e_internalized(term)); - if(!th.is_attached_to_var(ctx().get_enode(term))) { - mk_var(term); - } - m_delayed_terms.push_back(term); - } else { internalize_def(term); } @@ -833,7 +788,7 @@ namespace smt { } void internalize_eq_eh(app * atom, bool_var) { - expr* lhs, *rhs; + expr* lhs = 0, *rhs = 0; VERIFY(m.is_eq(atom, lhs, rhs)); enode * n1 = get_enode(lhs); enode * n2 = get_enode(rhs); @@ -851,13 +806,8 @@ namespace smt { } void new_eq_eh(theory_var v1, theory_var v2) { - if (m_delay_constraints) { - m_delayed_equalities.push_back(std::make_pair(v1, v2)); - } - else { - // or internalize_eq(v1, v2); - m_arith_eq_adapter.new_eq_eh(v1, v2); - } + // or internalize_eq(v1, v2); + m_arith_eq_adapter.new_eq_eh(v1, v2); } bool use_diseqs() const { @@ -876,13 +826,10 @@ namespace smt { s.m_bounds_lim = m_bounds_trail.size(); s.m_asserted_qhead = m_asserted_qhead; s.m_asserted_atoms_lim = m_asserted_atoms.size(); - s.m_delayed_terms_lim = m_delayed_terms.size(); - s.m_delayed_equalities_lim = m_delayed_equalities.size(); - s.m_delayed_defs_lim = m_delayed_defs.size(); s.m_not_handled = m_not_handled; s.m_underspecified_lim = m_underspecified.size(); s.m_var_trail_lim = m_var_trail.size(); - if (!m_delay_constraints) m_solver->push(); + m_solver->push(); if (m_nra) m_nra->push(); } @@ -893,7 +840,7 @@ namespace smt { unsigned old_size = m_scopes.size() - num_scopes; del_bounds(m_scopes[old_size].m_bounds_lim); for (unsigned i = m_scopes[old_size].m_var_trail_lim; i < m_var_trail.size(); ++i) { - lean::var_index vi = m_theory_var2var_index[m_var_trail[i]]; + lp::var_index vi = m_theory_var2var_index[m_var_trail[i]]; if (m_solver->is_term(vi)) { unsigned ti = m_solver->adjust_term_index(vi); m_term_index2theory_var[ti] = UINT_MAX; @@ -904,15 +851,12 @@ namespace smt { m_theory_var2var_index[m_var_trail[i]] = UINT_MAX; } m_asserted_atoms.shrink(m_scopes[old_size].m_asserted_atoms_lim); - m_delayed_terms.shrink(m_scopes[old_size].m_delayed_terms_lim); - m_delayed_defs.shrink(m_scopes[old_size].m_delayed_defs_lim); - m_delayed_equalities.shrink(m_scopes[old_size].m_delayed_equalities_lim); m_asserted_qhead = m_scopes[old_size].m_asserted_qhead; m_underspecified.shrink(m_scopes[old_size].m_underspecified_lim); m_var_trail.shrink(m_scopes[old_size].m_var_trail_lim); m_not_handled = m_scopes[old_size].m_not_handled; m_scopes.resize(old_size); - if (!m_delay_constraints) m_solver->pop(num_scopes); + m_solver->pop(num_scopes); // VERIFY(l_false != make_feasible()); m_new_bounds.reset(); m_to_check.reset(); @@ -962,7 +906,7 @@ namespace smt { // to_int (to_real x) = x // to_real(to_int(x)) <= x < to_real(to_int(x)) + 1 void mk_to_int_axiom(app* n) { - expr* x, *y; + expr* x = 0, *y = 0; VERIFY (a.is_to_int(n, x)); if (a.is_to_real(x, y)) { mk_axiom(th.mk_eq(y, n, false)); @@ -978,7 +922,7 @@ namespace smt { // is_int(x) <=> to_real(to_int(x)) = x void mk_is_int_axiom(app* n) { - expr* x; + expr* x = 0; VERIFY(a.is_is_int(n, x)); literal eq = th.mk_eq(a.mk_to_real(a.mk_to_int(x)), x, false); literal is_int = ctx().get_literal(n); @@ -1087,38 +1031,58 @@ namespace smt { return m_solver->var_is_registered(m_theory_var2var_index[v]); } - lean::impq get_ivalue(theory_var v) const { - lean_assert(can_get_ivalue(v)); - lean::var_index vi = m_theory_var2var_index[v]; + mutable vector> m_todo_terms; + + lp::impq get_ivalue(theory_var v) const { + lp_assert(can_get_ivalue(v)); + lp::var_index vi = m_theory_var2var_index[v]; if (!m_solver->is_term(vi)) return m_solver->get_value(vi); - - const lean::lar_term& term = m_solver->get_term(vi); - lean::impq result(term.m_v); - for (const auto & i: term.m_coeffs) { - result += m_solver->get_value(i.first) * i.second; + m_todo_terms.push_back(std::make_pair(vi, rational::one())); + lp::impq result(0); + while (!m_todo_terms.empty()) { + vi = m_todo_terms.back().first; + rational coeff = m_todo_terms.back().second; + m_todo_terms.pop_back(); + if (m_solver->is_term(vi)) { + const lp::lar_term& term = m_solver->get_term(vi); + result += term.m_v * coeff; + for (const auto & i: term.m_coeffs) { + m_todo_terms.push_back(std::make_pair(i.first, coeff * i.second)); + } + } + else { + result += m_solver->get_value(vi) * coeff; + } } return result; } - rational get_value(theory_var v) const { if (!can_get_value(v)) return rational::zero(); - lean::var_index vi = m_theory_var2var_index[v]; + lp::var_index vi = m_theory_var2var_index[v]; if (m_variable_values.count(vi) > 0) { return m_variable_values[vi]; } - if (m_solver->is_term(vi)) { - const lean::lar_term& term = m_solver->get_term(vi); - rational result = term.m_v; - for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { - result += m_variable_values[i->first] * i->second; + m_todo_terms.push_back(std::make_pair(vi, rational::one())); + rational result(0); + while (!m_todo_terms.empty()) { + lp::var_index wi = m_todo_terms.back().first; + rational coeff = m_todo_terms.back().second; + m_todo_terms.pop_back(); + if (m_solver->is_term(wi)) { + const lp::lar_term& term = m_solver->get_term(wi); + result += term.m_v * coeff; + for (auto const& i : term.m_coeffs) { + m_todo_terms.push_back(std::make_pair(i.first, i.second * coeff)); + } + } + else { + result += m_variable_values[wi] * coeff; } - m_variable_values[vi] = result; - return result; } - UNREACHABLE(); - return m_variable_values[vi]; + m_variable_values[vi] = result; + return result; } void init_variable_values() { @@ -1132,7 +1096,7 @@ namespace smt { } bool assume_eqs() { - svector vars; + svector vars; theory_var sz = static_cast(th.get_num_vars()); for (theory_var v = 0; v < sz; ++v) { if (th.is_relevant_and_shared(get_enode(v))) { @@ -1150,7 +1114,9 @@ namespace smt { } tout << "\n"; ); - m_solver->random_update(vars.size(), vars.c_ptr()); + if (!m_use_nra_model) { + m_solver->random_update(vars.size(), vars.c_ptr()); + } m_model_eqs.reset(); TRACE("arith", display(tout);); @@ -1200,40 +1166,33 @@ namespace smt { enode* n2 = get_enode(v2); m_assume_eq_head++; CTRACE("arith", - get_ivalue(v1) == get_ivalue(v2) && n1->get_root() != n2->get_root(), + is_eq(v1, v2) && n1->get_root() != n2->get_root(), tout << "assuming eq: v" << v1 << " = v" << v2 << "\n";); - if (get_ivalue(v1) == get_ivalue(v2) && n1->get_root() != n2->get_root() && th.assume_eq(n1, n2)) { + if (is_eq(v1, v2) && n1->get_root() != n2->get_root() && th.assume_eq(n1, n2)) { return true; } } return false; } + bool is_eq(theory_var v1, theory_var v2) { + if (m_use_nra_model) { + return m_nra->am().eq(nl_value(v1, *m_a1), nl_value(v2, *m_a2)); + } + else { + return get_ivalue(v1) == get_ivalue(v2); + } + } + bool has_delayed_constraints() const { - return !(m_asserted_atoms.empty() && m_delayed_terms.empty() && m_delayed_equalities.empty()); + return !m_asserted_atoms.empty(); } final_check_status final_check_eh() { + TRACE("lar_solver", tout << "ddd=" <<++lp::lp_settings::ddd << std::endl;); + m_use_nra_model = false; lbool is_sat = l_true; - if (m_delay_constraints) { - init_solver(); - for (unsigned i = 0; i < m_asserted_atoms.size(); ++i) { - bool_var bv = m_asserted_atoms[i].m_bv; - assert_bound(bv, m_asserted_atoms[i].m_is_true, *m_bool_var2bound.find(bv)); - } - for (unsigned i = 0; i < m_delayed_terms.size(); ++i) { - internalize_def(m_delayed_terms[i].get()); - } - for (unsigned i = 0; i < m_delayed_defs.size(); ++i) { - internalize_eq(m_delayed_defs[i]); - } - for (unsigned i = 0; i < m_delayed_equalities.size(); ++i) { - std::pair const& eq = m_delayed_equalities[i]; - internalize_eq(eq.first, eq.second); - } - is_sat = make_feasible(); - } - else if (m_solver->get_status() != lean::lp_status::OPTIMAL) { + if (m_solver->get_status() != lp::lp_status::OPTIMAL) { is_sat = make_feasible(); } final_check_status st = FC_DONE; @@ -1253,6 +1212,7 @@ namespace smt { case l_false: return FC_CONTINUE; case l_undef: + TRACE("arith", tout << "check-lia giveup\n";); st = FC_GIVEUP; break; } @@ -1263,29 +1223,87 @@ namespace smt { case l_false: return FC_CONTINUE; case l_undef: + TRACE("arith", tout << "check-nra giveup\n";); st = FC_GIVEUP; break; } - if (m_not_handled != 0) { + if (m_not_handled != 0) { + TRACE("arith", tout << "unhandled operator " << mk_pp(m_not_handled, m) << "\n";); st = FC_GIVEUP; } - + return st; case l_false: set_conflict(); return FC_CONTINUE; case l_undef: + TRACE("arith", tout << "check feasiable is undef\n";); return m.canceled() ? FC_CONTINUE : FC_GIVEUP; default: UNREACHABLE(); break; } + TRACE("arith", tout << "default giveup\n";); return FC_GIVEUP; } + // create a bound atom representing term <= k + app_ref mk_bound(lp::lar_term const& term, rational const& k) { + SASSERT(k.is_int()); + app_ref t = mk_term(term, true); + app_ref atom(a.mk_le(t, a.mk_numeral(k, true)), m); + TRACE("arith", tout << atom << "\n"; + m_solver->print_term(term, tout << "bound atom: "); tout << " <= " << k << "\n"; + display(tout); + ); + ctx().internalize(atom, true); + ctx().mark_as_relevant(atom.get()); + return atom; + } + lbool check_lia() { if (m.canceled()) return l_undef; - return l_true; + lp::lar_term term; + lp::mpq k; + lp::explanation ex; // TBD, this should be streamlined accross different explanations + switch(m_lia->check(term, k, ex)) { + case lp::lia_move::ok: + return l_true; + case lp::lia_move::branch: { + (void)mk_bound(term, k); + // branch on term <= k + // at this point we have a new unassigned atom that the + // SAT core assigns a value to + return l_false; + } + case lp::lia_move::cut: { + ++m_stats.m_gomory_cuts; + // m_explanation implies term <= k + app_ref b = mk_bound(term, k); + m_eqs.reset(); + m_core.reset(); + m_params.reset(); + for (auto const& ev : ex.m_explanation) { + if (!ev.first.is_zero()) { + set_evidence(ev.second); + } + } + assign(literal(ctx().get_bool_var(b), false)); + return l_false; + } + case lp::lia_move::conflict: + // ex contains unsat core + m_explanation = ex.m_explanation; + set_conflict1(); + return l_false; + case lp::lia_move::give_up: + TRACE("arith", tout << "lia giveup\n";); + return l_undef; + default: + UNREACHABLE(); + } + UNREACHABLE(); + return l_undef; } lbool check_nra() { @@ -1293,15 +1311,22 @@ namespace smt { if (m.canceled()) return l_undef; if (!m_nra) return l_true; if (!m_nra->need_check()) return l_true; + m_a1 = 0; m_a2 = 0; lbool r = m_nra->check(m_explanation); + m_a1 = alloc(scoped_anum, m_nra->am()); + m_a2 = alloc(scoped_anum, m_nra->am()); switch (r) { case l_false: set_conflict1(); break; case l_true: m_use_nra_model = true; - // TBD: check equalities + if (assume_eqs()) { + return l_false; + } break; + case l_undef: + TRACE("arith", tout << "nra-undef\n";); default: break; } @@ -1376,21 +1401,20 @@ namespace smt { #else propagate_bound(bv, is_true, b); #endif - if (!m_delay_constraints) { - lp::bound& b = *m_bool_var2bound.find(bv); - assert_bound(bv, is_true, b); - } + lp_api::bound& b = *m_bool_var2bound.find(bv); + assert_bound(bv, is_true, b); + ++m_asserted_qhead; } - if (m_delay_constraints || ctx().inconsistent()) { + if (ctx().inconsistent()) { m_to_check.reset(); return; } /*for (; qhead < m_asserted_atoms.size() && !ctx().inconsistent(); ++qhead) { bool_var bv = m_asserted_atoms[qhead].m_bv; bool is_true = m_asserted_atoms[qhead].m_is_true; - lp::bound& b = *m_bool_var2bound.find(bv); + lp_api::bound& b = *m_bool_var2bound.find(bv); propagate_bound_compound(bv, is_true, b); }*/ @@ -1416,14 +1440,16 @@ namespace smt { return; } int num_of_p = m_solver->settings().st().m_num_of_implied_bounds; + (void)num_of_p; local_bound_propagator bp(*this); m_solver->propagate_bounds_for_touched_rows(bp); if (m.canceled()) { return; } int new_num_of_p = m_solver->settings().st().m_num_of_implied_bounds; + (void)new_num_of_p; CTRACE("arith", new_num_of_p > num_of_p, tout << "found " << new_num_of_p << " implied bounds\n";); - if (m_solver->get_status() == lean::lp_status::INFEASIBLE) { + if (m_solver->get_status() == lp::lp_status::INFEASIBLE) { set_conflict(); } else { @@ -1433,7 +1459,7 @@ namespace smt { } } - bool bound_is_interesting(unsigned vi, lean::lconstraint_kind kind, const rational & bval) const { + bool bound_is_interesting(unsigned vi, lp::lconstraint_kind kind, const rational & bval) const { theory_var v; if (m_solver->is_term(vi)) { v = m_term_index2theory_var.get(m_solver->adjust_term_index(vi), null_theory_var); @@ -1450,7 +1476,7 @@ namespace smt { } lp_bounds const& bounds = m_bounds[v]; for (unsigned i = 0; i < bounds.size(); ++i) { - lp::bound* b = bounds[i]; + lp_api::bound* b = bounds[i]; if (ctx().get_assignment(b->get_bv()) != l_undef) { continue; } @@ -1463,11 +1489,11 @@ namespace smt { return false; } - struct local_bound_propagator: public lean::bound_propagator { + struct local_bound_propagator: public lp::bound_propagator { imp & m_imp; local_bound_propagator(imp& i) : bound_propagator(*i.m_solver), m_imp(i) {} - bool bound_is_interesting(unsigned j, lean::lconstraint_kind kind, const rational & v) { + bool bound_is_interesting(unsigned j, lp::lconstraint_kind kind, const rational & v) { return m_imp.bound_is_interesting(j, kind, v); } @@ -1477,10 +1503,10 @@ namespace smt { }; - void propagate_lp_solver_bound(lean::implied_bound& be) { + void propagate_lp_solver_bound(lp::implied_bound& be) { theory_var v; - lean::var_index vi = be.m_j; + lp::var_index vi = be.m_j; if (m_solver->is_term(vi)) { v = m_term_index2theory_var.get(m_solver->adjust_term_index(vi), null_theory_var); } @@ -1501,7 +1527,7 @@ namespace smt { lp_bounds const& bounds = m_bounds[v]; bool first = true; for (unsigned i = 0; i < bounds.size(); ++i) { - lp::bound* b = bounds[i]; + lp_api::bound* b = bounds[i]; if (ctx().get_assignment(b->get_bv()) != l_undef) { continue; } @@ -1544,8 +1570,8 @@ namespace smt { SASSERT(validate_assign(lit)); if (m_core.size() < small_lemma_size() && m_eqs.empty()) { m_core2.reset(); - for (unsigned i = 0; i < m_core.size(); ++i) { - m_core2.push_back(~m_core[i]); + for (auto const& c : m_core) { + m_core2.push_back(~c); } m_core2.push_back(lit); justification * js = 0; @@ -1564,28 +1590,28 @@ namespace smt { } } - literal is_bound_implied(lean::lconstraint_kind k, rational const& value, lp::bound const& b) const { - if ((k == lean::LE || k == lean::LT) && b.get_bound_kind() == lp::upper_t && value <= b.get_value()) { + literal is_bound_implied(lp::lconstraint_kind k, rational const& value, lp_api::bound const& b) const { + if ((k == lp::LE || k == lp::LT) && b.get_bound_kind() == lp_api::upper_t && value <= b.get_value()) { // v <= value <= b.get_value() => v <= b.get_value() return literal(b.get_bv(), false); } - if ((k == lean::GE || k == lean::GT) && b.get_bound_kind() == lp::lower_t && b.get_value() <= value) { + if ((k == lp::GE || k == lp::GT) && b.get_bound_kind() == lp_api::lower_t && b.get_value() <= value) { // b.get_value() <= value <= v => b.get_value() <= v return literal(b.get_bv(), false); } - if (k == lean::LE && b.get_bound_kind() == lp::lower_t && value < b.get_value()) { + if (k == lp::LE && b.get_bound_kind() == lp_api::lower_t && value < b.get_value()) { // v <= value < b.get_value() => v < b.get_value() return literal(b.get_bv(), true); } - if (k == lean::LT && b.get_bound_kind() == lp::lower_t && value <= b.get_value()) { + if (k == lp::LT && b.get_bound_kind() == lp_api::lower_t && value <= b.get_value()) { // v < value <= b.get_value() => v < b.get_value() return literal(b.get_bv(), true); } - if (k == lean::GE && b.get_bound_kind() == lp::upper_t && b.get_value() < value) { + if (k == lp::GE && b.get_bound_kind() == lp_api::upper_t && b.get_value() < value) { // b.get_value() < value <= v => b.get_value() < v return literal(b.get_bv(), true); } - if (k == lean::GT && b.get_bound_kind() == lp::upper_t && b.get_value() <= value) { + if (k == lp::GT && b.get_bound_kind() == lp_api::upper_t && b.get_value() <= value) { // b.get_value() <= value < v => b.get_value() < v return literal(b.get_bv(), true); } @@ -1593,7 +1619,7 @@ namespace smt { return null_literal; } - void mk_bound_axioms(lp::bound& b) { + void mk_bound_axioms(lp_api::bound& b) { if (!ctx().is_searching()) { // // NB. We make an assumption that user push calls propagation @@ -1604,19 +1630,19 @@ namespace smt { return; } theory_var v = b.get_var(); - lp::bound_kind kind1 = b.get_bound_kind(); + lp_api::bound_kind kind1 = b.get_bound_kind(); rational const& k1 = b.get_value(); lp_bounds & bounds = m_bounds[v]; - lp::bound* end = 0; - lp::bound* lo_inf = end, *lo_sup = end; - lp::bound* hi_inf = end, *hi_sup = end; + lp_api::bound* end = 0; + lp_api::bound* lo_inf = end, *lo_sup = end; + lp_api::bound* hi_inf = end, *hi_sup = end; for (unsigned i = 0; i < bounds.size(); ++i) { - lp::bound& other = *bounds[i]; + lp_api::bound& other = *bounds[i]; if (&other == &b) continue; if (b.get_bv() == other.get_bv()) continue; - lp::bound_kind kind2 = other.get_bound_kind(); + lp_api::bound_kind kind2 = other.get_bound_kind(); rational const& k2 = other.get_value(); if (k1 == k2 && kind1 == kind2) { // the bounds are equivalent. @@ -1624,7 +1650,7 @@ namespace smt { } SASSERT(k1 != k2 || kind1 != kind2); - if (kind2 == lp::lower_t) { + if (kind2 == lp_api::lower_t) { if (k2 < k1) { if (lo_inf == end || k2 > lo_inf->get_value()) { lo_inf = &other; @@ -1650,14 +1676,14 @@ namespace smt { } - void mk_bound_axiom(lp::bound& b1, lp::bound& b2) { + void mk_bound_axiom(lp_api::bound& b1, lp_api::bound& b2) { theory_var v = b1.get_var(); literal l1(b1.get_bv()); literal l2(b2.get_bv()); rational const& k1 = b1.get_value(); rational const& k2 = b2.get_value(); - lp::bound_kind kind1 = b1.get_bound_kind(); - lp::bound_kind kind2 = b2.get_bound_kind(); + lp_api::bound_kind kind1 = b1.get_bound_kind(); + lp_api::bound_kind kind2 = b2.get_bound_kind(); bool v_is_int = is_int(v); SASSERT(v == b2.get_var()); if (k1 == k2 && kind1 == kind2) return; @@ -1665,8 +1691,8 @@ namespace smt { parameter coeffs[3] = { parameter(symbol("farkas")), parameter(rational(1)), parameter(rational(1)) }; - if (kind1 == lp::lower_t) { - if (kind2 == lp::lower_t) { + if (kind1 == lp_api::lower_t) { + if (kind2 == lp_api::lower_t) { if (k2 <= k1) { mk_clause(~l1, l2, 3, coeffs); } @@ -1687,7 +1713,7 @@ namespace smt { } } } - else if (kind2 == lp::lower_t) { + else if (kind2 == lp_api::lower_t) { if (k1 >= k2) { // k1 >= lo_inf, k1 >= x or lo_inf <= x mk_clause(l1, l2, 3, coeffs); @@ -1745,21 +1771,21 @@ namespace smt { iterator begin1 = occs.begin(); iterator begin2 = occs.begin(); iterator end = occs.end(); - begin1 = first(lp::lower_t, begin1, end); - begin2 = first(lp::upper_t, begin2, end); + begin1 = first(lp_api::lower_t, begin1, end); + begin2 = first(lp_api::upper_t, begin2, end); iterator lo_inf = begin1, lo_sup = begin1; iterator hi_inf = begin2, hi_sup = begin2; iterator lo_inf1 = begin1, lo_sup1 = begin1; iterator hi_inf1 = begin2, hi_sup1 = begin2; bool flo_inf, fhi_inf, flo_sup, fhi_sup; - ptr_addr_hashtable visited; + ptr_addr_hashtable visited; for (unsigned i = 0; i < atoms.size(); ++i) { - lp::bound* a1 = atoms[i]; - lo_inf1 = next_inf(a1, lp::lower_t, lo_inf, end, flo_inf); - hi_inf1 = next_inf(a1, lp::upper_t, hi_inf, end, fhi_inf); - lo_sup1 = next_sup(a1, lp::lower_t, lo_sup, end, flo_sup); - hi_sup1 = next_sup(a1, lp::upper_t, hi_sup, end, fhi_sup); + lp_api::bound* a1 = atoms[i]; + lo_inf1 = next_inf(a1, lp_api::lower_t, lo_inf, end, flo_inf); + hi_inf1 = next_inf(a1, lp_api::upper_t, hi_inf, end, fhi_inf); + lo_sup1 = next_sup(a1, lp_api::lower_t, lo_sup, end, flo_sup); + hi_sup1 = next_sup(a1, lp_api::upper_t, hi_sup, end, fhi_sup); if (lo_inf1 != end) lo_inf = lo_inf1; if (lo_sup1 != end) lo_sup = lo_sup1; if (hi_inf1 != end) hi_inf = hi_inf1; @@ -1778,24 +1804,24 @@ namespace smt { } struct compare_bounds { - bool operator()(lp::bound* a1, lp::bound* a2) const { return a1->get_value() < a2->get_value(); } + bool operator()(lp_api::bound* a1, lp_api::bound* a2) const { return a1->get_value() < a2->get_value(); } }; lp_bounds::iterator first( - lp::bound_kind kind, + lp_api::bound_kind kind, iterator it, iterator end) { for (; it != end; ++it) { - lp::bound* a = *it; + lp_api::bound* a = *it; if (a->get_bound_kind() == kind) return it; } return end; } lp_bounds::iterator next_inf( - lp::bound* a1, - lp::bound_kind kind, + lp_api::bound* a1, + lp_api::bound_kind kind, iterator it, iterator end, bool& found_compatible) { @@ -1803,7 +1829,7 @@ namespace smt { iterator result = end; found_compatible = false; for (; it != end; ++it) { - lp::bound * a2 = *it; + lp_api::bound * a2 = *it; if (a1 == a2) continue; if (a2->get_bound_kind() != kind) continue; rational const & k2(a2->get_value()); @@ -1819,15 +1845,15 @@ namespace smt { } lp_bounds::iterator next_sup( - lp::bound* a1, - lp::bound_kind kind, + lp_api::bound* a1, + lp_api::bound_kind kind, iterator it, iterator end, bool& found_compatible) { rational const & k1(a1->get_value()); found_compatible = false; for (; it != end; ++it) { - lp::bound * a2 = *it; + lp_api::bound * a2 = *it; if (a1 == a2) continue; if (a2->get_bound_kind() != kind) continue; rational const & k2(a2->get_value()); @@ -1841,7 +1867,7 @@ namespace smt { void propagate_basic_bounds() { for (auto const& bv : m_to_check) { - lp::bound& b = *m_bool_var2bound.find(bv); + lp_api::bound& b = *m_bool_var2bound.find(bv); propagate_bound(bv, ctx().get_assignment(bv) == l_true, b); if (ctx().inconsistent()) break; @@ -1856,11 +1882,11 @@ namespace smt { // x <= hi -> x <= hi' // x <= hi -> ~(x >= hi') - void propagate_bound(bool_var bv, bool is_true, lp::bound& b) { + void propagate_bound(bool_var bv, bool is_true, lp_api::bound& b) { if (BP_NONE == propagation_mode()) { return; } - lp::bound_kind k = b.get_bound_kind(); + lp_api::bound_kind k = b.get_bound_kind(); theory_var v = b.get_var(); inf_rational val = b.get_value(is_true); lp_bounds const& bounds = m_bounds[v]; @@ -1870,12 +1896,12 @@ namespace smt { literal lit1(bv, !is_true); literal lit2 = null_literal; - bool find_glb = (is_true == (k == lp::lower_t)); + bool find_glb = (is_true == (k == lp_api::lower_t)); if (find_glb) { rational glb; - lp::bound* lb = 0; + lp_api::bound* lb = 0; for (unsigned i = 0; i < bounds.size(); ++i) { - lp::bound* b2 = bounds[i]; + lp_api::bound* b2 = bounds[i]; if (b2 == &b) continue; rational const& val2 = b2->get_value(); if ((is_true ? val2 < val : val2 <= val) && (!lb || glb < val2)) { @@ -1884,14 +1910,14 @@ namespace smt { } } if (!lb) return; - bool sign = lb->get_bound_kind() != lp::lower_t; + bool sign = lb->get_bound_kind() != lp_api::lower_t; lit2 = literal(lb->get_bv(), sign); } else { rational lub; - lp::bound* ub = 0; + lp_api::bound* ub = 0; for (unsigned i = 0; i < bounds.size(); ++i) { - lp::bound* b2 = bounds[i]; + lp_api::bound* b2 = bounds[i]; if (b2 == &b) continue; rational const& val2 = b2->get_value(); if ((is_true ? val < val2 : val <= val2) && (!ub || val2 < lub)) { @@ -1900,7 +1926,7 @@ namespace smt { } } if (!ub) return; - bool sign = ub->get_bound_kind() != lp::upper_t; + bool sign = ub->get_bound_kind() != lp_api::upper_t; lit2 = literal(ub->get_bv(), sign); } TRACE("arith", @@ -1920,30 +1946,54 @@ namespace smt { ++m_stats.m_bounds_propagations; } - void add_use_lists(lp::bound* b) { + svector m_todo_vars; + + void add_use_lists(lp_api::bound* b) { theory_var v = b->get_var(); - lean::var_index vi = get_var_index(v); - if (m_solver->is_term(vi)) { - lean::lar_term const& term = m_solver->get_term(vi); + lp::var_index vi = get_var_index(v); + if (!m_solver->is_term(vi)) { + return; + } + m_todo_vars.push_back(vi); + while (!m_todo_vars.empty()) { + vi = m_todo_vars.back(); + m_todo_vars.pop_back(); + lp::lar_term const& term = m_solver->get_term(vi); for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { - lean::var_index wi = i->first; - unsigned w = m_var_index2theory_var[wi]; - m_use_list.reserve(w + 1, ptr_vector()); - m_use_list[w].push_back(b); + lp::var_index wi = i->first; + if (m_solver->is_term(wi)) { + m_todo_vars.push_back(wi); + } + else { + unsigned w = m_var_index2theory_var[wi]; + m_use_list.reserve(w + 1, ptr_vector()); + m_use_list[w].push_back(b); + } } } } - void del_use_lists(lp::bound* b) { + void del_use_lists(lp_api::bound* b) { theory_var v = b->get_var(); - lean::var_index vi = m_theory_var2var_index[v]; - if (m_solver->is_term(vi)) { - lean::lar_term const& term = m_solver->get_term(vi); + lp::var_index vi = m_theory_var2var_index[v]; + if (!m_solver->is_term(vi)) { + return; + } + m_todo_vars.push_back(vi); + while (!m_todo_vars.empty()) { + vi = m_todo_vars.back(); + m_todo_vars.pop_back(); + lp::lar_term const& term = m_solver->get_term(vi); for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { - lean::var_index wi = i->first; - unsigned w = m_var_index2theory_var[wi]; - SASSERT(m_use_list[w].back() == b); - m_use_list[w].pop_back(); + lp::var_index wi = i->first; + if (m_solver->is_term(wi)) { + m_todo_vars.push_back(wi); + } + else { + unsigned w = m_var_index2theory_var[wi]; + SASSERT(m_use_list[w].back() == b); + m_use_list[w].pop_back(); + } } } } @@ -1954,7 +2004,7 @@ namespace smt { // have been assigned we may know the truth value of the inequality by using simple // bounds propagation. // - void propagate_bound_compound(bool_var bv, bool is_true, lp::bound& b) { + void propagate_bound_compound(bool_var bv, bool is_true, lp_api::bound& b) { theory_var v = b.get_var(); TRACE("arith", tout << mk_pp(get_owner(v), m) << "\n";); if (static_cast(v) >= m_use_list.size()) { @@ -1970,7 +2020,7 @@ namespace smt { // x >= 0, y >= 1 -> x + y >= 1 // x <= 0, y <= 2 -> x + y <= 2 literal lit = null_literal; - if (lp::lower_t == vb->get_bound_kind()) { + if (lp_api::lower_t == vb->get_bound_kind()) { if (get_glb(*vb, r) && r >= vb->get_value()) { // vb is assigned true lit = literal(vb->get_bv(), false); } @@ -2004,32 +2054,35 @@ namespace smt { } } - bool get_lub(lp::bound const& b, inf_rational& lub) { + bool get_lub(lp_api::bound const& b, inf_rational& lub) { return get_bound(b, lub, true); } - bool get_glb(lp::bound const& b, inf_rational& glb) { + bool get_glb(lp_api::bound const& b, inf_rational& glb) { return get_bound(b, glb, false); } - std::ostream& display_bound(std::ostream& out, lp::bound const& b) { + std::ostream& display_bound(std::ostream& out, lp_api::bound const& b) { return out << mk_pp(ctx().bool_var2expr(b.get_bv()), m); } - bool get_bound(lp::bound const& b, inf_rational& r, bool is_lub) { + bool get_bound(lp_api::bound const& b, inf_rational& r, bool is_lub) { m_core.reset(); m_eqs.reset(); m_params.reset(); r.reset(); theory_var v = b.get_var(); - lean::var_index vi = m_theory_var2var_index[v]; + lp::var_index vi = m_theory_var2var_index[v]; SASSERT(m_solver->is_term(vi)); - lean::lar_term const& term = m_solver->get_term(vi); + lp::lar_term const& term = m_solver->get_term(vi); for (auto const coeff : term.m_coeffs) { - lean::var_index wi = coeff.first; - lean::constraint_index ci; + lp::var_index wi = coeff.first; + lp::constraint_index ci; rational value; bool is_strict; + if (m_solver->is_term(wi)) { + return false; + } if (coeff.second.is_neg() == is_lub) { // -3*x ... <= lub based on lower bound for x. if (!m_solver->has_lower_bound(wi, ci, value, is_strict)) { @@ -2054,31 +2107,40 @@ namespace smt { return true; } - void assert_bound(bool_var bv, bool is_true, lp::bound& b) { - if (m_solver->get_status() == lean::lp_status::INFEASIBLE) { + void assert_bound(bool_var bv, bool is_true, lp_api::bound& b) { + if (m_solver->get_status() == lp::lp_status::INFEASIBLE) { return; } scoped_internalize_state st(*this); st.vars().push_back(b.get_var()); st.coeffs().push_back(rational::one()); init_left_side(st); - lean::lconstraint_kind k = lean::EQ; + lp::lconstraint_kind k = lp::EQ; + bool is_int = b.is_int(); switch (b.get_bound_kind()) { - case lp::lower_t: - k = is_true ? lean::GE : lean::LT; + case lp_api::lower_t: + k = is_true ? lp::GE : (is_int ? lp::LE : lp::LT); break; - case lp::upper_t: - k = is_true ? lean::LE : lean::GT; + case lp_api::upper_t: + k = is_true ? lp::LE : (is_int ? lp::GE : lp::GT); break; } - if (k == lean::LT || k == lean::LE) { + if (k == lp::LT || k == lp::LE) { ++m_stats.m_assert_lower; } else { ++m_stats.m_assert_upper; } auto vi = get_var_index(b.get_var()); - auto ci = m_solver->add_var_bound(vi, k, b.get_value()); + rational bound = b.get_value(); + lp::constraint_index ci; + if (is_int && !is_true) { + rational bound = b.get_value(false).get_rational(); + ci = m_solver->add_var_bound(vi, k, bound); + } + else { + ci = m_solver->add_var_bound(vi, k, b.get_value()); + } TRACE("arith", tout << "v" << b.get_var() << "\n";); add_ineq_constraint(ci, literal(bv, !is_true)); @@ -2092,7 +2154,7 @@ namespace smt { // Then the equality v1 == v2 is propagated to the core. // - typedef std::pair constraint_bound; + typedef std::pair constraint_bound; vector m_lower_terms; vector m_upper_terms; typedef std::pair value_sort_pair; @@ -2100,16 +2162,16 @@ namespace smt { typedef map > value2var; value2var m_fixed_var_table; - void propagate_eqs(lean::var_index vi, lean::constraint_index ci, lean::lconstraint_kind k, lp::bound& b) { + void propagate_eqs(lp::var_index vi, lp::constraint_index ci, lp::lconstraint_kind k, lp_api::bound& b) { if (propagate_eqs()) { rational const& value = b.get_value(); - if (k == lean::GE) { + if (k == lp::GE) { set_lower_bound(vi, ci, value); if (has_upper_bound(vi, ci, value)) { fixed_var_eh(b.get_var(), value); } } - else if (k == lean::LE) { + else if (k == lp::LE) { set_upper_bound(vi, ci, value); if (has_lower_bound(vi, ci, value)) { fixed_var_eh(b.get_var(), value); @@ -2130,16 +2192,16 @@ namespace smt { bool use_tableau() const { return lp_params(ctx().get_params()).simplex_strategy() < 2; } - void set_upper_bound(lean::var_index vi, lean::constraint_index ci, rational const& v) { set_bound(vi, ci, v, false); } + void set_upper_bound(lp::var_index vi, lp::constraint_index ci, rational const& v) { set_bound(vi, ci, v, false); } - void set_lower_bound(lean::var_index vi, lean::constraint_index ci, rational const& v) { set_bound(vi, ci, v, true); } + void set_lower_bound(lp::var_index vi, lp::constraint_index ci, rational const& v) { set_bound(vi, ci, v, true); } - void set_bound(lean::var_index vi, lean::constraint_index ci, rational const& v, bool is_lower) { + void set_bound(lp::var_index vi, lp::constraint_index ci, rational const& v, bool is_lower) { if (!m_solver->is_term(vi)) { // m_solver already tracks bounds on proper variables, but not on terms. return; } - lean::var_index ti = m_solver->adjust_term_index(vi); + lp::var_index ti = m_solver->adjust_term_index(vi); auto& vec = is_lower ? m_lower_terms : m_upper_terms; if (vec.size() <= ti) { vec.resize(ti + 1, constraint_bound(UINT_MAX, rational())); @@ -2152,15 +2214,15 @@ namespace smt { } } - bool has_upper_bound(lean::var_index vi, lean::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, false); } + bool has_upper_bound(lp::var_index vi, lp::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, false); } - bool has_lower_bound(lean::var_index vi, lean::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, true); } + bool has_lower_bound(lp::var_index vi, lp::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, true); } - bool has_bound(lean::var_index vi, lean::constraint_index& ci, rational const& bound, bool is_lower) { + bool has_bound(lp::var_index vi, lp::constraint_index& ci, rational const& bound, bool is_lower) { if (m_solver->is_term(vi)) { - lean::var_index ti = m_solver->adjust_term_index(vi); + lp::var_index ti = m_solver->adjust_term_index(vi); theory_var v = m_term_index2theory_var.get(ti, null_theory_var); rational val; TRACE("arith", tout << vi << " " << v << "\n";); @@ -2203,7 +2265,7 @@ namespace smt { if (static_cast(v2) < th.get_num_vars() && !is_equal(v1, v2)) { auto vi1 = get_var_index(v1); auto vi2 = get_var_index(v2); - lean::constraint_index ci1, ci2, ci3, ci4; + lp::constraint_index ci1, ci2, ci3, ci4; TRACE("arith", tout << "fixed: " << mk_pp(get_owner(v1), m) << " " << mk_pp(get_owner(v2), m) << " " << bound << " " << has_lower_bound(vi2, ci3, bound) << "\n";); if (has_lower_bound(vi2, ci3, bound) && has_upper_bound(vi2, ci4, bound)) { VERIFY (has_lower_bound(vi1, ci1, bound)); @@ -2250,26 +2312,16 @@ namespace smt { } lbool make_feasible() { - reset_variable_values(); - ++m_stats.m_make_feasible; - if (m_solver->A_r().column_count() > m_stats.m_max_cols) - m_stats.m_max_cols = m_solver->A_r().column_count(); - if (m_solver->A_r().row_count() > m_stats.m_max_rows) - m_stats.m_max_rows = m_solver->A_r().row_count(); + auto status = m_solver->find_feasible_solution(); TRACE("arith_verbose", display(tout);); - lean::lp_status status = m_solver->find_feasible_solution(); - m_stats.m_num_iterations = m_solver->settings().st().m_total_iterations; - m_stats.m_num_factorizations = m_solver->settings().st().m_num_factorizations; - m_stats.m_need_to_solve_inf = m_solver->settings().st().m_need_to_solve_inf; - switch (status) { - case lean::lp_status::INFEASIBLE: + case lp::lp_status::INFEASIBLE: return l_false; - case lean::lp_status::FEASIBLE: - case lean::lp_status::OPTIMAL: + case lp::lp_status::FEASIBLE: + case lp::lp_status::OPTIMAL: // SASSERT(m_solver->all_constraints_hold()); return l_true; - case lean::lp_status::TIME_EXHAUSTED: + case lp::lp_status::TIME_EXHAUSTED: default: TRACE("arith", tout << "status treated as inconclusive: " << status << "\n";); @@ -2279,14 +2331,14 @@ namespace smt { } } - vector> m_explanation; + vector> m_explanation; literal_vector m_core; svector m_eqs; vector m_params; - // lean::constraint_index const null_constraint_index = UINT_MAX; // not sure what a correct fix is + // lp::constraint_index const null_constraint_index = UINT_MAX; // not sure what a correct fix is - void set_evidence(lean::constraint_index idx) { + void set_evidence(lp::constraint_index idx) { if (idx == UINT_MAX) { return; } @@ -2371,13 +2423,53 @@ namespace smt { TRACE("arith", display(tout);); } + nlsat::anum const& nl_value(theory_var v, scoped_anum& r) { + SASSERT(m_nra); + SASSERT(m_use_nra_model); + lp::var_index vi = m_theory_var2var_index[v]; + if (m_solver->is_term(vi)) { + + m_todo_terms.push_back(std::make_pair(vi, rational::one())); + + m_nra->am().set(r, 0); + while (!m_todo_terms.empty()) { + rational wcoeff = m_todo_terms.back().second; + lp::var_index wi = m_todo_terms.back().first; + m_todo_terms.pop_back(); + lp::lar_term const& term = m_solver->get_term(vi); + scoped_anum r1(m_nra->am()); + rational c1 = term.m_v * wcoeff; + m_nra->am().set(r1, c1.to_mpq()); + m_nra->am().add(r, r1, r); + for (auto const coeff : term.m_coeffs) { + lp::var_index wi = coeff.first; + c1 = coeff.second * wcoeff; + if (m_solver->is_term(wi)) { + m_todo_terms.push_back(std::make_pair(wi, c1)); + } + else { + m_nra->am().set(r1, c1.to_mpq()); + m_nra->am().mul(m_nra->value(wi), r1, r1); + m_nra->am().add(r1, r, r); + } + } + } + return r; + } + else { + return m_nra->value(vi); + } + } + model_value_proc * mk_value(enode * n, model_generator & mg) { theory_var v = n->get_th_var(get_id()); expr* o = n->get_owner(); if (m_use_nra_model) { - SASSERT(m_nra); - app* e = a.mk_numeral(m_nra->value(m_theory_var2var_index[v]), a.is_int(o)); - return alloc(expr_wrapper_proc, e); + anum const& an = nl_value(v, *m_a1); + if (a.is_int(o) && !m_nra->am().is_int(an)) { + return alloc(expr_wrapper_proc, a.mk_numeral(rational::zero(), a.is_int(o))); + } + return alloc(expr_wrapper_proc, a.mk_numeral(nl_value(v, *m_a1), a.is_int(o))); } else { rational r = get_value(v); @@ -2453,17 +2545,21 @@ namespace smt { } theory_lra::inf_eps value(theory_var v) { - lean::impq ival = get_ivalue(v); + lp::impq ival = get_ivalue(v); return inf_eps(0, inf_rational(ival.x, ival.y)); } theory_lra::inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared) { - lean::var_index vi = m_theory_var2var_index.get(v, UINT_MAX); - vector > coeffs; - rational coeff; + lp::var_index vi = m_theory_var2var_index.get(v, UINT_MAX); + vector > coeffs; + rational coeff(0); + // + // TBD: change API for maximize_term to take a proper term as input. + // if (m_solver->is_term(vi)) { - const lean::lar_term& term = m_solver->get_term(vi); + const lp::lar_term& term = m_solver->get_term(vi); for (auto & ti : term.m_coeffs) { + SASSERT(!m_solver->is_term(ti.first)); coeffs.push_back(std::make_pair(ti.second, ti.first)); } coeff = term.m_v; @@ -2472,7 +2568,7 @@ namespace smt { coeffs.push_back(std::make_pair(rational::one(), vi)); coeff = rational::zero(); } - lean::impq term_max; + lp::impq term_max; if (m_solver->maximize_term(coeffs, term_max)) { blocker = mk_gt(v); inf_rational val(term_max.x + coeff, term_max.y); @@ -2487,7 +2583,7 @@ namespace smt { } expr_ref mk_gt(theory_var v) { - lean::impq val = get_ivalue(v); + lp::impq val = get_ivalue(v); expr* obj = get_enode(v)->get_owner(); rational r = val.x; expr_ref e(m); @@ -2518,19 +2614,38 @@ namespace smt { return internalize_def(term); } - app_ref mk_obj(theory_var v) { - lean::var_index vi = m_theory_var2var_index[v]; - if (m_solver->is_term(vi)) { - expr_ref_vector args(m); - const lean::lar_term& term = m_solver->get_term(vi); - for (auto & ti : term.m_coeffs) { - theory_var w = m_var_index2theory_var[ti.first]; - expr* o = get_enode(w)->get_owner(); - args.push_back(a.mk_mul(a.mk_numeral(ti.second, a.is_int(o)), o)); + app_ref mk_term(lp::lar_term const& term, bool is_int) { + expr_ref_vector args(m); + for (auto & ti : term.m_coeffs) { + theory_var w; + if (m_solver->is_term(ti.first)) { + w = m_term_index2theory_var[m_solver->adjust_term_index(ti.first)]; } - rational r = term.m_v; - args.push_back(a.mk_numeral(r, r.is_int())); - return app_ref(a.mk_add(args.size(), args.c_ptr()), m); + else { + w = m_var_index2theory_var[ti.first]; + } + expr* o = get_enode(w)->get_owner(); + if (ti.second.is_one()) { + args.push_back(o); + } + else { + args.push_back(a.mk_mul(a.mk_numeral(ti.second, is_int), o)); + } + } + if (!term.m_v.is_zero()) { + args.push_back(a.mk_numeral(term.m_v, is_int)); + } + if (args.size() == 1) { + return app_ref(to_app(args[0].get()), m); + } + return app_ref(a.mk_add(args.size(), args.c_ptr()), m); + } + + app_ref mk_obj(theory_var v) { + lp::var_index vi = m_theory_var2var_index[v]; + bool is_int = a.is_int(get_enode(v)->get_owner()); + if (m_solver->is_term(vi)) { + return mk_term(m_solver->get_term(vi), is_int); } else { theory_var w = m_var_index2theory_var[vi]; @@ -2542,20 +2657,21 @@ namespace smt { rational r = val.get_rational(); bool is_strict = val.get_infinitesimal().is_pos(); app_ref b(m); + bool is_int = a.is_int(get_enode(v)->get_owner()); if (is_strict) { - b = a.mk_le(mk_obj(v), a.mk_numeral(r, r.is_int())); + b = a.mk_le(mk_obj(v), a.mk_numeral(r, is_int)); } else { - b = a.mk_ge(mk_obj(v), a.mk_numeral(r, r.is_int())); + b = a.mk_ge(mk_obj(v), a.mk_numeral(r, is_int)); } if (!ctx().b_internalized(b)) { fm.insert(b->get_decl()); bool_var bv = ctx().mk_bool_var(b); ctx().set_var_theory(bv, get_id()); // ctx().set_enode_flag(bv, true); - lp::bound_kind bkind = lp::bound_kind::lower_t; - if (is_strict) bkind = lp::bound_kind::upper_t; - lp::bound* a = alloc(lp::bound, bv, v, r, bkind); + lp_api::bound_kind bkind = lp_api::bound_kind::lower_t; + if (is_strict) bkind = lp_api::bound_kind::upper_t; + lp_api::bound* a = alloc(lp_api::bound, bv, v, is_int, r, bkind); mk_bound_axioms(*a); updt_unassigned_bounds(v, +1); m_bounds[v].push_back(a); @@ -2587,7 +2703,7 @@ namespace smt { } } - void display_evidence(std::ostream& out, vector> const& evidence) { + void display_evidence(std::ostream& out, vector> const& evidence) { for (auto const& ev : evidence) { expr_ref e(m); SASSERT(!ev.first.is_zero()); @@ -2629,7 +2745,7 @@ namespace smt { st.update("arith-rows", m_stats.m_add_rows); st.update("arith-propagations", m_stats.m_bounds_propagations); st.update("arith-iterations", m_stats.m_num_iterations); - st.update("arith-factorizations", m_stats.m_num_factorizations); + st.update("arith-factorizations", m_solver->settings().st().m_num_factorizations); st.update("arith-pivots", m_stats.m_need_to_solve_inf); st.update("arith-plateau-iterations", m_stats.m_num_iterations_with_no_progress); st.update("arith-fixed-eqs", m_stats.m_fixed_eqs); @@ -2637,9 +2753,9 @@ namespace smt { st.update("arith-bound-propagations-lp", m_stats.m_bound_propagations1); st.update("arith-bound-propagations-cheap", m_stats.m_bound_propagations2); st.update("arith-diseq", m_stats.m_assert_diseq); - st.update("arith-make-feasible", m_stats.m_make_feasible); - st.update("arith-max-columns", m_stats.m_max_cols); - st.update("arith-max-rows", m_stats.m_max_rows); + st.update("arith-make-feasible", m_solver->settings().st().m_make_feasible); + st.update("arith-max-columns", m_solver->settings().st().m_max_cols); + st.update("arith-max-rows", m_solver->settings().st().m_max_rows); } }; diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index 3f8845546..832995994 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -1074,7 +1074,7 @@ expr_ref theory_seq::mk_first(expr* s) { void theory_seq::mk_decompose(expr* e, expr_ref& head, expr_ref& tail) { - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; zstring s; if (m_util.str.is_empty(e)) { head = m_util.str.mk_unit(mk_nth(e, m_autil.mk_int(0))); @@ -1401,7 +1401,7 @@ bool theory_seq::occurs(expr* a, expr* b) { // true if a occurs under an interpreted function or under left/right selector. SASSERT(is_var(a)); SASSERT(m_todo.empty()); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; m_todo.push_back(b); while (!m_todo.empty()) { b = m_todo.back(); @@ -1990,7 +1990,7 @@ bool theory_seq::solve_nc(unsigned idx) { return true; } - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; if (m.is_eq(c, e1, e2)) { literal eq = mk_eq(e1, e2, false); propagate_lit(deps, 0, 0, ~eq); @@ -2176,8 +2176,67 @@ bool theory_seq::simplify_and_solve_eqs() { return m_new_propagation || ctx.inconsistent(); } -void theory_seq::internalize_eq_eh(app * atom, bool_var v) {} +void theory_seq::internalize_eq_eh(app * atom, bool_var v) { +} +bool theory_seq::internalize_atom(app* a, bool) { +#if 1 + return internalize_term(a); +#else + if (is_skolem(m_eq, a)) { + return internalize_term(a); + } + context & ctx = get_context(); + bool_var bv = ctx.mk_bool_var(a); + ctx.set_var_theory(bv, get_id()); + ctx.mark_as_relevant(bv); + + expr* e1, *e2; + if (m_util.str.is_in_re(a, e1, e2)) { + return internalize_term(to_app(e1)) && internalize_re(e2); + } + if (m_util.str.is_contains(a, e1, e2) || + m_util.str.is_prefix(a, e1, e2) || + m_util.str.is_suffix(a, e1, e2)) { + return internalize_term(to_app(e1)) && internalize_term(to_app(e2)); + } + if (is_accept(a) || is_reject(a) || is_step(a) || is_skolem(symbol("seq.is_digit"), a)) { + return true; + } + UNREACHABLE(); + return internalize_term(a); +#endif +} + +bool theory_seq::internalize_re(expr* e) { + expr* e1, *e2; + unsigned lc, uc; + if (m_util.re.is_to_re(e, e1)) { + return internalize_term(to_app(e1)); + } + if (m_util.re.is_star(e, e1) || + m_util.re.is_plus(e, e1) || + m_util.re.is_opt(e, e1) || + m_util.re.is_loop(e, e1, lc) || + m_util.re.is_loop(e, e1, lc, uc) || + m_util.re.is_complement(e, e1)) { + return internalize_re(e1); + } + if (m_util.re.is_union(e, e1, e2) || + m_util.re.is_intersection(e, e1, e2) || + m_util.re.is_concat(e, e1, e2)) { + return internalize_re(e1) && internalize_re(e2); + } + if (m_util.re.is_full(e) || + m_util.re.is_empty(e)) { + return true; + } + if (m_util.re.is_range(e, e1, e2)) { + return internalize_term(to_app(e1)) && internalize_term(to_app(e2)); + } + UNREACHABLE(); + return internalize_term(to_app(e)); +} bool theory_seq::internalize_term(app* term) { context & ctx = get_context(); @@ -2187,10 +2246,7 @@ bool theory_seq::internalize_term(app* term) { return true; } TRACE("seq_verbose", tout << mk_pp(term, m) << "\n";); - unsigned num_args = term->get_num_args(); - expr* arg; - for (unsigned i = 0; i < num_args; i++) { - arg = term->get_arg(i); + for (expr* arg : *term) { mk_var(ensure_enode(arg)); } if (m.is_bool(term)) { @@ -2257,7 +2313,7 @@ bool theory_seq::check_int_string() { bool theory_seq::add_stoi_axiom(expr* e) { context& ctx = get_context(); - expr* n; + expr* n = 0; rational val; TRACE("seq", tout << mk_pp(e, m) << "\n";); VERIFY(m_util.str.is_stoi(e, n)); @@ -2339,7 +2395,7 @@ expr_ref theory_seq::digit2int(expr* ch) { bool theory_seq::add_itos_axiom(expr* e) { context& ctx = get_context(); rational val; - expr* n; + expr* n = 0; TRACE("seq", tout << mk_pp(e, m) << "\n";); VERIFY(m_util.str.is_itos(e, n)); if (get_num_value(n, val)) { @@ -2543,9 +2599,9 @@ void theory_seq::collect_statistics(::statistics & st) const { void theory_seq::init_model(expr_ref_vector const& es) { expr_ref new_s(m); - for (unsigned i = 0; i < es.size(); ++i) { + for (expr* e : es) { dependency* eqs = 0; - expr_ref s = canonize(es[i], eqs); + expr_ref s = canonize(e, eqs); if (is_var(s)) { new_s = m_factory->get_fresh_value(m.get_sort(s)); m_rep.update(s, new_s, eqs); @@ -2556,13 +2612,11 @@ void theory_seq::init_model(expr_ref_vector const& es) { void theory_seq::init_model(model_generator & mg) { m_factory = alloc(seq_factory, get_manager(), get_family_id(), mg.get_model()); mg.register_factory(m_factory); - for (unsigned j = 0; j < m_nqs.size(); ++j) { - ne const& n = m_nqs[j]; + for (ne const& n : m_nqs) { m_factory->register_value(n.l()); m_factory->register_value(n.r()); } - for (unsigned j = 0; j < m_nqs.size(); ++j) { - ne const& n = m_nqs[j]; + for (ne const& n : m_nqs) { for (unsigned i = 0; i < n.ls().size(); ++i) { init_model(n.ls(i)); init_model(n.rs(i)); @@ -2804,77 +2858,123 @@ bool theory_seq::canonize(expr_ref_vector const& es, expr_ref_vector& result, de return change; } - -expr_ref theory_seq::expand(expr* e0, dependency*& eqs) { +expr_ref theory_seq::expand(expr* e, dependency*& eqs) { + unsigned sz = m_expand_todo.size(); + m_expand_todo.push_back(e); expr_ref result(m); - dependency* deps = 0; - expr_dep ed; - if (m_rep.find_cache(e0, ed)) { - eqs = m_dm.mk_join(eqs, ed.second); - result = ed.first; - return result; + while (m_expand_todo.size() != sz) { + expr* e = m_expand_todo.back(); + result = expand1(e, eqs); + if (result.get()) m_expand_todo.pop_back(); } + return result; +} + +expr_ref theory_seq::try_expand(expr* e, dependency*& eqs){ + expr_ref result(m); + expr_dep ed; + if (m_rep.find_cache(e, ed)) { + if (e != ed.first) { + eqs = m_dm.mk_join(eqs, ed.second); + } + result = ed.first; + } + else { + m_expand_todo.push_back(e); + } + return result; +} +expr_ref theory_seq::expand1(expr* e0, dependency*& eqs) { + expr_ref result(m); + result = try_expand(e0, eqs); + if (result) return result; + dependency* deps = 0; expr* e = m_rep.find(e0, deps); expr* e1, *e2, *e3; + expr_ref arg1(m), arg2(m); context& ctx = get_context(); if (m_util.str.is_concat(e, e1, e2)) { - result = mk_concat(expand(e1, deps), expand(e2, deps)); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = mk_concat(arg1, arg2); } else if (m_util.str.is_empty(e) || m_util.str.is_string(e)) { result = e; } else if (m_util.str.is_prefix(e, e1, e2)) { - result = m_util.str.mk_prefix(expand(e1, deps), expand(e2, deps)); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = m_util.str.mk_prefix(arg1, arg2); } else if (m_util.str.is_suffix(e, e1, e2)) { - result = m_util.str.mk_suffix(expand(e1, deps), expand(e2, deps)); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = m_util.str.mk_suffix(arg1, arg2); } else if (m_util.str.is_contains(e, e1, e2)) { - result = m_util.str.mk_contains(expand(e1, deps), expand(e2, deps)); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = m_util.str.mk_contains(arg1, arg2); } else if (m_util.str.is_unit(e, e1)) { - result = m_util.str.mk_unit(expand(e1, deps)); + arg1 = try_expand(e1, deps); + if (!arg1) return result; + result = m_util.str.mk_unit(arg1); } else if (m_util.str.is_index(e, e1, e2)) { - result = m_util.str.mk_index(expand(e1, deps), expand(e2, deps), m_autil.mk_int(0)); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = m_util.str.mk_index(arg1, arg2, m_autil.mk_int(0)); } else if (m_util.str.is_index(e, e1, e2, e3)) { - result = m_util.str.mk_index(expand(e1, deps), expand(e2, deps), e3); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = m_util.str.mk_index(arg1, arg2, e3); } else if (m.is_ite(e, e1, e2, e3)) { if (ctx.e_internalized(e) && ctx.e_internalized(e2) && ctx.get_enode(e)->get_root() == ctx.get_enode(e2)->get_root()) { - result = expand(e2, deps); + result = try_expand(e2, deps); + if (!result) return result; add_dependency(deps, ctx.get_enode(e), ctx.get_enode(e2)); } else if (ctx.e_internalized(e) && ctx.e_internalized(e2) && ctx.get_enode(e)->get_root() == ctx.get_enode(e3)->get_root()) { - result = expand(e3, deps); + result = try_expand(e3, deps); + if (!result) return result; add_dependency(deps, ctx.get_enode(e), ctx.get_enode(e3)); } else { - literal lit(mk_literal(e1)); + literal lit(mk_literal(e1)); #if 0 - expr_ref sk_ite = mk_sk_ite(e1, e2, e3); - add_axiom(~lit, mk_eq(e2, sk_ite, false)); - add_axiom( lit, mk_eq(e3, sk_ite, false)); - result = sk_ite; - + expr_ref sk_ite = mk_sk_ite(e1, e2, e3); + add_axiom(~lit, mk_eq(e2, sk_ite, false)); + add_axiom( lit, mk_eq(e3, sk_ite, false)); + result = sk_ite; + #else - switch (ctx.get_assignment(lit)) { - case l_true: - deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(lit))); - result = expand(e2, deps); - break; - case l_false: - deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(~lit))); - result = expand(e3, deps); - break; - case l_undef: - result = e; - m_reset_cache = true; - TRACE("seq", tout << "undef: " << result << "\n"; - tout << lit << "@ level: " << ctx.get_scope_level() << "\n";); - break; - } + switch (ctx.get_assignment(lit)) { + case l_true: + deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(lit))); + result = try_expand(e2, deps); + if (!result) return result; + break; + case l_false: + deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(~lit))); + result = try_expand(e3, deps); + if (!result) return result; + break; + case l_undef: + result = e; + m_reset_cache = true; + TRACE("seq", tout << "undef: " << result << "\n"; + tout << lit << "@ level: " << ctx.get_scope_level() << "\n";); + break; + } #endif } } @@ -2962,6 +3062,7 @@ void theory_seq::deque_axiom(expr* n) { add_length_axiom(n); } else if (m_util.str.is_empty(n) && !has_length(n) && !m_length.empty()) { + ensure_enode(n); enforce_length(get_context().get_enode(n)); } else if (m_util.str.is_index(n)) { @@ -3091,7 +3192,7 @@ void theory_seq::add_indexof_axiom(expr* i) { */ void theory_seq::add_replace_axiom(expr* r) { - expr* a, *s, *t; + expr* a = 0, *s = 0, *t = 0; VERIFY(m_util.str.is_replace(r, a, s, t)); expr_ref x = mk_skolem(m_indexof_left, a, s); expr_ref y = mk_skolem(m_indexof_right, a, s); @@ -3224,7 +3325,7 @@ void theory_seq::add_itos_length_axiom(expr* len) { void theory_seq::propagate_in_re(expr* n, bool is_true) { TRACE("seq", tout << mk_pp(n, m) << " <- " << (is_true?"true":"false") << "\n";); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; VERIFY(m_util.str.is_in_re(n, e1, e2)); expr_ref tmp(n, m); @@ -3356,7 +3457,7 @@ bool theory_seq::get_length(expr* e, rational& val) const { if (!tha) return false; rational val1; expr_ref len(m), len_val(m); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; ptr_vector todo; todo.push_back(e); val.reset(); @@ -3416,7 +3517,7 @@ bool theory_seq::get_length(expr* e, rational& val) const { */ void theory_seq::add_extract_axiom(expr* e) { - expr* s, *i, *l; + expr* s = 0, *i = 0, *l = 0; VERIFY(m_util.str.is_extract(e, s, i, l)); if (is_tail(s, i, l)) { add_tail_axiom(e, s); @@ -3567,8 +3668,8 @@ void theory_seq::add_at_axiom(expr* e) { add_axiom(~i_ge_0, i_ge_len_s, mk_eq(one, len_e, false)); add_axiom(~i_ge_0, i_ge_len_s, mk_eq(i, len_x, false)); - add_axiom(i_ge_0, mk_eq(s, emp, false)); - add_axiom(~i_ge_len_s, mk_eq(s, emp, false)); + add_axiom(i_ge_0, mk_eq(e, emp, false)); + add_axiom(~i_ge_len_s, mk_eq(e, emp, false)); } /** @@ -3576,7 +3677,7 @@ void theory_seq::add_at_axiom(expr* e) { */ void theory_seq::propagate_step(literal lit, expr* step) { SASSERT(get_context().get_assignment(lit) == l_true); - expr* re, *acc, *s, *idx, *i, *j; + expr* re = 0, *acc = 0, *s = 0, *idx = 0, *i = 0, *j = 0; VERIFY(is_step(step, s, idx, re, i, j, acc)); TRACE("seq", tout << mk_pp(step, m) << " -> " << mk_pp(acc, m) << "\n";); propagate_lit(0, 1, &lit, mk_literal(acc)); @@ -3737,7 +3838,7 @@ void theory_seq::propagate_eq(dependency* deps, literal_vector const& _lits, exp void theory_seq::assign_eh(bool_var v, bool is_true) { context & ctx = get_context(); expr* e = ctx.bool_var2expr(v); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; expr_ref f(m); bool change = false; literal lit(v, !is_true); @@ -3875,7 +3976,7 @@ void theory_seq::new_eq_eh(dependency* deps, enode* n1, enode* n2) { enforce_length_coherence(n1, n2); } else if (n1 != n2 && m_util.is_re(n1->get_owner())) { - warning_msg("equality between regular expressions is not yet supported"); + // ignore // eautomaton* a1 = get_automaton(n1->get_owner()); // eautomaton* a2 = get_automaton(n2->get_owner()); // eautomaton* b1 = mk_difference(*a1, *a2); @@ -3995,7 +4096,7 @@ void theory_seq::relevant_eh(app* n) { } expr* arg; - if (m_util.str.is_length(n, arg) && !has_length(arg)) { + if (m_util.str.is_length(n, arg) && !has_length(arg) && get_context().e_internalized(arg)) { enforce_length(get_context().get_enode(arg)); } } @@ -4085,7 +4186,7 @@ expr_ref theory_seq::mk_step(expr* s, expr* idx, expr* re, unsigned i, unsigned rej(s, idx, re, i) -> len(s) > idx if i is final */ void theory_seq::propagate_acc_rej_length(literal lit, expr* e) { - expr *s, * idx, *re; + expr *s = 0, *idx = 0, *re = 0; unsigned src; eautomaton* aut = 0; bool is_acc; @@ -4114,7 +4215,7 @@ bool theory_seq::add_accept2step(expr* acc, bool& change) { TRACE("seq", tout << mk_pp(acc, m) << "\n";); SASSERT(ctx.get_assignment(acc) == l_true); - expr *e, * idx, *re; + expr *e = 0, *idx = 0, *re = 0; expr_ref step(m); unsigned src; eautomaton* aut = 0; @@ -4193,7 +4294,7 @@ bool theory_seq::add_accept2step(expr* acc, bool& change) { bool theory_seq::add_step2accept(expr* step, bool& change) { context& ctx = get_context(); SASSERT(ctx.get_assignment(step) == l_true); - expr* re, *_acc, *s, *idx, *i, *j; + expr* re = 0, *_acc = 0, *s = 0, *idx = 0, *i = 0, *j = 0; VERIFY(is_step(step, s, idx, re, i, j, _acc)); literal acc1 = mk_accept(s, idx, re, i); switch (ctx.get_assignment(acc1)) { @@ -4242,7 +4343,7 @@ Recall we also have: bool theory_seq::add_reject2reject(expr* rej, bool& change) { context& ctx = get_context(); SASSERT(ctx.get_assignment(rej) == l_true); - expr* s, *idx, *re; + expr* s = 0, *idx = 0, *re = 0; unsigned src; rational r; eautomaton* aut = 0; @@ -4304,7 +4405,7 @@ bool theory_seq::add_reject2reject(expr* rej, bool& change) { void theory_seq::propagate_not_prefix(expr* e) { context& ctx = get_context(); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; VERIFY(m_util.str.is_prefix(e, e1, e2)); literal lit = ctx.get_literal(e); SASSERT(ctx.get_assignment(lit) == l_false); @@ -4333,7 +4434,7 @@ void theory_seq::propagate_not_prefix(expr* e) { void theory_seq::propagate_not_prefix2(expr* e) { context& ctx = get_context(); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; VERIFY(m_util.str.is_prefix(e, e1, e2)); literal lit = ctx.get_literal(e); SASSERT(ctx.get_assignment(lit) == l_false); diff --git a/src/smt/theory_seq.h b/src/smt/theory_seq.h index e145d3077..f7212e608 100644 --- a/src/smt/theory_seq.h +++ b/src/smt/theory_seq.h @@ -341,8 +341,8 @@ namespace smt { virtual void init(context* ctx); virtual final_check_status final_check_eh(); - virtual bool internalize_atom(app* atom, bool) { return internalize_term(atom); } - virtual bool internalize_term(app*); + virtual bool internalize_atom(app* atom, bool); + virtual bool internalize_term(app*); virtual void internalize_eq_eh(app * atom, bool_var v); virtual void new_eq_eh(theory_var, theory_var); virtual void new_diseq_eh(theory_var, theory_var); @@ -387,6 +387,7 @@ namespace smt { vector const& ll, vector const& rl); bool set_empty(expr* x); bool is_complex(eq const& e); + bool internalize_re(expr* e); bool check_extensionality(); bool check_contains(); @@ -461,7 +462,10 @@ namespace smt { expr_ref canonize(expr* e, dependency*& eqs); bool canonize(expr* e, expr_ref_vector& es, dependency*& eqs); bool canonize(expr_ref_vector const& es, expr_ref_vector& result, dependency*& eqs); + ptr_vector m_expand_todo; expr_ref expand(expr* e, dependency*& eqs); + expr_ref expand1(expr* e, dependency*& eqs); + expr_ref try_expand(expr* e, dependency*& eqs); void add_dependency(dependency*& dep, enode* a, enode* b); void get_concat(expr* e, ptr_vector& concats); diff --git a/src/smt/theory_str.cpp b/src/smt/theory_str.cpp index d560a54a1..13f8ab282 100644 --- a/src/smt/theory_str.cpp +++ b/src/smt/theory_str.cpp @@ -21,14 +21,13 @@ #include"ast_pp.h" #include"ast_ll_pp.h" #include -#include #include #include"theory_seq_empty.h" #include"theory_arith.h" #include"ast_util.h" namespace smt { - + theory_str::theory_str(ast_manager & m, theory_str_params const & params): theory(m.mk_family_id("seq")), m_params(params), @@ -99,7 +98,7 @@ namespace smt { if (defaultCharset) { // valid C strings can't contain the null byte ('\0') charSetSize = 255; - char_set.resize(256, 0); + char_set.resize(256, 0); int idx = 0; // small letters for (int i = 97; i < 123; i++) { @@ -233,11 +232,11 @@ namespace smt { for (unsigned i = 0; i < num_args; ++i) { enode * arg = e->get_arg(i); theory_var v_arg = mk_var(arg); - TRACE("str", tout << "arg has theory var #" << v_arg << std::endl;); + TRACE("str", tout << "arg has theory var #" << v_arg << std::endl;); (void)v_arg; } theory_var v = mk_var(e); - TRACE("str", tout << "term has theory var #" << v << std::endl;); + TRACE("str", tout << "term has theory var #" << v << std::endl;); (void)v; if (opt_EagerStringConstantLengthAssertions && u.str.is_string(term)) { TRACE("str", tout << "eagerly asserting length of string term " << mk_pp(term, m) << std::endl;); @@ -258,7 +257,7 @@ namespace smt { void theory_str::refresh_theory_var(expr * e) { enode * en = ensure_enode(e); - theory_var v = mk_var(en); + theory_var v = mk_var(en); (void)v; TRACE("str", tout << "refresh " << mk_pp(e, get_manager()) << ": v#" << v << std::endl;); m_basicstr_axiom_todo.push_back(en); } @@ -488,7 +487,6 @@ namespace smt { app * theory_str::mk_str_var(std::string name) { context & ctx = get_context(); - ast_manager & m = get_manager(); TRACE("str", tout << "creating string variable " << name << " at scope level " << sLevel << std::endl;); @@ -506,7 +504,7 @@ namespace smt { // this might help?? mk_var(ctx.get_enode(a)); m_basicstr_axiom_todo.push_back(ctx.get_enode(a)); - TRACE("str", tout << "add " << mk_pp(a, m) << " to m_basicstr_axiom_todo" << std::endl;); + TRACE("str", tout << "add " << mk_pp(a, get_manager()) << " to m_basicstr_axiom_todo" << std::endl;); variable_set.insert(a); internal_variable_set.insert(a); @@ -517,7 +515,6 @@ namespace smt { app * theory_str::mk_regex_rep_var() { context & ctx = get_context(); - ast_manager & m = get_manager(); sort * string_sort = u.str.mk_string_sort(); app * a = mk_fresh_const("regex", string_sort); @@ -528,7 +525,7 @@ namespace smt { SASSERT(ctx.e_internalized(a)); mk_var(ctx.get_enode(a)); m_basicstr_axiom_todo.push_back(ctx.get_enode(a)); - TRACE("str", tout << "add " << mk_pp(a, m) << " to m_basicstr_axiom_todo" << std::endl;); + TRACE("str", tout << "add " << mk_pp(a, get_manager()) << " to m_basicstr_axiom_todo" << std::endl;); variable_set.insert(a); //internal_variable_set.insert(a); @@ -934,8 +931,7 @@ namespace smt { SASSERT(len_xy); // build RHS: start by extracting x and y from Concat(x, y) - unsigned nArgs = a_cat->get_num_args(); - SASSERT(nArgs == 2); + SASSERT(a_cat->get_num_args() == 2); app * a_x = to_app(a_cat->get_arg(0)); app * a_y = to_app(a_cat->get_arg(1)); @@ -1553,14 +1549,12 @@ namespace smt { expr_ref elseBranch(ctx.mk_eq_atom(result, expr->get_arg(0)), m); expr_ref breakdownAssert(m.mk_ite(condAst, m.mk_and(thenItems.size(), thenItems.c_ptr()), elseBranch), m); + assert_axiom(breakdownAssert); + SASSERT(breakdownAssert); expr_ref reduceToResult(ctx.mk_eq_atom(expr, result), m); - SASSERT(reduceToResult); - - expr_ref finalAxiom(m.mk_and(breakdownAssert, reduceToResult), m); - SASSERT(finalAxiom); - assert_axiom(finalAxiom); + assert_axiom(reduceToResult); } void theory_str::instantiate_axiom_str_to_int(enode * e) { @@ -1988,7 +1982,8 @@ namespace smt { return NULL; } - static inline std::string rational_to_string_if_exists(const rational & x, bool x_exists) { + // trace code helper + inline std::string rational_to_string_if_exists(const rational & x, bool x_exists) { if (x_exists) { return x.to_string(); } else { @@ -2055,7 +2050,7 @@ namespace smt { << "* |parent| = " << rational_to_string_if_exists(parentLen, parentLen_exists) << std::endl << "* |arg0| = " << rational_to_string_if_exists(arg0Len, arg0Len_exists) << std::endl << "* |arg1| = " << rational_to_string_if_exists(arg1Len, arg1Len_exists) << std::endl; - ); + ); (void)arg0Len_exists; if (parentLen_exists && !arg1Len_exists) { TRACE("str", tout << "make up len for arg1" << std::endl;); @@ -2126,7 +2121,8 @@ namespace smt { << "* |parent| = " << rational_to_string_if_exists(parentLen, parentLen_exists) << std::endl << "* |arg0| = " << rational_to_string_if_exists(arg0Len, arg0Len_exists) << std::endl << "* |arg1| = " << rational_to_string_if_exists(arg1Len, arg1Len_exists) << std::endl; - ); + ); (void)arg1Len_exists; + if (parentLen_exists && !arg0Len_exists) { TRACE("str", tout << "make up len for arg0" << std::endl;); expr_ref implyL11(m.mk_and(ctx.mk_eq_atom(mk_strlen(a_parent), mk_int(parentLen)), @@ -4497,8 +4493,6 @@ namespace smt { } void theory_str::process_unroll_eq_const_str(expr * unrollFunc, expr * constStr) { - ast_manager & m = get_manager(); - if (!u.re.is_unroll(to_app(unrollFunc))) { return; } @@ -4510,8 +4504,8 @@ namespace smt { zstring strValue; u.str.is_string(constStr, strValue); - TRACE("str", tout << "unrollFunc: " << mk_pp(unrollFunc, m) << std::endl - << "constStr: " << mk_pp(constStr, m) << std::endl;); + TRACE("str", tout << "unrollFunc: " << mk_pp(unrollFunc, get_manager()) << std::endl + << "constStr: " << mk_pp(constStr, get_manager()) << std::endl;); if (strValue == "") { return; @@ -4656,35 +4650,25 @@ namespace smt { } } - bool theory_str::get_value(expr* e, rational& val) const { - if (opt_DisableIntegerTheoryIntegration) { - TRACE("str", tout << "WARNING: integer theory integration disabled" << std::endl;); - return false; - } - + bool theory_str::get_arith_value(expr* e, rational& val) const { context& ctx = get_context(); ast_manager & m = get_manager(); - theory_mi_arith* tha = get_th_arith(ctx, m_autil.get_family_id(), e); - if (!tha) { + + // safety + if (!ctx.e_internalized(e)) { + return false; + } + + // if an integer constant exists in the eqc, it should be the root + enode * en_e = ctx.get_enode(e); + enode * root_e = en_e->get_root(); + if (m_autil.is_numeral(root_e->get_owner(), val) && val.is_int()) { + TRACE("str", tout << mk_pp(e, m) << " ~= " << mk_pp(root_e->get_owner(), m) << std::endl;); + return true; + } else { + TRACE("str", tout << "root of eqc of " << mk_pp(e, m) << " is not a numeral" << std::endl;); return false; } - TRACE("str", tout << "checking eqc of " << mk_pp(e, m) << " for arithmetic value" << std::endl;); - expr_ref _val(m); - enode * en_e = ctx.get_enode(e); - enode * it = en_e; - do { - if (m_autil.is_numeral(it->get_owner(), val) && val.is_int()) { - // found an arithmetic term - TRACE("str", tout << mk_pp(it->get_owner(), m) << " is an integer ( ~= " << val << " )" - << std::endl;); - return true; - } else { - TRACE("str", tout << mk_pp(it->get_owner(), m) << " not a numeral" << std::endl;); - } - it = it->get_next(); - } while (it != en_e); - TRACE("str", tout << "no arithmetic values found in eqc" << std::endl;); - return false; } bool theory_str::lower_bound(expr* _e, rational& lo) { @@ -4785,7 +4769,7 @@ namespace smt { } }); - if (ctx.e_internalized(len) && get_value(len, val1)) { + if (ctx.e_internalized(len) && get_arith_value(len, val1)) { val += val1; TRACE("str", tout << "integer theory: subexpression " << mk_ismt2_pp(len, m) << " has length " << val1 << std::endl;); } @@ -4808,17 +4792,16 @@ namespace smt { bool theory_str::in_same_eqc(expr * n1, expr * n2) { if (n1 == n2) return true; context & ctx = get_context(); - ast_manager & m = get_manager(); // similar to get_eqc_value(), make absolutely sure // that we've set this up properly for the context if (!ctx.e_internalized(n1)) { - TRACE("str", tout << "WARNING: expression " << mk_ismt2_pp(n1, m) << " was not internalized" << std::endl;); + TRACE("str", tout << "WARNING: expression " << mk_ismt2_pp(n1, get_manager()) << " was not internalized" << std::endl;); ctx.internalize(n1, false); } if (!ctx.e_internalized(n2)) { - TRACE("str", tout << "WARNING: expression " << mk_ismt2_pp(n2, m) << " was not internalized" << std::endl;); + TRACE("str", tout << "WARNING: expression " << mk_ismt2_pp(n2, get_manager()) << " was not internalized" << std::endl;); ctx.internalize(n2, false); } @@ -4877,7 +4860,7 @@ namespace smt { expr * strAst = itor1->first; expr * substrAst = itor1->second; - expr * boolVar; + expr * boolVar = NULL; if (!contain_pair_bool_map.find(strAst, substrAst, boolVar)) { TRACE("str", tout << "warning: no entry for boolVar in contain_pair_bool_map" << std::endl;); } @@ -5014,7 +4997,7 @@ namespace smt { expr * strAst = itor1->first; expr * substrAst = itor1->second; - expr * boolVar; + expr * boolVar = NULL; if (!contain_pair_bool_map.find(strAst, substrAst, boolVar)) { TRACE("str", tout << "warning: no entry for boolVar in contain_pair_bool_map" << std::endl;); } @@ -5625,8 +5608,7 @@ namespace smt { } void theory_str::print_grounded_concat(expr * node, std::map, std::set > > & groundedMap) { - ast_manager & m = get_manager(); - TRACE("str", tout << mk_pp(node, m) << std::endl;); + TRACE("str", tout << mk_pp(node, get_manager()) << std::endl;); if (groundedMap.find(node) != groundedMap.end()) { std::map, std::set >::iterator itor = groundedMap[node].begin(); for (; itor != groundedMap[node].end(); ++itor) { @@ -5634,13 +5616,13 @@ namespace smt { tout << "\t[grounded] "; std::vector::const_iterator vIt = itor->first.begin(); for (; vIt != itor->first.end(); ++vIt) { - tout << mk_pp(*vIt, m) << ", "; + tout << mk_pp(*vIt, get_manager()) << ", "; } tout << std::endl; tout << "\t[condition] "; std::set::iterator sIt = itor->second.begin(); for (; sIt != itor->second.end(); sIt++) { - tout << mk_pp(*sIt, m) << ", "; + tout << mk_pp(*sIt, get_manager()) << ", "; } tout << std::endl; ); @@ -6936,7 +6918,7 @@ namespace smt { } void theory_str::more_value_tests(expr * valTester, zstring valTesterValue) { - ast_manager & m = get_manager(); + ast_manager & m = get_manager(); (void)m; expr * fVar = valueTester_fvar_map[valTester]; if (m_params.m_UseBinarySearch) { @@ -6991,17 +6973,16 @@ namespace smt { } bool theory_str::free_var_attempt(expr * nn1, expr * nn2) { - ast_manager & m = get_manager(); zstring nn2_str; if (internal_lenTest_vars.contains(nn1) && u.str.is_string(nn2, nn2_str)) { - TRACE("str", tout << "acting on equivalence between length tester var " << mk_ismt2_pp(nn1, m) - << " and constant " << mk_ismt2_pp(nn2, m) << std::endl;); + TRACE("str", tout << "acting on equivalence between length tester var " << mk_pp(nn1, get_manager()) + << " and constant " << mk_pp(nn2, get_manager()) << std::endl;); more_len_tests(nn1, nn2_str); return true; } else if (internal_valTest_vars.contains(nn1) && u.str.is_string(nn2, nn2_str)) { if (nn2_str == "more") { - TRACE("str", tout << "acting on equivalence between value var " << mk_ismt2_pp(nn1, m) - << " and constant " << mk_ismt2_pp(nn2, m) << std::endl;); + TRACE("str", tout << "acting on equivalence between value var " << mk_pp(nn1, get_manager()) + << " and constant " << mk_pp(nn2, get_manager()) << std::endl;); more_value_tests(nn1, nn2_str); } return true; @@ -7302,6 +7283,7 @@ namespace smt { // this might help?? theory_var v = mk_var(n); TRACE("str", tout << "variable " << mk_ismt2_pp(ap, get_manager()) << " is #" << v << std::endl;); + (void)v; } } } else if (ex_sort == bool_sort && !is_quantifier(ex)) { @@ -7388,7 +7370,6 @@ namespace smt { } void theory_str::init_search_eh() { - ast_manager & m = get_manager(); context & ctx = get_context(); TRACE("str", @@ -7396,7 +7377,7 @@ namespace smt { unsigned nFormulas = ctx.get_num_asserted_formulas(); for (unsigned i = 0; i < nFormulas; ++i) { expr * ex = ctx.get_asserted_formula(i); - tout << mk_ismt2_pp(ex, m) << (ctx.is_relevant(ex) ? " (rel)" : " (NOT REL)") << std::endl; + tout << mk_pp(ex, get_manager()) << (ctx.is_relevant(ex) ? " (rel)" : " (NOT REL)") << std::endl; } ); /* @@ -7411,36 +7392,6 @@ namespace smt { set_up_axioms(ex); } - /* - * Similar recursive descent, except over all initially assigned terms. - * This is done to find equalities between terms, etc. that we otherwise - * might not get a chance to see. - */ - - /* - expr_ref_vector assignments(m); - ctx.get_assignments(assignments); - for (expr_ref_vector::iterator i = assignments.begin(); i != assignments.end(); ++i) { - expr * ex = *i; - if (m.is_eq(ex)) { - TRACE("str", tout << "processing assignment " << mk_ismt2_pp(ex, m) << - ": expr is equality" << std::endl;); - app * eq = (app*)ex; - SASSERT(eq->get_num_args() == 2); - expr * lhs = eq->get_arg(0); - expr * rhs = eq->get_arg(1); - - enode * e_lhs = ctx.get_enode(lhs); - enode * e_rhs = ctx.get_enode(rhs); - std::pair eq_pair(e_lhs, e_rhs); - m_str_eq_todo.push_back(eq_pair); - } else { - TRACE("str", tout << "processing assignment " << mk_ismt2_pp(ex, m) - << ": expr ignored" << std::endl;); - } - } - */ - // this might be cheating but we need to make sure that certain maps are populated // before the first call to new_eq_eh() propagate(); @@ -7476,8 +7427,7 @@ namespace smt { } void theory_str::assign_eh(bool_var v, bool is_true) { - context & ctx = get_context(); - TRACE("str", tout << "assert: v" << v << " #" << ctx.bool_var2expr(v)->get_id() << " is_true: " << is_true << std::endl;); + TRACE("str", tout << "assert: v" << v << " #" << get_context().bool_var2expr(v)->get_id() << " is_true: " << is_true << std::endl;); } void theory_str::push_scope_eh() { @@ -7544,7 +7494,6 @@ namespace smt { void theory_str::pop_scope_eh(unsigned num_scopes) { sLevel -= num_scopes; TRACE("str", tout << "pop " << num_scopes << " to " << sLevel << std::endl;); - ast_manager & m = get_manager(); TRACE_CODE(if (is_trace_enabled("t_str_dump_assign_on_scope_change")) { dump_assignments(); }); @@ -7553,10 +7502,9 @@ namespace smt { obj_map >::iterator varItor = cut_var_map.begin(); while (varItor != cut_var_map.end()) { - expr * e = varItor->m_key; std::stack & val = cut_var_map[varItor->m_key]; while ((val.size() > 0) && (val.top()->level != 0) && (val.top()->level >= sLevel)) { - TRACE("str", tout << "remove cut info for " << mk_pp(e, m) << std::endl; print_cut_var(e, tout);); + // TRACE("str", tout << "remove cut info for " << mk_pp(e, get_manager()) << std::endl; print_cut_var(e, tout);); // T_cut * aCut = val.top(); val.pop(); // dealloc(aCut); @@ -7578,8 +7526,7 @@ namespace smt { ptr_vector new_m_basicstr; for (ptr_vector::iterator it = m_basicstr_axiom_todo.begin(); it != m_basicstr_axiom_todo.end(); ++it) { enode * e = *it; - app * a = e->get_owner(); - TRACE("str", tout << "consider deleting " << mk_pp(a, get_manager()) + TRACE("str", tout << "consider deleting " << mk_pp(e->get_owner(), get_manager()) << ", enode scope level is " << e->get_iscope_lvl() << std::endl;); if (e->get_iscope_lvl() <= (unsigned)sLevel) { @@ -8481,7 +8428,7 @@ namespace smt { // check integer theory rational Ival; - bool Ival_exists = get_value(a, Ival); + bool Ival_exists = get_arith_value(a, Ival); if (Ival_exists) { TRACE("str", tout << "integer theory assigns " << mk_pp(a, m) << " = " << Ival.to_string() << std::endl;); // if that value is not -1, we can assert (str.to-int S) = Ival --> S = "Ival" @@ -8652,7 +8599,7 @@ namespace smt { rational lenValue; expr_ref concatlenExpr (mk_strlen(concat), m) ; bool allLeafResolved = true; - if (! get_value(concatlenExpr, lenValue)) { + if (! get_arith_value(concatlenExpr, lenValue)) { // the length fo concat is unresolved yet if (get_len_value(concat, lenValue)) { // but all leaf nodes have length information @@ -8689,7 +8636,7 @@ namespace smt { expr * var = *it; rational lenValue; expr_ref varlen (mk_strlen(var), m) ; - if (! get_value(varlen, lenValue)) { + if (! get_arith_value(varlen, lenValue)) { if (propagate_length_within_eqc(var)) { axiomAdded = true; } @@ -8862,7 +8809,7 @@ namespace smt { continue; } bool hasEqcValue = false; - expr * eqcString = get_eqc_value(itor->first, hasEqcValue); + get_eqc_value(itor->first, hasEqcValue); if (!hasEqcValue) { TRACE("str", tout << "found free variable " << mk_pp(itor->first, m) << std::endl;); needToAssignFreeVars = true; @@ -8870,7 +8817,7 @@ namespace smt { // break; } else { // debug - TRACE("str", tout << "variable " << mk_pp(itor->first, m) << " = " << mk_pp(eqcString, m) << std::endl;); + // TRACE("str", tout << "variable " << mk_pp(itor->first, m) << " = " << mk_pp(eqcString, m) << std::endl;); } } } @@ -9105,7 +9052,6 @@ namespace smt { } void theory_str::print_value_tester_list(svector > & testerList) { - ast_manager & m = get_manager(); TRACE("str", int ss = testerList.size(); tout << "valueTesterList = {"; @@ -9114,7 +9060,7 @@ namespace smt { tout << std::endl; } tout << "(" << testerList[i].first << ", "; - tout << mk_ismt2_pp(testerList[i].second, m); + tout << mk_pp(testerList[i].second, get_manager()); tout << "), "; } tout << std::endl << "}" << std::endl; @@ -9194,7 +9140,7 @@ namespace smt { // ---------------------------------------------------------------------------------------- int len = atoi(lenStr.encode().c_str()); bool coverAll = false; - vector options; + vector options; int_vector base; TRACE("str", tout @@ -9217,8 +9163,8 @@ namespace smt { coverAll = get_next_val_encode(val_range_map[lastestValIndi], base); } - long long l = (tries) * distance; - long long h = l; + size_t l = (tries) * distance; + size_t h = l; for (int i = 0; i < distance; i++) { if (coverAll) break; @@ -9239,10 +9185,10 @@ namespace smt { ); // ---------------------------------------------------------------------------------------- - + expr_ref_vector orList(m), andList(m); - for (long long i = l; i < h; i++) { + for (size_t i = l; i < h; i++) { orList.push_back(m.mk_eq(val_indicator, mk_string(longlong_to_string(i).c_str()) )); if (m_params.m_AggressiveValueTesting) { literal lit = mk_eq(val_indicator, mk_string(longlong_to_string(i).c_str()), false); @@ -9346,8 +9292,7 @@ namespace smt { } bool anEqcHasValue = false; - // Z3_ast anEqc = get_eqc_value(t, aTester, anEqcHasValue); - expr * aTester_eqc_value = get_eqc_value(aTester, anEqcHasValue); + get_eqc_value(aTester, anEqcHasValue); if (!anEqcHasValue) { TRACE("str", tout << "value tester " << mk_ismt2_pp(aTester, m) << " doesn't have an equivalence class value." << std::endl;); @@ -9359,8 +9304,8 @@ namespace smt { << mk_ismt2_pp(makeupAssert, m) << std::endl;); assert_axiom(makeupAssert); } else { - TRACE("str", tout << "value tester " << mk_ismt2_pp(aTester, m) - << " == " << mk_ismt2_pp(aTester_eqc_value, m) << std::endl;); + // TRACE("str", tout << "value tester " << mk_ismt2_pp(aTester, m) + // << " == " << mk_ismt2_pp(aTester_eqc_value, m) << std::endl;); } } @@ -9514,8 +9459,8 @@ namespace smt { items.reset(); rational low, high; - bool low_exists = lower_bound(cntInUnr, low); - bool high_exists = upper_bound(cntInUnr, high); + bool low_exists = lower_bound(cntInUnr, low); (void)low_exists; + bool high_exists = upper_bound(cntInUnr, high); (void)high_exists; TRACE("str", tout << "unroll " << mk_pp(unrFunc, mgr) << std::endl; @@ -9523,7 +9468,7 @@ namespace smt { bool unrLenValue_exists = get_len_value(unrFunc, unrLenValue); tout << "unroll length: " << (unrLenValue_exists ? unrLenValue.to_string() : "?") << std::endl; rational cntInUnrValue; - bool cntHasValue = get_value(cntInUnr, cntInUnrValue); + bool cntHasValue = get_arith_value(cntInUnr, cntInUnrValue); tout << "unroll count: " << (cntHasValue ? cntInUnrValue.to_string() : "?") << " low = " << (low_exists ? low.to_string() : "?") @@ -10266,7 +10211,7 @@ namespace smt { } else { tout << "no eqc string constant"; } - tout << std::endl;); + tout << std::endl;); (void)effectiveInScope; if (effectiveLenInd == lenTesterInCbEq) { effectiveLenIndiStr = lenTesterValue; } else { @@ -10351,7 +10296,6 @@ namespace smt { void theory_str::process_free_var(std::map & freeVar_map) { context & ctx = get_context(); - ast_manager & m = get_manager(); std::set eqcRepSet; std::set leafVarSet; @@ -10378,8 +10322,8 @@ namespace smt { } } if (duplicated && dupVar != NULL) { - TRACE("str", tout << "Duplicated free variable found:" << mk_ismt2_pp(freeVar, m) - << " = " << mk_ismt2_pp(dupVar, m) << " (SKIP)" << std::endl;); + TRACE("str", tout << "Duplicated free variable found:" << mk_pp(freeVar, get_manager()) + << " = " << mk_ismt2_pp(dupVar, get_manager()) << " (SKIP)" << std::endl;); continue; } else { eqcRepSet.insert(freeVar); diff --git a/src/smt/theory_str.h b/src/smt/theory_str.h index 0bbc44ab8..7f39efa70 100644 --- a/src/smt/theory_str.h +++ b/src/smt/theory_str.h @@ -219,7 +219,7 @@ protected: /* * If DisableIntegerTheoryIntegration is set to true, * ALL calls to the integer theory integration methods - * (get_value, get_len_value, lower_bound, upper_bound) + * (get_arith_value, get_len_value, lower_bound, upper_bound) * will ignore what the arithmetic solver believes about length terms, * and will return no information. * @@ -464,7 +464,7 @@ protected: bool in_same_eqc(expr * n1, expr * n2); expr * collect_eq_nodes(expr * n, expr_ref_vector & eqcSet); - bool get_value(expr* e, rational& val) const; + bool get_arith_value(expr* e, rational& val) const; bool get_len_value(expr* e, rational& val); bool lower_bound(expr* _e, rational& lo); bool upper_bound(expr* _e, rational& hi); diff --git a/contrib/cmake/src/solver/CMakeLists.txt b/src/solver/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/solver/CMakeLists.txt rename to src/solver/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/CMakeLists.txt b/src/tactic/CMakeLists.txt similarity index 87% rename from contrib/cmake/src/tactic/CMakeLists.txt rename to src/tactic/CMakeLists.txt index 324d8089b..e7cfdb644 100644 --- a/contrib/cmake/src/tactic/CMakeLists.txt +++ b/src/tactic/CMakeLists.txt @@ -18,4 +18,8 @@ z3_add_component(tactic COMPONENT_DEPENDENCIES ast model + TACTIC_HEADERS + probe.h + sine_filter.h + tactic.h ) diff --git a/contrib/cmake/src/tactic/aig/CMakeLists.txt b/src/tactic/aig/CMakeLists.txt similarity index 75% rename from contrib/cmake/src/tactic/aig/CMakeLists.txt rename to src/tactic/aig/CMakeLists.txt index 1e1a0d266..51ea9b6d3 100644 --- a/contrib/cmake/src/tactic/aig/CMakeLists.txt +++ b/src/tactic/aig/CMakeLists.txt @@ -4,4 +4,6 @@ z3_add_component(aig_tactic aig_tactic.cpp COMPONENT_DEPENDENCIES tactic + TACTIC_HEADERS + aig_tactic.h ) diff --git a/contrib/cmake/src/tactic/arith/CMakeLists.txt b/src/tactic/arith/CMakeLists.txt similarity index 62% rename from contrib/cmake/src/tactic/arith/CMakeLists.txt rename to src/tactic/arith/CMakeLists.txt index cdc42367a..335020838 100644 --- a/contrib/cmake/src/tactic/arith/CMakeLists.txt +++ b/src/tactic/arith/CMakeLists.txt @@ -28,4 +28,23 @@ z3_add_component(arith_tactics COMPONENT_DEPENDENCIES core_tactics sat + TACTIC_HEADERS + add_bounds_tactic.h + card2bv_tactic.h + degree_shift_tactic.h + diff_neq_tactic.h + elim01_tactic.h + eq2bv_tactic.h + factor_tactic.h + fix_dl_var_tactic.h + fm_tactic.h + lia2pb_tactic.h + lia2card_tactic.h + nla2bv_tactic.h + normalize_bounds_tactic.h + pb2bv_tactic.h + probe_arith.h + propagate_ineqs_tactic.h + purify_arith_tactic.h + recover_01_tactic.h ) diff --git a/src/tactic/arith/elim01_tactic.cpp b/src/tactic/arith/elim01_tactic.cpp index 1aef52d78..e00b1e9c0 100644 --- a/src/tactic/arith/elim01_tactic.cpp +++ b/src/tactic/arith/elim01_tactic.cpp @@ -169,7 +169,7 @@ public: for (; bit != bend; ++bit) { if (!is_app(*bit)) continue; app* x = to_app(*bit); - bool s1, s2; + bool s1 = false, s2 = false; rational lo, hi; if (a.is_int(x) && bounds.has_lower(x, lo, s1) && !s1 && zero <= lo && diff --git a/src/tactic/arith/lia2card_tactic.cpp b/src/tactic/arith/lia2card_tactic.cpp index 4c2e0dead..8f37a8d5e 100644 --- a/src/tactic/arith/lia2card_tactic.cpp +++ b/src/tactic/arith/lia2card_tactic.cpp @@ -176,7 +176,7 @@ public: bound_manager::iterator bit = bounds.begin(), bend = bounds.end(); for (; bit != bend; ++bit) { expr* x = *bit; - bool s1, s2; + bool s1 = false, s2 = false; rational lo, hi; if (a.is_int(x) && bounds.has_lower(x, lo, s1) && !s1 && lo.is_zero() && diff --git a/contrib/cmake/src/tactic/bv/CMakeLists.txt b/src/tactic/bv/CMakeLists.txt similarity index 63% rename from contrib/cmake/src/tactic/bv/CMakeLists.txt rename to src/tactic/bv/CMakeLists.txt index 90ed65e3f..e9f0927d5 100644 --- a/contrib/cmake/src/tactic/bv/CMakeLists.txt +++ b/src/tactic/bv/CMakeLists.txt @@ -15,4 +15,14 @@ z3_add_component(bv_tactics bit_blaster core_tactics tactic + TACTIC_HEADERS + bit_blaster_tactic.h + bv1_blaster_tactic.h + bv_bound_chk_tactic.h + bv_bounds_tactic.h + bv_size_reduction_tactic.h + bvarray2uf_tactic.h + dt2bv_tactic.h + elim_small_bv_tactic.h + max_bv_sharing_tactic.h ) diff --git a/src/tactic/bv/bv_bounds_tactic.cpp b/src/tactic/bv/bv_bounds_tactic.cpp index 1b324b2eb..94c9935b9 100644 --- a/src/tactic/bv/bv_bounds_tactic.cpp +++ b/src/tactic/bv/bv_bounds_tactic.cpp @@ -234,6 +234,7 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier { return false; } +#if 0 expr_set* get_expr_vars(expr* t) { unsigned id = t->get_id(); m_expr_vars.reserve(id + 1); @@ -259,7 +260,9 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier { } return set; } +#endif +#if 0 expr_cnt* get_expr_bounds(expr* t) { unsigned id = t->get_id(); m_bound_exprs.reserve(id + 1); @@ -288,6 +291,7 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier { } return set; } +#endif public: bv_bounds_simplifier(ast_manager& m, params_ref const& p) : m(m), m_params(p), m_bv(m) { @@ -392,17 +396,86 @@ public: return result != 0; } + // check if t contains v + ptr_vector todo; + bool contains(expr* t, expr* v) { + ast_fast_mark1 mark; + todo.push_back(t); + while (!todo.empty()) { + t = todo.back(); + todo.pop_back(); + if (mark.is_marked(t)) { + continue; + } + if (t == v) { + todo.reset(); + return true; + } + mark.mark(t); + + if (!is_app(t)) { + continue; + } + app* a = to_app(t); + todo.append(a->get_num_args(), a->get_args()); + } + return false; + } + + bool contains_bound(expr* t) { + ast_fast_mark1 mark1; + ast_fast_mark2 mark2; + + todo.push_back(t); + while (!todo.empty()) { + t = todo.back(); + todo.pop_back(); + if (mark1.is_marked(t)) { + continue; + } + mark1.mark(t); + + if (!is_app(t)) { + continue; + } + interval b; + expr* e; + if (is_bound(t, e, b)) { + if (mark2.is_marked(e)) { + todo.reset(); + return true; + } + mark2.mark(e); + if (m_bound.contains(e)) { + todo.reset(); + return true; + } + } + + app* a = to_app(t); + todo.append(a->get_num_args(), a->get_args()); + } + return false; + } + virtual bool may_simplify(expr* t) { if (m_bv.is_numeral(t)) return false; while (m.is_not(t, t)); + for (auto & v : m_bound) { + if (contains(t, v.m_key)) return true; + } + +#if 0 expr_set* used_exprs = get_expr_vars(t); for (map::iterator I = m_bound.begin(), E = m_bound.end(); I != E; ++I) { + if (contains(t, I->m_key)) return true; if (I->m_value.is_singleton() && used_exprs->contains(I->m_key)) return true; } +#endif expr* t1; interval b; @@ -411,11 +484,16 @@ public: return b.is_full() || m_bound.contains(t1); } + if (contains_bound(t)) { + return true; + } +#if 0 expr_cnt* bounds = get_expr_bounds(t); for (expr_cnt::iterator I = bounds->begin(), E = bounds->end(); I != E; ++I) { if (I->m_value > 1 || m_bound.contains(I->m_key)) return true; } +#endif return false; } diff --git a/src/tactic/bv/dt2bv_tactic.cpp b/src/tactic/bv/dt2bv_tactic.cpp index 2b9cfb7f3..3ae72215f 100644 --- a/src/tactic/bv/dt2bv_tactic.cpp +++ b/src/tactic/bv/dt2bv_tactic.cpp @@ -30,6 +30,7 @@ Revision History: #include "var_subst.h" #include "ast_util.h" #include "enum2bv_rewriter.h" +#include "ast_pp.h" class dt2bv_tactic : public tactic { @@ -53,30 +54,32 @@ class dt2bv_tactic : public tactic { void operator()(app* a) { if (m.is_eq(a)) { - return; + // no-op } - if (m.is_distinct(a)) { - return; + else if (m.is_distinct(a)) { + // no-op } - if (m_t.m_dt.is_recognizer(a->get_decl()) && + else if (m_t.m_dt.is_recognizer(a->get_decl()) && m_t.is_fd(a->get_arg(0))) { m_t.m_fd_sorts.insert(get_sort(a->get_arg(0))); - return; } - - if (m_t.is_fd(a) && a->get_num_args() > 0) { + else if (m_t.is_fd(a) && a->get_num_args() > 0) { m_t.m_non_fd_sorts.insert(get_sort(a)); + args_cannot_be_fd(a); } else if (m_t.is_fd(a)) { m_t.m_fd_sorts.insert(get_sort(a)); } else { - unsigned sz = a->get_num_args(); - for (unsigned i = 0; i < sz; ++i) { - if (m_t.is_fd(a->get_arg(i))) { - m_t.m_non_fd_sorts.insert(get_sort(a->get_arg(i))); - } - } + args_cannot_be_fd(a); + } + } + + void args_cannot_be_fd(app* a) { + for (expr* arg : *a) { + if (m_t.is_fd(arg)) { + m_t.m_non_fd_sorts.insert(get_sort(arg)); + } } } diff --git a/contrib/cmake/src/tactic/core/CMakeLists.txt b/src/tactic/core/CMakeLists.txt similarity index 54% rename from contrib/cmake/src/tactic/core/CMakeLists.txt rename to src/tactic/core/CMakeLists.txt index fcd26bd84..1f766bd47 100644 --- a/contrib/cmake/src/tactic/core/CMakeLists.txt +++ b/src/tactic/core/CMakeLists.txt @@ -3,7 +3,7 @@ z3_add_component(core_tactics blast_term_ite_tactic.cpp cofactor_elim_term_ite.cpp cofactor_term_ite_tactic.cpp - collect_statistics_tactic.cpp + collect_statistics_tactic.cpp ctx_simplify_tactic.cpp der_tactic.cpp distribute_forall_tactic.cpp @@ -23,5 +23,24 @@ z3_add_component(core_tactics COMPONENT_DEPENDENCIES normal_forms tactic + TACTIC_HEADERS + blast_term_ite_tactic.h + cofactor_term_ite_tactic.h + collect_statistics_tactic.h + ctx_simplify_tactic.h + der_tactic.h + distribute_forall_tactic.h + elim_term_ite_tactic.h + elim_uncnstr_tactic.h + nnf_tactic.h + occf_tactic.h + pb_preprocess_tactic.h + propagate_values_tactic.h + reduce_args_tactic.h + simplify_tactic.h + solve_eqs_tactic.h + split_clause_tactic.h + symmetry_reduce_tactic.h + tseitin_cnf_tactic.h ) diff --git a/src/tactic/core/blast_term_ite_tactic.cpp b/src/tactic/core/blast_term_ite_tactic.cpp index ea59641c9..483b59776 100644 --- a/src/tactic/core/blast_term_ite_tactic.cpp +++ b/src/tactic/core/blast_term_ite_tactic.cpp @@ -62,14 +62,14 @@ class blast_term_ite_tactic : public tactic { for (unsigned i = 0; i < num_args; ++i) { expr* c, *t, *e; if (!m.is_bool(args[i]) && m.is_ite(args[i], c, t, e)) { - enable_trace("blast_term_ite"); + // enable_trace("blast_term_ite"); TRACE("blast_term_ite", result = m.mk_app(f, num_args, args); tout << result << "\n";); expr_ref e1(m), e2(m); ptr_vector args1(num_args, args); args1[i] = t; ++m_num_fresh; e1 = m.mk_app(f, num_args, args1.c_ptr()); - if (t == e) { + if (m.are_equal(t,e)) { result = e1; return BR_REWRITE1; } diff --git a/src/tactic/core/collect_statistics_tactic.cpp b/src/tactic/core/collect_statistics_tactic.cpp index 8e8879fef..3b820de7a 100644 --- a/src/tactic/core/collect_statistics_tactic.cpp +++ b/src/tactic/core/collect_statistics_tactic.cpp @@ -47,10 +47,10 @@ class collect_statistics_tactic : public tactic { public: collect_statistics_tactic(ast_manager & m, params_ref const & p) : - m(m), + m(m), m_params(p) { - } - + } + virtual ~collect_statistics_tactic() {} virtual tactic * translate(ast_manager & m_) { @@ -60,21 +60,21 @@ public: virtual void updt_params(params_ref const & p) { m_params = p; } - + virtual void collect_param_descrs(param_descrs & r) {} virtual void operator()(goal_ref const & g, goal_ref_buffer & result, - model_converter_ref & mc, proof_converter_ref & pc, + model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { mc = 0; - tactic_report report("collect-statistics", *g); - + tactic_report report("collect-statistics", *g); + collect_proc cp(m, m_stats); - expr_mark visited; + expr_mark visited; const unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) for_each_expr(cp, visited, g->form(i)); - + std::cout << "(" << std::endl; stats_type::iterator it = m_stats.begin(); stats_type::iterator end = m_stats.end(); @@ -84,7 +84,7 @@ public: g->inc_depth(); result.push_back(g.get()); - } + } virtual void cleanup() {} @@ -98,11 +98,12 @@ protected: class collect_proc { public: ast_manager & m; - stats_type & m_stats; + stats_type & m_stats; obj_hashtable m_seen_sorts; obj_hashtable m_seen_func_decls; + unsigned m_qdepth; - collect_proc(ast_manager & m, stats_type & s) : m(m), m_stats(s) {} + collect_proc(ast_manager & m, stats_type & s) : m(m), m_stats(s), m_qdepth(0) {} void operator()(var * v) { m_stats["bound-variables"]++; @@ -113,7 +114,18 @@ protected: m_stats["quantifiers"]++; SASSERT(is_app(q->get_expr())); app * body = to_app(q->get_expr()); + if (q->is_forall()) + m_stats["forall-variables"] += q->get_num_decls(); + else + m_stats["exists-variables"] += q->get_num_decls(); + m_stats["patterns"] += q->get_num_patterns(); + m_stats["no-patterns"] += q->get_num_no_patterns(); + m_qdepth++; + if (m_stats.find("max-quantification-depth") == m_stats.end() || + m_stats["max-quantification-depth"] < m_qdepth) + m_stats["max-quantification-depth"] = m_qdepth; this->operator()(body); + m_qdepth--; } void operator()(app * n) { @@ -121,7 +133,7 @@ protected: this->operator()(n->get_decl()); } - void operator()(sort * s) { + void operator()(sort * s) { if (m.is_uninterp(s)) { if (!m_seen_sorts.contains(s)) { m_stats["uninterpreted-sorts"]++; @@ -135,7 +147,7 @@ protected: std::stringstream ss; ss << "(declare-sort " << mk_ismt2_pp(s, m, prms) << ")"; m_stats[ss.str()]++; - + if (s->get_info()->get_num_parameters() > 0) { std::stringstream ssname; ssname << "(declare-sort (_ " << s->get_name() << " *))"; diff --git a/contrib/cmake/src/tactic/fpa/CMakeLists.txt b/src/tactic/fpa/CMakeLists.txt similarity index 81% rename from contrib/cmake/src/tactic/fpa/CMakeLists.txt rename to src/tactic/fpa/CMakeLists.txt index d93cd5b82..a54212235 100644 --- a/contrib/cmake/src/tactic/fpa/CMakeLists.txt +++ b/src/tactic/fpa/CMakeLists.txt @@ -11,4 +11,7 @@ z3_add_component(fpa_tactics sat_tactic smtlogic_tactics smt_tactic + TACTIC_HEADERS + fpa2bv_tactic.h + qffp_tactic.h ) diff --git a/src/tactic/goal.cpp b/src/tactic/goal.cpp index af58d8331..9a2087437 100644 --- a/src/tactic/goal.cpp +++ b/src/tactic/goal.cpp @@ -137,7 +137,8 @@ void goal::push_back(expr * f, proof * pr, expr_dependency * d) { } void goal::quick_process(bool save_first, expr_ref& f, expr_dependency * d) { - if (!m().is_and(f) && !(m().is_not(f) && m().is_or(to_app(f)->get_arg(0)))) { + expr* g = 0; + if (!m().is_and(f) && !(m().is_not(f, g) && m().is_or(g))) { if (!save_first) { push_back(f, 0, d); } @@ -170,8 +171,8 @@ void goal::quick_process(bool save_first, expr_ref& f, expr_dependency * d) { todo.push_back(expr_pol(t->get_arg(i), false)); } } - else if (m().is_not(curr)) { - todo.push_back(expr_pol(to_app(curr)->get_arg(0), !pol)); + else if (m().is_not(curr, g)) { + todo.push_back(expr_pol(g, !pol)); } else { if (!pol) { diff --git a/contrib/cmake/src/tactic/nlsat_smt/CMakeLists.txt b/src/tactic/nlsat_smt/CMakeLists.txt similarity index 76% rename from contrib/cmake/src/tactic/nlsat_smt/CMakeLists.txt rename to src/tactic/nlsat_smt/CMakeLists.txt index e28b11966..ccfc0e3ef 100644 --- a/contrib/cmake/src/tactic/nlsat_smt/CMakeLists.txt +++ b/src/tactic/nlsat_smt/CMakeLists.txt @@ -4,4 +4,6 @@ z3_add_component(nlsat_smt_tactic COMPONENT_DEPENDENCIES nlsat_tactic smt_tactic + TACTIC_HEADERS + nl_purify_tactic.h ) diff --git a/contrib/cmake/src/tactic/portfolio/CMakeLists.txt b/src/tactic/portfolio/CMakeLists.txt similarity index 89% rename from contrib/cmake/src/tactic/portfolio/CMakeLists.txt rename to src/tactic/portfolio/CMakeLists.txt index c6f621f25..a8a9b2bba 100644 --- a/contrib/cmake/src/tactic/portfolio/CMakeLists.txt +++ b/src/tactic/portfolio/CMakeLists.txt @@ -16,4 +16,6 @@ z3_add_component(portfolio smtlogic_tactics subpaving_tactic ufbv_tactic + TACTIC_HEADERS + default_tactic.h ) diff --git a/src/tactic/portfolio/bounded_int2bv_solver.cpp b/src/tactic/portfolio/bounded_int2bv_solver.cpp index c8d5d1eb3..70fa9dba8 100644 --- a/src/tactic/portfolio/bounded_int2bv_solver.cpp +++ b/src/tactic/portfolio/bounded_int2bv_solver.cpp @@ -183,7 +183,7 @@ public: // translate bit-vector consequences back to integer values for (unsigned i = 0; i < consequences.size(); ++i) { - expr* a, *b, *u, *v; + expr* a = 0, *b = 0, *u = 0, *v = 0; func_decl* f; rational num; unsigned bvsize; @@ -243,7 +243,7 @@ private: for (; it != end; ++it) { expr* e = *it; rational lo, hi; - bool s1, s2; + bool s1 = false, s2 = false; SASSERT(is_uninterp_const(e)); func_decl* f = to_app(e)->get_decl(); diff --git a/src/tactic/portfolio/enum2bv_solver.cpp b/src/tactic/portfolio/enum2bv_solver.cpp index 353ea4441..6c063d6c3 100644 --- a/src/tactic/portfolio/enum2bv_solver.cpp +++ b/src/tactic/portfolio/enum2bv_solver.cpp @@ -128,7 +128,7 @@ public: // translate enumeration constants to bit-vectors. for (unsigned i = 0; i < vars.size(); ++i) { - func_decl* f; + func_decl* f = 0; if (is_app(vars[i]) && is_uninterp_const(vars[i]) && m_rewriter.enum2bv().find(to_app(vars[i])->get_decl(), f)) { bvars.push_back(m.mk_const(f)); } @@ -140,7 +140,7 @@ public: // translate bit-vector consequences back to enumeration types for (unsigned i = 0; i < consequences.size(); ++i) { - expr* a, *b, *u, *v; + expr* a = 0, *b = 0, *u = 0, *v = 0; func_decl* f; rational num; unsigned bvsize; diff --git a/contrib/cmake/src/tactic/sls/CMakeLists.txt b/src/tactic/sls/CMakeLists.txt similarity index 86% rename from contrib/cmake/src/tactic/sls/CMakeLists.txt rename to src/tactic/sls/CMakeLists.txt index 8b720b333..436b1742f 100644 --- a/contrib/cmake/src/tactic/sls/CMakeLists.txt +++ b/src/tactic/sls/CMakeLists.txt @@ -10,4 +10,6 @@ z3_add_component(sls_tactic tactic PYG_FILES sls_params.pyg + TACTIC_HEADERS + sls_tactic.h ) diff --git a/contrib/cmake/src/tactic/smtlogics/CMakeLists.txt b/src/tactic/smtlogics/CMakeLists.txt similarity index 68% rename from contrib/cmake/src/tactic/smtlogics/CMakeLists.txt rename to src/tactic/smtlogics/CMakeLists.txt index 840dd008a..c90fd7468 100644 --- a/contrib/cmake/src/tactic/smtlogics/CMakeLists.txt +++ b/src/tactic/smtlogics/CMakeLists.txt @@ -28,4 +28,18 @@ z3_add_component(smtlogic_tactics smt_tactic PYG_FILES qfufbv_tactic_params.pyg + TACTIC_HEADERS + nra_tactic.h + qfaufbv_tactic.h + qfauflia_tactic.h + qfbv_tactic.h + qfidl_tactic.h + qflia_tactic.h + qflra_tactic.h + qfnia_tactic.h + qfnra_tactic.h + qfuf_tactic.h + qfufbv_tactic.h + qfufnra_tactic.h + quant_tactics.h ) diff --git a/contrib/cmake/src/tactic/ufbv/CMakeLists.txt b/src/tactic/ufbv/CMakeLists.txt similarity index 70% rename from contrib/cmake/src/tactic/ufbv/CMakeLists.txt rename to src/tactic/ufbv/CMakeLists.txt index c1d6daaaa..511dc2b2d 100644 --- a/contrib/cmake/src/tactic/ufbv/CMakeLists.txt +++ b/src/tactic/ufbv/CMakeLists.txt @@ -11,4 +11,9 @@ z3_add_component(ufbv_tactic normal_forms rewriter smt_tactic + TACTIC_HEADERS + macro_finder_tactic.h + quasi_macros_tactic.h + ufbv_rewriter_tactic.h + ufbv_tactic.h ) diff --git a/contrib/cmake/src/test/CMakeLists.txt b/src/test/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/test/CMakeLists.txt rename to src/test/CMakeLists.txt diff --git a/src/test/algebraic.cpp b/src/test/algebraic.cpp index af7270825..076d7ec73 100644 --- a/src/test/algebraic.cpp +++ b/src/test/algebraic.cpp @@ -54,7 +54,7 @@ static void tst1() { std::cout << "p: " << p << "\n"; am.isolate_roots(p, rs1); display_anums(std::cout, rs1); - SASSERT(rs1.size() == 1); + ENSURE(rs1.size() == 1); std::cout.flush(); p = (x^2) - 2; @@ -62,7 +62,7 @@ static void tst1() { rs1.reset(); am.isolate_roots(p, rs1); display_anums(std::cout, rs1); - SASSERT(rs1.size() == 2); + ENSURE(rs1.size() == 2); scoped_anum sqrt2(am); am.set(sqrt2, rs1[1]); @@ -88,7 +88,7 @@ static void tst1() { rs1.reset(); am.isolate_roots(p, rs1); display_anums(std::cout, rs1); - SASSERT(rs1.size() == 3); + ENSURE(rs1.size() == 3); scoped_anum gauss(am); am.set(gauss, rs1[1]); @@ -104,7 +104,7 @@ static void tst1() { rs1.reset(); am.isolate_roots(p, rs1); display_anums(std::cout, rs1); - SASSERT(rs1.size() == 4); + ENSURE(rs1.size() == 4); scoped_anum hidden_sqrt2(am); am.set(hidden_sqrt2, rs1[2]); @@ -116,8 +116,8 @@ static void tst1() { std::cout << "sqrt(2)^4: " << (sqrt2^4) << "\n"; - SASSERT(is_int(power(sqrt2, 4))); - SASSERT(power(sqrt2, 4) == 4); + ENSURE(is_int(power(sqrt2, 4))); + ENSURE(power(sqrt2, 4) == 4); scoped_anum sqrt2_gauss(am); am.add(sqrt2, gauss, sqrt2_gauss); @@ -242,9 +242,9 @@ static void tst_wilkinson() { std::cout << "p: " << p << "\n"; am.isolate_roots(p, rs1); display_anums(std::cout, rs1); - SASSERT(rs1.size() == 20); + ENSURE(rs1.size() == 20); for (unsigned i = 0; i < rs1.size(); i++) { - SASSERT(am.is_int(rs1[i])); + ENSURE(am.is_int(rs1[i])); } } @@ -328,9 +328,9 @@ static void tst_eval_sign(polynomial_ref const & p, anum_manager & am, std::cout << "x1 -> "; am.display_root(std::cout, v1); std::cout << "\n"; std::cout << "x2 -> "; am.display_root(std::cout, v2); std::cout << "\n"; int s = am.eval_sign_at(p, x2v); - SASSERT((s == 0) == (expected == 0)); - SASSERT((s < 0) == (expected < 0)); - SASSERT((s > 0) == (expected > 0)); + ENSURE((s == 0) == (expected == 0)); + ENSURE((s < 0) == (expected < 0)); + ENSURE((s > 0) == (expected > 0)); std::cout << "sign: " << s << "\n"; } @@ -399,7 +399,7 @@ static void tst_isolate_roots(polynomial_ref const & p, anum_manager & am, scoped_anum_vector roots(am); svector signs; am.isolate_roots(p, x2v, roots, signs); - SASSERT(roots.size() + 1 == signs.size()); + ENSURE(roots.size() + 1 == signs.size()); std::cout << "roots:\n"; for (unsigned i = 0; i < roots.size(); i++) { am.display_root(std::cout, roots[i]); std::cout << " "; am.display_decimal(std::cout, roots[i]); std::cout << "\n"; diff --git a/src/test/api.cpp b/src/test/api.cpp index 667d10bc5..f691a8701 100644 --- a/src/test/api.cpp +++ b/src/test/api.cpp @@ -101,7 +101,7 @@ static void test_mk_distinct() { Z3_sort bv32 = Z3_mk_bv_sort(ctx, 32); Z3_ast args[] = { Z3_mk_int64(ctx, 0, bv8), Z3_mk_int64(ctx, 0, bv32) }; Z3_ast d = Z3_mk_distinct(ctx, 2, args); - SASSERT(cb_called); + ENSURE(cb_called); Z3_del_config(cfg); Z3_del_context(ctx); diff --git a/src/test/arith_rewriter.cpp b/src/test/arith_rewriter.cpp index 5ed7c3501..6bdb11d48 100644 --- a/src/test/arith_rewriter.cpp +++ b/src/test/arith_rewriter.cpp @@ -27,7 +27,7 @@ static expr_ref parse_fml(ast_manager& m, char const* str) { << "(assert " << str << ")\n"; std::istringstream is(buffer.str()); VERIFY(parse_smt2_commands(ctx, is)); - SASSERT(ctx.begin_assertions() != ctx.end_assertions()); + ENSURE(ctx.begin_assertions() != ctx.end_assertions()); result = *ctx.begin_assertions(); return result; } diff --git a/src/test/ast.cpp b/src/test/ast.cpp index b59e2a612..20a1007a4 100644 --- a/src/test/ast.cpp +++ b/src/test/ast.cpp @@ -29,21 +29,21 @@ static void tst1() { expr_ref i1(m.mk_app(fid, OP_AND, a.get(), c.get()), m); expr_ref i2(m.mk_app(fid, OP_AND, a.get(), c.get()), m); expr_ref i3(m.mk_app(fid, OP_OR, a.get(), c.get()), m); - SASSERT(i1.get() == i2.get()); - SASSERT(i1.get() != i3.get()); + ENSURE(i1.get() == i2.get()); + ENSURE(i1.get() != i3.get()); // TODO use smart pointers to track references // ast_manager m; // ast_ref n1(m.mk_numeral(rational(2,3)), m); // ast_ref n2(m.mk_numeral(rational(2,3)), m); -// SASSERT(n1 == n2); +// ENSURE(n1 == n2); // ast_ref n3(m.mk_numeral(rational(1,2)), m); -// SASSERT(n1 != n3); +// ENSURE(n1 != n3); // ast_ref v1 (m.mk_var(1), m); // ast_ref v2 (m.mk_var(2), m); // ast_ref v3 (m.mk_var(1), m); -// SASSERT(v1 != v2); -// SASSERT(v1 == v3); +// ENSURE(v1 != v2); +// ENSURE(v1 == v3); // TRACE("ast", tout << "reseting v1\n";); // v1.reset(); // TRACE("ast", tout << "overwriting v3\n";); @@ -59,7 +59,7 @@ static void tst1() { // ast_ref foo_x(m.mk_const(foo_decl.get(), x.get()), m); // ast_ref foo_foo_x(m.mk_const(foo_decl.get(), foo_x.get()), m); // ast_ref foo_foo_x2(m.mk_const(foo_decl.get(), m.mk_const(foo_decl.get(), m.mk_const(x_decl.get()))), m); -// SASSERT(foo_foo_x2 == foo_foo_x); +// ENSURE(foo_foo_x2 == foo_foo_x); } static void tst2() { @@ -70,13 +70,13 @@ static void tst2() { // m_nodes.push_back(m.mk_numeral(rational(1,2))); // m_nodes.push_back(m.mk_var(2)); // m_nodes[1] = m.mk_var(3); -// SASSERT(m_nodes[1]->kind() == AST_VAR); -// SASSERT(m_nodes.get(1)->kind() == AST_VAR); +// ENSURE(m_nodes[1]->kind() == AST_VAR); +// ENSURE(m_nodes.get(1)->kind() == AST_VAR); // m_nodes.pop_back(); -// SASSERT(m_nodes.size() == 2); -// SASSERT(!m_nodes.empty()); +// ENSURE(m_nodes.size() == 2); +// ENSURE(!m_nodes.empty()); // m_nodes.set(1, m.mk_var(4)); -// SASSERT(&(m_nodes.get_manager()) == &m); +// ENSURE(&(m_nodes.get_manager()) == &m); } static void tst3() { @@ -95,16 +95,16 @@ static void tst4() { // #ifdef Z3DEBUG // int r; // #endif -// SASSERT(!wm1.find(n1, r)); +// ENSURE(!wm1.find(n1, r)); // wm1.insert(n2, 10); -// SASSERT(!wm1.find(n1, r)); -// SASSERT(wm1.find(n2, r) && r == 10); +// ENSURE(!wm1.find(n1, r)); +// ENSURE(wm1.find(n2, r) && r == 10); // wm1.insert(n2, 20); -// SASSERT(!wm1.find(n1, r)); -// SASSERT(wm1.find(n2, r) && r == 20); +// ENSURE(!wm1.find(n1, r)); +// ENSURE(wm1.find(n2, r) && r == 20); // wm1.insert(n1, 0); -// SASSERT(wm1.find(n1, r) && r == 0); -// SASSERT(wm1.find(n2, r) && r == 20); +// ENSURE(wm1.find(n1, r) && r == 0); +// ENSURE(wm1.find(n2, r) && r == 20); } static void tst5() { @@ -119,13 +119,13 @@ static void tst5() { m.push_back(arr1, a2); m.pop_back(arr1, arr2); m.set(arr2, 0, a2, arr3); - SASSERT(m.size(arr1) == 2); - SASSERT(m.size(arr2) == 1); - SASSERT(m.size(arr3) == 1); - SASSERT(m.get(arr1, 0) == a1); - SASSERT(m.get(arr1, 1) == a2); - SASSERT(m.get(arr2, 0) == a1); - SASSERT(m.get(arr3, 0) == a2); + ENSURE(m.size(arr1) == 2); + ENSURE(m.size(arr2) == 1); + ENSURE(m.size(arr3) == 1); + ENSURE(m.get(arr1, 0) == a1); + ENSURE(m.get(arr1, 1) == a2); + ENSURE(m.get(arr2, 0) == a1); + ENSURE(m.get(arr3, 0) == a2); m.del(arr1); m.del(arr2); m.del(arr3); diff --git a/src/test/bit_vector.cpp b/src/test/bit_vector.cpp index 7d3f96ae4..46a39747d 100644 --- a/src/test/bit_vector.cpp +++ b/src/test/bit_vector.cpp @@ -31,30 +31,30 @@ static void tst1() { bool val = (rand()%2) != 0; v1.push_back(val); v2.push_back(val); - SASSERT(v1.size() == v2.size()); + ENSURE(v1.size() == v2.size()); } else if (op <= 3) { - SASSERT(v1.size() == v2.size()); + ENSURE(v1.size() == v2.size()); if (v1.size() > 0) { bool val = (rand()%2) != 0; unsigned idx = rand()%v1.size(); - SASSERT(v1.get(idx) == v2[idx]); + ENSURE(v1.get(idx) == v2[idx]); v1.set(idx, val); v2[idx] = val; - SASSERT(v1.get(idx) == v2[idx]); + ENSURE(v1.get(idx) == v2[idx]); } } else if (op <= 4) { - SASSERT(v1.size() == v2.size()); + ENSURE(v1.size() == v2.size()); if (v1.size() > 0) { unsigned idx = rand()%v1.size(); - SASSERT(v1.get(idx) == v2[idx]); + VERIFY(v1.get(idx) == v2[idx]); } } else if (op <= 5) { - SASSERT(v1.size() == v2.size()); + ENSURE(v1.size() == v2.size()); for (unsigned j = 0; j < v1.size(); j++) { - SASSERT(v1.get(j) == v2[j]); + ENSURE(v1.get(j) == v2[j]); } } } @@ -66,11 +66,11 @@ static void tst2() { b.push_back(false); b.push_back(true); b.resize(30); - SASSERT(b.get(0) == true); - SASSERT(b.get(1) == false); - SASSERT(b.get(2) == true); - SASSERT(b.get(3) == false); - SASSERT(b.get(29) == false); + ENSURE(b.get(0) == true); + ENSURE(b.get(1) == false); + ENSURE(b.get(2) == true); + ENSURE(b.get(3) == false); + ENSURE(b.get(29) == false); } static void tst_shift() { @@ -116,14 +116,14 @@ static void tst_or() { std::cout << b1 << "\n"; std::cout << b2 << "\n"; b1 |= b2; - SASSERT(b1.size() == 10); + ENSURE(b1.size() == 10); std::cout << b1 << "\n"; - SASSERT(b1 != b2); - SASSERT(b1 != b2); + ENSURE(b1 != b2); + ENSURE(b1 != b2); b1.unset(4); - SASSERT(b1 == b2); + ENSURE(b1 == b2); b1.unset(3); - SASSERT(b1 != b2); + ENSURE(b1 != b2); } { bit_vector b1; @@ -133,9 +133,9 @@ static void tst_or() { b1.set(0); b2.set(4); b1 |= b2; - SASSERT(b1 != b2); + ENSURE(b1 != b2); b2.set(0); - SASSERT(b1 == b2); + ENSURE(b1 == b2); std::cout << "-----\n"; std::cout << b1 << "\n"; } @@ -149,9 +149,9 @@ static void tst_or() { b2.set(3); b2.resize(5); b1 |= b2; - SASSERT(!b1.get(8)); - SASSERT(b1.get(5)); - SASSERT(b1.get(3)); + ENSURE(!b1.get(8)); + ENSURE(b1.get(5)); + ENSURE(b1.get(3)); } { bit_vector b1; @@ -166,17 +166,17 @@ static void tst_or() { b2.set(80); b1.set(4); b2.set(4); - SASSERT(b1!=b2); + ENSURE(b1!=b2); b2.resize(123); - SASSERT(b1!=b2); + ENSURE(b1!=b2); b1.resize(120); b2.resize(120); - SASSERT(b1==b2); + ENSURE(b1==b2); b1.unset(80); b1.unset(100); - SASSERT(b1!=b2); + ENSURE(b1!=b2); b1 |= b2; - SASSERT(b1 == b2); + ENSURE(b1 == b2); } { bit_vector b1; @@ -188,8 +188,8 @@ static void tst_or() { b2.set(1); b1.set(0); b1 |= b2; - SASSERT(b1.size() == 10); - SASSERT(b1.get(8) && b1.get(4) && b1.get(1) && b1.get(0) && !b1.get(9)); + ENSURE(b1.size() == 10); + ENSURE(b1.get(8) && b1.get(4) && b1.get(1) && b1.get(0) && !b1.get(9)); } { bit_vector b1; @@ -201,7 +201,7 @@ static void tst_or() { b2.set(8); b2.set(0); b1 |= b2; - SASSERT(b1.get(1) && b1.get(5) && b1.get(8) && b1.get(0) && !b1.get(11)); + ENSURE(b1.get(1) && b1.get(5) && b1.get(8) && b1.get(0) && !b1.get(11)); std::cout << "b1(size32): " << b1 << "\n"; } } @@ -218,8 +218,8 @@ static void tst_and() { std::cout << "------\nb1: " << b1 << "\n"; b1 &= b2; std::cout << "------\nb1: " << b1 << "\n"; - SASSERT(!b1.get(4)); - SASSERT(b1.get(2)); + ENSURE(!b1.get(4)); + ENSURE(b1.get(2)); } { bit_vector b1; @@ -234,7 +234,7 @@ static void tst_and() { b2.set(127); b2.set(5); b1 &= b2; - SASSERT(!b1.get(240) && !b1.get(232) && !b1.get(128) && b1.get(127) && !b1.get(8) && !b1.get(5)); + ENSURE(!b1.get(240) && !b1.get(232) && !b1.get(128) && b1.get(127) && !b1.get(8) && !b1.get(5)); } } @@ -243,17 +243,17 @@ static void tst_crash() { bit_vector b; b.push_back(true); b.resize(64); - SASSERT(!b.get(63)); - SASSERT(b.get(0)); - SASSERT(!b.get(1)); + ENSURE(!b.get(63)); + ENSURE(b.get(0)); + ENSURE(!b.get(1)); } { bit_vector b; b.push_back(false); b.resize(64, true); - SASSERT(b.get(63)); - SASSERT(!b.get(0)); - SASSERT(b.get(1)); + ENSURE(b.get(63)); + ENSURE(!b.get(0)); + ENSURE(b.get(1)); } } @@ -264,12 +264,12 @@ static void tst_bv_reset() { b.reset(); b.resize(sz, bit); for (unsigned i = 0; i < sz; ++i) { - SASSERT(bit == b.get(i)); + ENSURE(bit == b.get(i)); } for (unsigned sz2 = sz; sz2 < sz+10; ++sz2) { b.resize(sz2, !bit); for (unsigned i = sz; i < sz2; ++i) { - SASSERT(bit != b.get(i)); + ENSURE(bit != b.get(i)); } } bit = !bit; @@ -283,19 +283,19 @@ static void tst_eq() { b3.resize(32); b1.set(3, true); - SASSERT(b1 != b2); - SASSERT(!(b1 == b2)); - SASSERT(b2 == b3); + ENSURE(b1 != b2); + ENSURE(!(b1 == b2)); + ENSURE(b2 == b3); b3.set(3, true); - SASSERT(b1 == b3); - SASSERT(!(b1 != b3)); + ENSURE(b1 == b3); + ENSURE(!(b1 != b3)); b2.set(31, true); b3.set(31); b3.unset(3); - SASSERT(b2 == b3); - SASSERT(!(b2 != b3)); + ENSURE(b2 == b3); + ENSURE(!(b2 != b3)); } void tst_bit_vector() { diff --git a/src/test/bits.cpp b/src/test/bits.cpp index f32871a5a..ba75ea0b4 100644 --- a/src/test/bits.cpp +++ b/src/test/bits.cpp @@ -27,11 +27,11 @@ static void tst_shl(unsigned src_sz, unsigned const * src, unsigned k, if (trace) std::cout << " for sz = " << sz << std::endl; shl(src_sz, src, k, sz, actual_dst.c_ptr()); - SASSERT(!has_one_at_first_k_bits(sz, actual_dst.c_ptr(), k)); + ENSURE(!has_one_at_first_k_bits(sz, actual_dst.c_ptr(), k)); for (unsigned i = 0; i < sz; i++) { if (trace && dst[i] != actual_dst[i]) std::cout << "UNEXPECTED RESULT at [" << i << "]: " << actual_dst[i] << ", expected: " << dst[i] << "\n"; - SASSERT(dst[i] == actual_dst[i]); + ENSURE(dst[i] == actual_dst[i]); } if (sz == src_sz) { unsigned nz1 = nlz(sz, src); @@ -52,7 +52,7 @@ static void tst_shl(unsigned src_sz, unsigned const * src, unsigned k, if (trace && src[i] != new_src[i]) { std::cout << "shr BUG, inverting shl, at bit[" << i << "], " << new_src[i] << ", expected: " << src[i] << std::endl; } - SASSERT(src[i] == new_src[i]); + ENSURE(src[i] == new_src[i]); } } } @@ -65,7 +65,7 @@ static void tst_shl(unsigned src_sz, unsigned const * src, unsigned k, for (unsigned i = 0; i < dst_sz; i++) { if (trace && dst[i] != actual_dst[i]) std::cout << "UNEXPECTED RESULT at [" << i << "]: " << actual_dst[i] << ", expected: " << dst[i] << "\n"; - SASSERT(dst[i] == actual_dst[i]); + ENSURE(dst[i] == actual_dst[i]); } if (src_sz <= dst_sz) { if (trace) @@ -74,7 +74,7 @@ static void tst_shl(unsigned src_sz, unsigned const * src, unsigned k, for (unsigned i = 0; i < src_sz; i++) { if (trace && src[i] != dst[i]) std::cout << "UNEXPECTED RESULT at [" << i << "]: " << src[i] << ", expected: " << dst[i] << "\n"; - SASSERT(src[i] == actual_dst[i]); + ENSURE(src[i] == actual_dst[i]); } } } @@ -134,7 +134,7 @@ static void tst_shr(unsigned src_sz, unsigned const * src, unsigned k, for (unsigned i = 0; i < src_sz; i++) { if (trace && dst[i] != actual_dst[i]) std::cout << "UNEXPECTED RESULT at [" << i << "]: " << actual_dst[i] << ", expected: " << dst[i] << "\n"; - SASSERT(dst[i] == actual_dst[i]); + ENSURE(dst[i] == actual_dst[i]); } } @@ -172,7 +172,7 @@ static void tst_shl_rand(unsynch_mpz_manager & m, unsigned sz, unsigned k, bool m.mul2k(max, 32); while (!m.is_zero(_dst)) { m.mod(_dst, max, tmp); - SASSERT(m.is_uint64(tmp) && m.get_uint64(tmp) < UINT_MAX); + ENSURE(m.is_uint64(tmp) && m.get_uint64(tmp) < UINT_MAX); dst.push_back(static_cast(m.get_uint64(tmp))); m.div(_dst, max, _dst); } diff --git a/src/test/buffer.cpp b/src/test/buffer.cpp index a23fb3c74..f4b7f0c99 100644 --- a/src/test/buffer.cpp +++ b/src/test/buffer.cpp @@ -24,22 +24,22 @@ template class ptr_scoped_buffer; static void tst1() { ptr_scoped_buffer b; - SASSERT(b.empty()); + ENSURE(b.empty()); b.push_back(alloc(point, 10, 20)); - SASSERT(!b.empty()); + ENSURE(!b.empty()); point * p1 = alloc(point, 30, 20); b.push_back(p1); - SASSERT(b.get(1) == p1); + ENSURE(b.get(1) == p1); b.push_back(alloc(point, 40, 20)); - SASSERT(b.size() == 3); + ENSURE(b.size() == 3); b.pop_back(); - SASSERT(b.get(0) != p1); - SASSERT(b.get(1) == p1); + ENSURE(b.get(0) != p1); + ENSURE(b.get(1) == p1); point * p2 = alloc(point, 30, 20); - SASSERT(b.get(0) != p2); + ENSURE(b.get(0) != p2); b.set(0, p2); - SASSERT(b.get(0) == p2); - SASSERT(b.size() == 2); + ENSURE(b.get(0) == p2); + ENSURE(b.size() == 2); b.push_back(alloc(point, 40, 40)); } diff --git a/src/test/bv_simplifier_plugin.cpp b/src/test/bv_simplifier_plugin.cpp index dc930bb82..42952706b 100644 --- a/src/test/bv_simplifier_plugin.cpp +++ b/src/test/bv_simplifier_plugin.cpp @@ -30,7 +30,7 @@ class tst_bv_simplifier_plugin_cls { if (!m_bv_util.is_numeral(e, r, bv_size0)) { UNREACHABLE(); } - SASSERT(bv_size == bv_size0); + ENSURE(bv_size == bv_size0); } unsigned u32(expr* e) { @@ -109,49 +109,49 @@ public: ar = m_manager.mk_app(m_fid, OP_BNEG, e1.get()); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((0-a) == u32(e.get())); + ENSURE((0-a) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BNOT, e1.get()); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((~a) == u32(e.get())); + ENSURE((~a) == u32(e.get())); parameter params[2] = { parameter(32), parameter(32) }; ar = m_manager.mk_app(m_fid, OP_SIGN_EXT, 1, params, 1, es); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((int64)(int)a) == i64(e.get())); + ENSURE(((int64)(int)a) == i64(e.get())); ar = m_manager.mk_app(m_fid, OP_ZERO_EXT, 1, params, 1, es); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((uint64)a) == u64(e.get())); + ENSURE(((uint64)a) == u64(e.get())); params[0] = parameter(7); params[1] = parameter(0); ar = m_manager.mk_app(m_fid, OP_EXTRACT, 2, params, 1, es); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((unsigned char)a) == u8(e.get())); + ENSURE(((unsigned char)a) == u8(e.get())); params[0] = parameter(2); ar = m_manager.mk_app(m_fid, OP_REPEAT, 1, params, 1, es); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((a64 << 32) | a64) == u64(e.get())); + VERIFY(((a64 << 32) | a64) == u64(e.get())); ar = m_manager.mk_app(m_fid, OP_BREDOR, e1.get()); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a != 0) == bit2bool(e.get())); + ENSURE((a != 0) == bit2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_BREDAND, e1.get()); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a == 0xFFFFFFFF) == bit2bool(e.get())); + ENSURE((a == 0xFFFFFFFF) == bit2bool(e.get())); params[0] = parameter(8); ar = m_manager.mk_app(m_fid, OP_ROTATE_LEFT, 1, params, 1, es); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((a << 8) | (a >> 24)) == u32(e.get())); + ENSURE(((a << 8) | (a >> 24)) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_ROTATE_RIGHT, 1, params, 1, es); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((a >> 8) | (a << 24)) == u32(e.get())); + ENSURE(((a >> 8) | (a << 24)) == u32(e.get())); params[0] = parameter(m_manager.mk_sort(m_manager.mk_family_id("arith"), INT_SORT)); ar = m_manager.mk_app(m_fid, OP_BV2INT, 1, params, 1, es); @@ -159,15 +159,15 @@ public: params[0] = parameter(32); ar = m_manager.mk_app(m_fid, OP_INT2BV, 1, params, 1, es2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(a == u32(e.get())); + ENSURE(a == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BIT0); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(!bit2bool(e.get())); + VERIFY(!bit2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_BIT1); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(bit2bool(e.get())); + VERIFY(bit2bool(e.get())); } @@ -187,113 +187,113 @@ public: ar = m_manager.mk_app(m_fid, OP_BADD, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a + b) == u32(e.get())); + VERIFY((a + b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BSUB, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a - b) == u32(e.get())); + VERIFY((a - b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BMUL, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a * b) == u32(e.get())); + VERIFY((a * b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BAND, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a & b) == u32(e.get())); + VERIFY((a & b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BOR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a | b) == u32(e.get())); + VERIFY((a | b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BNOR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(~(a | b) == u32(e.get())); + VERIFY(~(a | b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BXOR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a ^ b) == u32(e.get())); + VERIFY((a ^ b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BXNOR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((~(a ^ b)) == u32(e.get())); + VERIFY((~(a ^ b)) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BNAND, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((~(a & b)) == u32(e.get())); + VERIFY((~(a & b)) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_ULEQ, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a <= b) == ast2bool(e.get())); + VERIFY((a <= b) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_UGEQ, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a >= b) == ast2bool(e.get())); + VERIFY((a >= b) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_ULT, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a < b) == ast2bool(e.get())); + VERIFY((a < b) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_UGT, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a > b) == ast2bool(e.get())); + VERIFY((a > b) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_SLEQ, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((sa <= sb) == ast2bool(e.get())); + VERIFY((sa <= sb) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_SGEQ, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((sa >= sb) == ast2bool(e.get())); + VERIFY((sa >= sb) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_SLT, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((sa < sb) == ast2bool(e.get())); + VERIFY((sa < sb) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_SGT, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((sa > sb) == ast2bool(e.get())); + VERIFY((sa > sb) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_BSHL, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((b>=32)?0:(a << b)) == u32(e.get())); + VERIFY(((b>=32)?0:(a << b)) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BLSHR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((b>=32)?0:(a >> b)) == u32(e.get())); + VERIFY(((b>=32)?0:(a >> b)) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BASHR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); std::cout << "compare: " << sa << " >> " << b << " = " << (sa >> b) << " with " << i32(e.get()) << "\n"; - SASSERT(b >= 32 || ((sa >> b) == i32(e.get()))); + VERIFY(b >= 32 || ((sa >> b) == i32(e.get()))); if (b != 0) { ar = m_manager.mk_app(m_fid, OP_BSDIV, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((sa / sb) == i32(e.get())); + VERIFY((sa / sb) == i32(e.get())); ar = m_manager.mk_app(m_fid, OP_BUDIV, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a / b) == u32(e.get())); + VERIFY((a / b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BSREM, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - //SASSERT((sa % sb) == i32(e.get())); + //VERIFY((sa % sb) == i32(e.get())); ar = m_manager.mk_app(m_fid, OP_BUREM, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a % b) == u32(e.get())); + VERIFY((a % b) == u32(e.get())); // TBD: BSMOD. } ar = m_manager.mk_app(m_fid, OP_CONCAT, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((a64 << 32) | b64) == u64(e.get())); + VERIFY(((a64 << 32) | b64) == u64(e.get())); ar = m_manager.mk_app(m_fid, OP_BCOMP, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a == b) == bit2bool(e.get())); + VERIFY((a == b) == bit2bool(e.get())); } void test() { diff --git a/src/test/chashtable.cpp b/src/test/chashtable.cpp index 7d55fe01f..c9750b95e 100644 --- a/src/test/chashtable.cpp +++ b/src/test/chashtable.cpp @@ -37,16 +37,16 @@ static void display(T const & beg, T const & end) { static void tst1() { int_table t; t.insert(10); - SASSERT(t.contains(10)); + ENSURE(t.contains(10)); t.insert(20); - SASSERT(t.contains(20)); + ENSURE(t.contains(20)); t.insert(30); - SASSERT(t.contains(30)); - SASSERT(t.size() == 3); + ENSURE(t.contains(30)); + ENSURE(t.size() == 3); display(t.begin(), t.end()); t.erase(20); - SASSERT(!t.contains(20)); - SASSERT(t.size() == 2); + ENSURE(!t.contains(20)); + ENSURE(t.size() == 2); } struct dummy_hash { @@ -61,54 +61,54 @@ static void tst2() { dint_table t; t.insert(10); t.insert(12); - SASSERT(t.used_slots() == 1); + ENSURE(t.used_slots() == 1); display(t.begin(), t.end()); t.insert(13); display(t.begin(), t.end()); - SASSERT(t.used_slots() == 2); + ENSURE(t.used_slots() == 2); t.insert(14); - SASSERT(t.used_slots() == 2); - SASSERT(t.size() == 4); + ENSURE(t.used_slots() == 2); + ENSURE(t.size() == 4); display(t.begin(), t.end()); t.erase(12); - SASSERT(!t.contains(12)); - SASSERT(t.size() == 3); - SASSERT(t.contains(10)); - SASSERT(!t.contains(12)); - SASSERT(t.contains(14)); - SASSERT(t.contains(13)); + ENSURE(!t.contains(12)); + ENSURE(t.size() == 3); + ENSURE(t.contains(10)); + ENSURE(!t.contains(12)); + ENSURE(t.contains(14)); + ENSURE(t.contains(13)); t.insert(16); - SASSERT(t.size() == 4); + ENSURE(t.size() == 4); t.insert(18); - SASSERT(t.size() == 5); - SASSERT(t.used_slots() == 2); + ENSURE(t.size() == 5); + ENSURE(t.used_slots() == 2); display(t.begin(), t.end()); t.erase(10); display(t.begin(), t.end()); - SASSERT(!t.contains(10)); - SASSERT(!t.contains(12)); - SASSERT(t.contains(14)); - SASSERT(t.contains(13)); - SASSERT(t.contains(16)); - SASSERT(t.contains(18)); + ENSURE(!t.contains(10)); + ENSURE(!t.contains(12)); + ENSURE(t.contains(14)); + ENSURE(t.contains(13)); + ENSURE(t.contains(16)); + ENSURE(t.contains(18)); } static void tst3() { dint_table t; t.insert(10); t.insert(12); - SASSERT(t.used_slots() == 1); - SASSERT(t.contains(10)); - SASSERT(t.contains(12)); + ENSURE(t.used_slots() == 1); + ENSURE(t.contains(10)); + ENSURE(t.contains(12)); t.erase(12); t.erase(10); - SASSERT(t.size() == 0); - SASSERT(t.empty()); - SASSERT(t.used_slots() == 0); + ENSURE(t.size() == 0); + ENSURE(t.empty()); + ENSURE(t.used_slots() == 0); t.insert(10); - SASSERT(t.used_slots() == 1); - SASSERT(t.contains(10)); - SASSERT(t.size() == 1); + ENSURE(t.used_slots() == 1); + ENSURE(t.contains(10)); + ENSURE(t.size() == 1); } typedef int_hashtable > int_set; @@ -123,29 +123,29 @@ static void tst4(unsigned num, unsigned N) { TRACE("chashtable", tout << "erase " << v << "\n";); s.erase(v); t.erase(v); - SASSERT(!t.contains(v)); + ENSURE(!t.contains(v)); } else { TRACE("chashtable", tout << "insert " << v << "\n";); s.insert(v); t.insert(v); - SASSERT(t.contains(v)); + ENSURE(t.contains(v)); } - SASSERT(s.size() == t.size()); - SASSERT(s.empty() == t.empty()); + ENSURE(s.size() == t.size()); + ENSURE(s.empty() == t.empty()); } std::cout << "size: " << s.size() << " " << t.size() << "\n"; int_set::iterator it1 = s.begin(); int_set::iterator end1 = s.end(); for(; it1 != end1; ++it1) { - SASSERT(t.contains(*it1)); + ENSURE(t.contains(*it1)); } typename T::iterator it2 = t.begin(); typename T::iterator end2 = t.end(); for(; it2 != end2; ++it2) { - SASSERT(s.contains(*it2)); - SASSERT(t.contains(*it2)); + ENSURE(s.contains(*it2)); + ENSURE(t.contains(*it2)); } } @@ -164,10 +164,10 @@ static void tst5() { static void tst6() { int_map m; m.insert(10, 4); - SASSERT(m.contains(10)); + ENSURE(m.contains(10)); DEBUG_CODE({ int r; - SASSERT(m.find(10, r) && r == 4); + ENSURE(m.find(10, r) && r == 4); }); } diff --git a/src/test/check_assumptions.cpp b/src/test/check_assumptions.cpp index fa8327cd4..918513ca0 100644 --- a/src/test/check_assumptions.cpp +++ b/src/test/check_assumptions.cpp @@ -38,7 +38,7 @@ void tst_check_assumptions() expr * npE = np.get(); lbool res1 = ctx.check(1, &npE); - SASSERT(res1==l_true); + VERIFY(res1 == l_true); ctx.assert_expr(npE); diff --git a/src/test/cnf_backbones.cpp b/src/test/cnf_backbones.cpp index 638f9684e..0d07b3ff0 100644 --- a/src/test/cnf_backbones.cpp +++ b/src/test/cnf_backbones.cpp @@ -38,6 +38,7 @@ static void STD_CALL on_ctrl_c(int) { raise(SIGINT); } +#if 0 static void display_model(sat::solver const & s) { sat::model const & m = s.get_model(); for (unsigned i = 1; i < m.size(); i++) { @@ -49,6 +50,7 @@ static void display_model(sat::solver const & s) { } std::cout << "\n"; } +#endif static void display_status(lbool r) { switch (r) { diff --git a/src/test/diff_logic.cpp b/src/test/diff_logic.cpp index 70345c2d6..3a1ec198d 100644 --- a/src/test/diff_logic.cpp +++ b/src/test/diff_logic.cpp @@ -70,20 +70,20 @@ static void tst2() { g.init_var(3); g.init_var(4); smt::literal d; - SASSERT(g.enable_edge(g.add_edge(1, 2, rational(-1), l1))); - SASSERT(g.get_edge_weight(1, 2, w, d) && w == rational(-1)); - SASSERT(!g.get_edge_weight(2, 3, w, d)); - SASSERT(g.enable_edge(g.add_edge(2, 3, rational(-2), l2))); - SASSERT(g.enable_edge(g.add_edge(1, 4, rational(1), l3))); - SASSERT(g.get_edge_weight(1, 2, w, d) && w == rational(-1)); - SASSERT(g.get_edge_weight(1, 4, w, d) && w == rational(1)); - SASSERT(!g.get_edge_weight(1, 3, w, d)); - SASSERT(g.enable_edge(g.add_edge(2, 4, rational(10), l6))); - SASSERT(g.is_feasible()); + ENSURE(g.enable_edge(g.add_edge(1, 2, rational(-1), l1))); + ENSURE(g.get_edge_weight(1, 2, w, d) && w == rational(-1)); + ENSURE(!g.get_edge_weight(2, 3, w, d)); + ENSURE(g.enable_edge(g.add_edge(2, 3, rational(-2), l2))); + ENSURE(g.enable_edge(g.add_edge(1, 4, rational(1), l3))); + ENSURE(g.get_edge_weight(1, 2, w, d) && w == rational(-1)); + ENSURE(g.get_edge_weight(1, 4, w, d) && w == rational(1)); + ENSURE(!g.get_edge_weight(1, 3, w, d)); + ENSURE(g.enable_edge(g.add_edge(2, 4, rational(10), l6))); + ENSURE(g.is_feasible()); g.push(); - SASSERT(g.enable_edge(g.add_edge(3, 0, rational(2), l4))); - SASSERT(!g.enable_edge(g.add_edge(0, 1, rational(-1), l5))); - SASSERT(!g.is_feasible()); + ENSURE(g.enable_edge(g.add_edge(3, 0, rational(2), l4))); + ENSURE(!g.enable_edge(g.add_edge(0, 1, rational(-1), l5))); + ENSURE(!g.is_feasible()); TRACE("diff_logic", g.display(tout);); struct proc { svector found; @@ -96,22 +96,22 @@ static void tst2() { }; proc p; g.traverse_neg_cycle(true, p); - SASSERT(p.found[0] == false); - SASSERT(p.found[1] == true); - SASSERT(p.found[2] == true); - SASSERT(p.found[3] == false); - SASSERT(p.found[4] == true); - SASSERT(p.found[5] == true); - SASSERT(p.found[6] == false); + ENSURE(p.found[0] == false); + ENSURE(p.found[1] == true); + ENSURE(p.found[2] == true); + ENSURE(p.found[3] == false); + ENSURE(p.found[4] == true); + ENSURE(p.found[5] == true); + ENSURE(p.found[6] == false); g.pop(1); - SASSERT(g.is_feasible()); + ENSURE(g.is_feasible()); TRACE("diff_logic", g.display(tout);); } static int add_edge(dlg& g, dl_var src, dl_var dst, int weight, unsigned lit) { int id = g.add_edge(src, dst, rational(weight), smt::literal(lit)); bool ok = g.enable_edge(id); - SASSERT(ok); + ENSURE(ok); return id; } @@ -147,7 +147,7 @@ static void tst3() { for (unsigned i = 0; i < subsumed.size(); ++i) { std::cout << "subsumed: " << subsumed[i] << "\n"; - SASSERT(e38 == subsumed[i]); + ENSURE(e38 == subsumed[i]); tst_dl_functor tst_fn; diff --git a/src/test/dl_context.cpp b/src/test/dl_context.cpp index ac09722ac..8d60cd883 100644 --- a/src/test/dl_context.cpp +++ b/src/test/dl_context.cpp @@ -14,6 +14,36 @@ Copyright (c) 2015 Microsoft Corporation using namespace datalog; +void tst_dl_context() { + + return; + +#if 0 + symbol relations[] = { symbol("tr_skip"), symbol("tr_sparse"), symbol("tr_hashtable"), symbol("smt_relation2") }; + + const unsigned rel_cnt = sizeof(relations)/sizeof(symbol); + const char * test_file = "c:\\tvm\\src\\benchmarks\\datalog\\t0.datalog"; + + params_ref params; + for(unsigned rel_index=0; rel_index=0; eager_checking--) { + params.set_bool("eager_emptiness_checking", eager_checking!=0); + + std::cerr << "Testing " << relations[rel_index] << "\n"; + std::cerr << "Eager emptiness checking " << (eager_checking!=0 ? "on" : "off") << "\n"; + dl_context_simple_query_test(params); + dl_context_saturate_file(params, test_file); + } + } +#endif + +} + + +#if 0 + + static lbool dl_context_eval_unary_predicate(ast_manager & m, context & ctx, char const* problem_text, const char * pred_name) { parser* p = parser::create(ctx,m); @@ -21,12 +51,12 @@ static lbool dl_context_eval_unary_predicate(ast_manager & m, context & ctx, cha dealloc(p); func_decl * pred = ctx.try_get_predicate_decl(symbol(pred_name)); - SASSERT(pred); - SASSERT(pred->get_arity()==1); + ENSURE(pred); + ENSURE(pred->get_arity()==1); app_ref query_app(m.mk_app(pred, m.mk_var(0, pred->get_domain()[0])), m); lbool status = ctx.query(query_app); - SASSERT(status != l_undef); + ENSURE(status != l_undef); return status; } @@ -47,9 +77,9 @@ static void dl_context_simple_query_test(params_ref & params) { app_ref c_1(decl_util.mk_constant(1, res1->get_signature()[0]), m); relation_fact f(m); f.push_back(c_0); - SASSERT(res1->contains_fact(f)); + ENSURE(res1->contains_fact(f)); f[0]=c_1; - SASSERT(!res1->contains_fact(f)); + ENSURE(!res1->contains_fact(f)); #endif } @@ -72,29 +102,4 @@ void dl_context_saturate_file(params_ref & params, const char * f) { ctx.get_rel_context()->saturate(); std::cerr << "Done\n"; } - -void tst_dl_context() { - symbol relations[] = { symbol("tr_skip"), symbol("tr_sparse"), symbol("tr_hashtable"), symbol("smt_relation2") }; - const unsigned rel_cnt = sizeof(relations)/sizeof(symbol); - - return; -#if 0 - const char * test_file = "c:\\tvm\\src\\benchmarks\\datalog\\t0.datalog"; - - params_ref params; - for(unsigned rel_index=0; rel_index=0; eager_checking--) { - params.set_bool("eager_emptiness_checking", eager_checking!=0); - - std::cerr << "Testing " << relations[rel_index] << "\n"; - std::cerr << "Eager emptiness checking " << (eager_checking!=0 ? "on" : "off") << "\n"; - dl_context_simple_query_test(params); - dl_context_saturate_file(params, test_file); - } - } #endif -} - - - diff --git a/src/test/dl_product_relation.cpp b/src/test/dl_product_relation.cpp index c375587fb..84ffd548a 100644 --- a/src/test/dl_product_relation.cpp +++ b/src/test/dl_product_relation.cpp @@ -37,12 +37,12 @@ namespace datalog { sparse_table_plugin & plugin = static_cast(*rctx.get_rmanager().get_table_plugin(symbol("sparse"))); - SASSERT(&plugin); + ENSURE(&plugin); table_signature sig2; sig2.push_back(2); sig2.push_back(2); sig2.set_functional_columns(1); - SASSERT(plugin.can_handle_signature(sig2)); + ENSURE(plugin.can_handle_signature(sig2)); table_fact f00; f00.push_back(0); @@ -56,32 +56,32 @@ namespace datalog { { table_aptr t0 = plugin.mk_empty(sig2); - SASSERT(t0->empty()); + ENSURE(t0->empty()); t0->add_fact(f00); - SASSERT(!t0->empty()); - SASSERT(t0->get_size_estimate_rows()==1); + ENSURE(!t0->empty()); + ENSURE(t0->get_size_estimate_rows()==1); t0->add_fact(f01); - SASSERT(t0->get_size_estimate_rows()==1); + ENSURE(t0->get_size_estimate_rows()==1); t0->add_fact(f11); - SASSERT(t0->get_size_estimate_rows()==2); + ENSURE(t0->get_size_estimate_rows()==2); unsigned rem_cols0[]={0}; scoped_ptr project0 = rmgr.mk_project_fn(*t0, 1, rem_cols0); table_aptr t1 = (*project0)(*t0); - SASSERT(t1->get_size_estimate_rows()==2); - SASSERT(t1->get_signature().functional_columns()==0); //project on non-functional column cancels functional + ENSURE(t1->get_size_estimate_rows()==2); + ENSURE(t1->get_signature().functional_columns()==0); //project on non-functional column cancels functional unsigned rem_cols1[]={1}; scoped_ptr project1 = rmgr.mk_project_fn(*t0, 1, rem_cols1); table_aptr t2 = (*project1)(*t0); - SASSERT(t2->get_size_estimate_rows()==2); + ENSURE(t2->get_size_estimate_rows()==2); idx_set acc; collector_of_reduced * reducer = alloc(collector_of_reduced, acc); scoped_ptr rproject = rmgr.mk_project_with_reduce_fn(*t0, 1, rem_cols0, reducer); table_aptr rt = (*rproject)(*t0); - SASSERT(acc.num_elems()==1); - SASSERT(rt->get_size_estimate_rows()==1); + ENSURE(acc.num_elems()==1); + ENSURE(rt->get_size_estimate_rows()==1); } { table_aptr t0 = plugin.mk_empty(sig2); @@ -90,44 +90,44 @@ namespace datalog { unsigned join_cols[]={1}; scoped_ptr join0 = rmgr.mk_join_fn(*t0, *t0, 1, join_cols, join_cols); table_aptr t1 = (*join0)(*t0, *t0); - SASSERT(t1->get_signature().size()==4); - SASSERT(t1->get_signature().functional_columns()==2); + ENSURE(t1->get_signature().size()==4); + ENSURE(t1->get_signature().functional_columns()==2); table_fact f0011; f0011.push_back(0); f0011.push_back(0); f0011.push_back(1); f0011.push_back(1); - SASSERT(t1->contains_fact(f0011)); + ENSURE(t1->contains_fact(f0011)); table_fact f0111 = f0011; f0111[1] = 1; - SASSERT(!t1->contains_fact(f0111)); + ENSURE(!t1->contains_fact(f0111)); } { table_aptr t0 = plugin.mk_empty(sig2); t0->display(std::cout<<"0:"); - SASSERT(t0->get_signature().functional_columns()==1); + ENSURE(t0->get_signature().functional_columns()==1); table_fact aux_fact; aux_fact = f01; TRUSTME( t0->suggest_fact(aux_fact) ); t0->display(std::cout<<"1:"); - SASSERT(t0->contains_fact(f01)); - SASSERT(aux_fact[1]==1); + ENSURE(t0->contains_fact(f01)); + ENSURE(aux_fact[1]==1); aux_fact = f00; TRUSTME( !t0->suggest_fact(aux_fact) ); t0->display(std::cout<<"2:"); - SASSERT(t0->contains_fact(f01)); - SASSERT(!t0->contains_fact(f00)); - SASSERT(aux_fact[1]==1); + ENSURE(t0->contains_fact(f01)); + ENSURE(!t0->contains_fact(f00)); + ENSURE(aux_fact[1]==1); t0->ensure_fact(f00); t0->display(std::cout<<"3:"); - SASSERT(t0->contains_fact(f00)); - SASSERT(!t0->contains_fact(f01)); + ENSURE(t0->contains_fact(f00)); + ENSURE(!t0->contains_fact(f01)); } } @@ -140,7 +140,7 @@ namespace datalog { relation_manager & rmgr = ctx.get_rel_context()->get_rmanager(); relation_plugin & rel_plugin = *rmgr.get_relation_plugin(params.get_sym("default_relation", symbol("sparse"))); - SASSERT(&rel_plugin); + ENSURE(&rel_plugin); finite_product_relation_plugin plg(rel_plugin, rmgr); sort_ref byte_srt_ref(dl_util.mk_sort(symbol("BYTE"), 256), m); @@ -194,9 +194,9 @@ namespace datalog { scoped_rel r2 = r1->clone(); scoped_rel r3 = r2->clone(); - SASSERT(!r1->contains_fact(f77)); + ENSURE(!r1->contains_fact(f77)); r1->add_fact(f77); - SASSERT(r1->contains_fact(f77)); + ENSURE(r1->contains_fact(f77)); r2->add_fact(f79); r3->add_fact(f99); @@ -207,34 +207,34 @@ namespace datalog { r2->display( std::cout << "r2 1\n"); r4->display( std::cout << "r4 0\n"); - SASSERT(!r4->contains_fact(f77)); - SASSERT(r4->contains_fact(f79)); + ENSURE(!r4->contains_fact(f77)); + ENSURE(r4->contains_fact(f79)); r4->add_fact(f77); r4->display( std::cout << "r4 1\n"); - SASSERT(r4->contains_fact(f77)); - SASSERT(r4->contains_fact(f79)); + ENSURE(r4->contains_fact(f77)); + ENSURE(r4->contains_fact(f79)); r4->add_fact(f99); r4->display( std::cout << "r4 2\n"); - SASSERT(r4->contains_fact(f99)); + ENSURE(r4->contains_fact(f99)); std::cout << "------ testing union ------\n"; r2->display( std::cout << "r2\n"); scoped_ptr union_op = rmgr.mk_union_fn(*r1, *r2, r3.get()); - SASSERT(union_op); + ENSURE(union_op); (*union_op)(*r1, *r2, r3.get()); r1->display( std::cout << "r1\n"); r2->display( std::cout << "r2\n"); r3->display( std::cout << "r3\n"); - SASSERT(r1->contains_fact(f77)); - SASSERT(r1->contains_fact(f79)); - SASSERT(!r1->contains_fact(f99)); + ENSURE(r1->contains_fact(f77)); + ENSURE(r1->contains_fact(f79)); + ENSURE(!r1->contains_fact(f99)); - SASSERT(!r3->contains_fact(f77)); - SASSERT(r3->contains_fact(f79)); - SASSERT(r3->contains_fact(f99)); + ENSURE(!r3->contains_fact(f77)); + ENSURE(r3->contains_fact(f79)); + ENSURE(r3->contains_fact(f99)); std::cout << "------ testing join ------\n"; @@ -264,9 +264,9 @@ namespace datalog { jr_rr->display( std::cout << "rr\n"); - SASSERT(!jr_tt->contains_fact(f7797)); - SASSERT(jr_tr->contains_fact(f7797)); - SASSERT(jr_rr->contains_fact(f7797)); + ENSURE(!jr_tt->contains_fact(f7797)); + ENSURE(jr_tr->contains_fact(f7797)); + ENSURE(jr_rr->contains_fact(f7797)); std::cout << "------ testing project ------\n"; @@ -288,17 +288,17 @@ namespace datalog { scoped_rel sr_2r = (*proj_2r)(*r31); scoped_rel sr_1t = (*proj_1t)(*r31); - SASSERT(sr_1r->contains_fact(f79)); - SASSERT(sr_1r->contains_fact(f97)); - SASSERT(!sr_1r->contains_fact(f77)); + ENSURE(sr_1r->contains_fact(f79)); + ENSURE(sr_1r->contains_fact(f97)); + ENSURE(!sr_1r->contains_fact(f77)); - SASSERT(sr_2r->contains_fact(f7)); - SASSERT(sr_2r->contains_fact(f9)); + ENSURE(sr_2r->contains_fact(f7)); + ENSURE(sr_2r->contains_fact(f9)); - SASSERT(sr_1t->contains_fact(f79)); - SASSERT(!sr_1t->contains_fact(f97)); - SASSERT(sr_1t->contains_fact(f77)); - SASSERT(sr_1t->contains_fact(f99)); + ENSURE(sr_1t->contains_fact(f79)); + ENSURE(!sr_1t->contains_fact(f97)); + ENSURE(sr_1t->contains_fact(f77)); + ENSURE(sr_1t->contains_fact(f99)); std::cout << "------ testing filter_interpreted ------\n"; @@ -314,8 +314,8 @@ namespace datalog { scoped_ptr i_filter = rmgr.mk_filter_interpreted_fn(*r41, cond); (*i_filter)(*r41); - SASSERT(r41->contains_fact(f7797)); - SASSERT(!r41->contains_fact(f7997)); + ENSURE(r41->contains_fact(f7797)); + ENSURE(!r41->contains_fact(f7997)); std::cout << "------ testing filter_by_negation ------\n"; @@ -334,9 +334,9 @@ namespace datalog { nf_r31_cols, nf_r1_cols); (*neg_filter)(*r31, *r1); - SASSERT(!r31->contains_fact(f779)); - SASSERT(r31->contains_fact(f977)); - SASSERT(r31->contains_fact(f799)); + ENSURE(!r31->contains_fact(f779)); + ENSURE(r31->contains_fact(f977)); + ENSURE(r31->contains_fact(f799)); } diff --git a/src/test/dl_query.cpp b/src/test/dl_query.cpp index ae7313e41..eaa26cdbb 100644 --- a/src/test/dl_query.cpp +++ b/src/test/dl_query.cpp @@ -23,7 +23,7 @@ void dl_query_ask_ground_query(context & ctx, func_decl * pred, relation_fact & lbool is_sat = ctx.query(query); std::cerr << "@@ query should succeed: " << should_be_successful << "\n"; - SASSERT(is_sat != l_undef); + ENSURE(is_sat != l_undef); if((is_sat != l_true) == should_be_successful) { std::cerr<<"wrong ground query answer!\n"; UNREACHABLE(); @@ -40,7 +40,7 @@ void dl_query_ask_for_last_arg(context & ctx, func_decl * pred, relation_fact & lbool is_sat = ctx.query(query); std::cerr << "@@ last arg query should succeed: " << should_be_successful << "\n"; - SASSERT(is_sat != l_undef); + VERIFY(is_sat != l_undef); relation_fact res_fact(m); res_fact.push_back(f.back()); @@ -80,13 +80,13 @@ void dl_query_test(ast_manager & m, smt_params & fparams, params_ref& params, func_decl * pred_b = *it; std::cerr << "Checking queries on relation " << pred_b->get_name() << "\n"; func_decl * pred_q = ctx_q.try_get_predicate_decl(symbol(pred_b->get_name().bare_str())); - SASSERT(pred_q); + ENSURE(pred_q); relation_base & rel_b = ctx_b.get_rel_context()->get_relation(pred_b); relation_signature sig_b = rel_b.get_signature(); relation_signature sig_q = ctx_q.get_rel_context()->get_relation(pred_q).get_signature(); - SASSERT(sig_b.size()==sig_q.size()); + ENSURE(sig_b.size()==sig_q.size()); std::cerr << "Queries on random facts...\n"; relation_fact f_b(m); @@ -164,7 +164,7 @@ void dl_query_test_wpa(smt_params & fparams, params_ref& params) { const unsigned attempts = 10; func_decl * v_pred = ctx.try_get_predicate_decl(symbol("V")); - SASSERT(v_pred); + ENSURE(v_pred); sort * var_sort = v_pred->get_domain(0); uint64 var_sz; @@ -180,7 +180,7 @@ void dl_query_test_wpa(smt_params & fparams, params_ref& params) { app_ref query_lit(m.mk_app(v_pred, q_args.c_ptr()), m); lbool is_sat = ctx.query(query_lit); - SASSERT(is_sat != l_undef); + ENSURE(is_sat != l_undef); bool found = is_sat == l_true; std::cerr<<"query finished: "<get_rmanager(); m.register_plugin(alloc(interval_relation_plugin, m)); interval_relation_plugin& ip = dynamic_cast(*m.get_relation_plugin(symbol("interval_relation"))); - SASSERT(&ip); + ENSURE(&ip); relation_signature sig; sort* int_sort = autil.mk_int(); @@ -38,8 +38,8 @@ namespace datalog { i1.display(std::cout); i2.display(std::cout); - SASSERT(i1.empty()); - SASSERT(!i2.empty()); + ENSURE(i1.empty()); + ENSURE(!i2.empty()); app_ref cond1(ast_m), cond2(ast_m), cond3(ast_m); app_ref cond4(ast_m), cond5(ast_m), cond6(ast_m); @@ -84,11 +84,11 @@ namespace datalog { fact1.push_back(autil.mk_numeral(rational(4), true)); fact1.push_back(autil.mk_numeral(rational(4), true)); fact1.push_back(autil.mk_numeral(rational(5), true)); - SASSERT(i2.contains_fact(fact1)); + ENSURE(i2.contains_fact(fact1)); fact1[0] = autil.mk_numeral(rational(-1), true); - SASSERT(i2.contains_fact(fact1)); + ENSURE(i2.contains_fact(fact1)); fact1[0] = autil.mk_numeral(rational(1), true); - SASSERT(!i2.contains_fact(fact1)); + ENSURE(!i2.contains_fact(fact1)); relation_base* i5 = (*ren1)(i2); i2.display(std::cout << "Orig\n"); @@ -97,7 +97,7 @@ namespace datalog { (*filterCond1)(i2); i2.display(std::cout); // empty - SASSERT(i2.empty()); + ENSURE(i2.empty()); relation_base* i4 = (*proj2)(*i3); i4->display(std::cout); @@ -128,7 +128,7 @@ namespace datalog { relation_manager & m = ctx.get_rel_context()->get_rmanager(); m.register_plugin(alloc(bound_relation_plugin, m)); bound_relation_plugin& br = dynamic_cast(*m.get_relation_plugin(symbol("bound_relation"))); - SASSERT(&br); + ENSURE(&br); relation_signature sig; sort* int_sort = autil.mk_int(); @@ -142,8 +142,8 @@ namespace datalog { i1.display(std::cout << "empty:\n"); i2.display(std::cout << "full:\n"); - SASSERT(i1.empty()); - SASSERT(!i2.empty()); + ENSURE(i1.empty()); + ENSURE(!i2.empty()); app_ref cond1(ast_m), cond2(ast_m), cond3(ast_m); app_ref cond4(ast_m), cond5(ast_m), cond6(ast_m); @@ -201,7 +201,7 @@ namespace datalog { relation_base* i5 = (*ren1)(i2); i5->display(std::cout); - //SASSERT(i2.empty()); + //ENSURE(i2.empty()); relation_base* i4 = (*proj2)(*i3); i4->display(std::cout); diff --git a/src/test/dl_table.cpp b/src/test/dl_table.cpp index 62eec34bc..f9ccb3116 100644 --- a/src/test/dl_table.cpp +++ b/src/test/dl_table.cpp @@ -12,7 +12,7 @@ typedef datalog::table_base* (*mk_table_fn)(datalog::relation_manager& m, datalo static datalog::table_base* mk_bv_table(datalog::relation_manager& m, datalog::table_signature& sig) { datalog::table_plugin * p = m.get_table_plugin(symbol("bitvector")); - SASSERT(p); + ENSURE(p); return p->mk_empty(sig); } @@ -57,12 +57,12 @@ static void test_table(mk_table_fn mk_table) { std::cout << "\n"; } - SASSERT(table.contains_fact(row1)); - SASSERT(table.contains_fact(row2)); - SASSERT(!table.contains_fact(row3)); + ENSURE(table.contains_fact(row1)); + ENSURE(table.contains_fact(row2)); + ENSURE(!table.contains_fact(row3)); #if 0 table.remove_facts(1, &row1); - SASSERT(!table.contains_fact(row1)); + ENSURE(!table.contains_fact(row1)); #endif table.add_fact(row1); diff --git a/src/test/dl_util.cpp b/src/test/dl_util.cpp index 02e40bbd9..44b95934e 100644 --- a/src/test/dl_util.cpp +++ b/src/test/dl_util.cpp @@ -22,7 +22,7 @@ void dl_util_two_array_sort() { datalog::sort_two_arrays(num, a1, a2); for(unsigned i=0; i result; // VERIFY(!m.intersect(*d1,*d0, result)); // m.subtract(*d1,*d0, result); - SASSERT(result.empty()); + ENSURE(result.empty()); dX = m.allocateX(); m.display(std::cout, *d0) << "\n"; m.display(std::cout, *dX) << "\n"; - SASSERT(m.contains(*dX,*d1)); - SASSERT(m.contains(*dX,*d0)); - SASSERT(!m.contains(*d0,*d1)); - SASSERT(!m.contains(*d1,*d0)); + ENSURE(m.contains(*dX,*d1)); + ENSURE(m.contains(*dX,*d0)); + ENSURE(!m.contains(*d0,*d1)); + ENSURE(!m.contains(*d1,*d0)); d1->neg().push_back(m.tbvm().allocate0()); @@ -88,14 +88,14 @@ static void tst_doc1(unsigned n) { doc_ref d1_2(m1, m1.allocate1()); m.display(std::cout, *d1) << " -> "; m1.display(std::cout, *d1_1) << "\n"; - SASSERT(m1.equals(*d1_1,*d1_2)); + ENSURE(m1.equals(*d1_1,*d1_2)); m.set(*d1,2,BIT_x); m.set(*d1,4,BIT_x); d1_1 = m.project(m1, to_delete, *d1); m.display(std::cout, *d1) << " -> "; m1.display(std::cout, *d1_1) << "\n"; d1->neg().push_back(m.tbvm().allocate1()); - SASSERT(m.well_formed(*d1)); + ENSURE(m.well_formed(*d1)); d1_1 = m.project(m1, to_delete, *d1); m.display(std::cout, *d1) << " -> "; m1.display(std::cout, *d1_1) << "\n"; @@ -146,11 +146,11 @@ class test_doc_cls { tbv_ref t(dm.tbvm()); t = mk_rand_tbv(); doc* result = dm.allocate(*t); - SASSERT(dm.tbvm().equals(*t, result->pos())); + ENSURE(dm.tbvm().equals(*t, result->pos())); for (unsigned i = 0; i < num_diff; ++i) { result->neg().push_back(mk_rand_tbv(result->pos())); } - SASSERT(dm.well_formed(*result)); + ENSURE(dm.well_formed(*result)); return result; } @@ -181,7 +181,7 @@ class test_doc_cls { expr_ref result(m); expr_ref_vector conjs(m); unsigned n = m2.num_tbits(); - SASSERT(n <= m_vars.size()); + ENSURE(n <= m_vars.size()); for (unsigned i = 0; i < n; ++i) { switch (t[i]) { case BIT_x: @@ -347,7 +347,7 @@ class test_doc_cls { tout << mk_pp(fml2, m) << "\n"; ); } - SASSERT(res == l_false); + ENSURE(res == l_false); } @@ -464,7 +464,7 @@ public: d2.display(dm, tout) << "\n";); d1.intersect(dm, d2); TRACE("doc", d1.display(dm, tout) << "\n";); - SASSERT(d1.well_formed(dm)); + ENSURE(d1.well_formed(dm)); fml3 = to_formula(d1, dm); fml1 = m.mk_and(fml1, fml2); check_equiv(fml1, fml3); diff --git a/src/test/ext_numeral.cpp b/src/test/ext_numeral.cpp index 0e2b691c9..a35af1ba6 100644 --- a/src/test/ext_numeral.cpp +++ b/src/test/ext_numeral.cpp @@ -26,11 +26,11 @@ static void tst_ ## NAME(int a, ext_numeral_kind ak, int expected_c, ext_numeral scoped_mpq _a(m); \ m.set(_a, a); \ NAME(m, _a, ak); \ - SASSERT(ak == expected_ck); \ + ENSURE(ak == expected_ck); \ if (expected_ck == EN_NUMERAL) { \ scoped_mpq _expected_c(m); \ m.set(_expected_c, expected_c); \ - SASSERT(m.eq(_a, _expected_c)); \ + ENSURE(m.eq(_a, _expected_c)); \ } \ } @@ -45,11 +45,11 @@ static void FUN_NAME(int a, ext_numeral_kind ak, int b, ext_numeral_kind bk, int m.set(_b, b); \ ext_numeral_kind ck; \ OP_NAME(m, _a, ak, _b, bk, _c, ck); \ - SASSERT(ck == expected_ck); \ + ENSURE(ck == expected_ck); \ if (expected_ck == EN_NUMERAL) { \ scoped_mpq _expected_c(m); \ m.set(_expected_c, expected_c); \ - SASSERT(m.eq(_c, _expected_c)); \ + ENSURE(m.eq(_c, _expected_c)); \ } \ } @@ -158,8 +158,7 @@ static void FUN_NAME(int a, ext_numeral_kind ak, int b, ext_numeral_kind bk, boo scoped_mpq _a(m), _b(m); \ m.set(_a, a); \ m.set(_b, b); \ - bool r = OP_NAME(m, _a, ak, _b, bk); \ - SASSERT(r == expected); \ + VERIFY(expected == OP_NAME(m, _a, ak, _b, bk)); \ } #define MK_TST_REL(NAME) MK_TST_REL_CORE(tst_ ## NAME, NAME) @@ -341,52 +340,52 @@ static void tst2() { static void tst3() { unsynch_mpq_manager m; scoped_mpq a(m); - SASSERT(is_zero(m, a, EN_NUMERAL)); - SASSERT(!is_zero(m, a, EN_PLUS_INFINITY)); - SASSERT(!is_zero(m, a, EN_MINUS_INFINITY)); - SASSERT(!is_pos(m, a, EN_NUMERAL)); - SASSERT(is_pos(m, a, EN_PLUS_INFINITY)); - SASSERT(!is_pos(m, a, EN_MINUS_INFINITY)); - SASSERT(!is_infinite(EN_NUMERAL)); - SASSERT(is_infinite(EN_PLUS_INFINITY)); - SASSERT(is_infinite(EN_MINUS_INFINITY)); - SASSERT(!is_neg(m, a, EN_NUMERAL)); - SASSERT(!is_neg(m, a, EN_PLUS_INFINITY)); - SASSERT(is_neg(m, a, EN_MINUS_INFINITY)); + ENSURE(is_zero(m, a, EN_NUMERAL)); + ENSURE(!is_zero(m, a, EN_PLUS_INFINITY)); + ENSURE(!is_zero(m, a, EN_MINUS_INFINITY)); + ENSURE(!is_pos(m, a, EN_NUMERAL)); + ENSURE(is_pos(m, a, EN_PLUS_INFINITY)); + ENSURE(!is_pos(m, a, EN_MINUS_INFINITY)); + ENSURE(!is_infinite(EN_NUMERAL)); + ENSURE(is_infinite(EN_PLUS_INFINITY)); + ENSURE(is_infinite(EN_MINUS_INFINITY)); + ENSURE(!is_neg(m, a, EN_NUMERAL)); + ENSURE(!is_neg(m, a, EN_PLUS_INFINITY)); + ENSURE(is_neg(m, a, EN_MINUS_INFINITY)); m.set(a, 10); - SASSERT(!is_zero(m, a, EN_NUMERAL)); - SASSERT(is_pos(m, a, EN_NUMERAL)); - SASSERT(!is_neg(m, a, EN_NUMERAL)); - SASSERT(!is_infinite(EN_NUMERAL)); + ENSURE(!is_zero(m, a, EN_NUMERAL)); + ENSURE(is_pos(m, a, EN_NUMERAL)); + ENSURE(!is_neg(m, a, EN_NUMERAL)); + ENSURE(!is_infinite(EN_NUMERAL)); m.set(a, -5); - SASSERT(!is_zero(m, a, EN_NUMERAL)); - SASSERT(!is_pos(m, a, EN_NUMERAL)); - SASSERT(is_neg(m, a, EN_NUMERAL)); - SASSERT(!is_infinite(EN_NUMERAL)); + ENSURE(!is_zero(m, a, EN_NUMERAL)); + ENSURE(!is_pos(m, a, EN_NUMERAL)); + ENSURE(is_neg(m, a, EN_NUMERAL)); + ENSURE(!is_infinite(EN_NUMERAL)); ext_numeral_kind ak; ak = EN_MINUS_INFINITY; reset(m, a, ak); - SASSERT(is_zero(m, a, EN_NUMERAL)); + ENSURE(is_zero(m, a, EN_NUMERAL)); { std::ostringstream buffer; display(buffer, m, a, ak); - SASSERT(buffer.str() == "0"); + ENSURE(buffer.str() == "0"); } { std::ostringstream buffer; m.set(a, -10); display(buffer, m, a, ak); - SASSERT(buffer.str() == "-10"); + ENSURE(buffer.str() == "-10"); } { std::ostringstream buffer; display(buffer, m, a, EN_PLUS_INFINITY); - SASSERT(buffer.str() == "+oo"); + ENSURE(buffer.str() == "+oo"); } { std::ostringstream buffer; display(buffer, m, a, EN_MINUS_INFINITY); - SASSERT(buffer.str() == "-oo"); + ENSURE(buffer.str() == "-oo"); } } diff --git a/src/test/fixed_bit_vector.cpp b/src/test/fixed_bit_vector.cpp index 7bd9e62c3..0160fe574 100644 --- a/src/test/fixed_bit_vector.cpp +++ b/src/test/fixed_bit_vector.cpp @@ -31,11 +31,11 @@ static void tst1() { m.set(*b, 0, true); m.set(*b, 1, false); m.set(*b, 2, true); - SASSERT(b->get(0) == true); - SASSERT(b->get(1) == false); - SASSERT(b->get(2) == true); - SASSERT(b->get(3) == false); - SASSERT(b->get(29) == false); + ENSURE(b->get(0) == true); + ENSURE(b->get(1) == false); + ENSURE(b->get(2) == true); + ENSURE(b->get(3) == false); + ENSURE(b->get(29) == false); m.deallocate(b); } @@ -55,11 +55,11 @@ static void tst_or() { m.display(std::cout, *b2) << "\n"; m.set_or(*b1, *b2); m.display(std::cout, *b1) << "\n"; - SASSERT(!m.equals(*b1, *b2)); + ENSURE(!m.equals(*b1, *b2)); m.unset(*b1, 4); - SASSERT(m.equals(*b1, *b2)); + ENSURE(m.equals(*b1, *b2)); m.unset(*b1, 3); - SASSERT(!m.equals(*b1, *b2)); + ENSURE(!m.equals(*b1, *b2)); m.deallocate(b1); m.deallocate(b2); } @@ -78,25 +78,25 @@ static void tst_eq(unsigned num_bits) { fixed_bit_vector* b3 = m.allocate0(); m.set(*b1, 3, true); - SASSERT(!m.equals(*b1, *b2)); - SASSERT(m.equals(*b2, *b3)); + ENSURE(!m.equals(*b1, *b2)); + ENSURE(m.equals(*b2, *b3)); m.set(*b3, 3, true); - SASSERT(m.equals(*b1, *b3)); + ENSURE(m.equals(*b1, *b3)); m.set(*b2, num_bits-1, true); m.set(*b3, num_bits-1); m.unset(*b3, 3); - SASSERT(m.equals(*b2, *b3)); + ENSURE(m.equals(*b2, *b3)); m.fill0(*b1); m.set_neg(*b1); m.fill1(*b2); - SASSERT(m.equals(*b1, *b2)); + ENSURE(m.equals(*b1, *b2)); m.fill0(*b1); for (unsigned i = 0; i < num_bits; ++i) { m.set(*b1, i, true); } - SASSERT(m.equals(*b1, *b2)); + ENSURE(m.equals(*b1, *b2)); m.deallocate(b1); m.deallocate(b2); m.deallocate(b3); diff --git a/contrib/cmake/src/test/fuzzing/CMakeLists.txt b/src/test/fuzzing/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/test/fuzzing/CMakeLists.txt rename to src/test/fuzzing/CMakeLists.txt diff --git a/src/test/get_consequences.cpp b/src/test/get_consequences.cpp index febff0151..029a13881 100644 --- a/src/test/get_consequences.cpp +++ b/src/test/get_consequences.cpp @@ -66,7 +66,7 @@ void test2() { constructor_decl* B = mk_constructor_decl(symbol("B"), symbol("is-B"), 0, 0); constructor_decl* constrs[3] = { R, G, B }; datatype_decl * enum_sort = mk_datatype_decl(symbol("RGB"), 3, constrs); - VERIFY(dt.mk_datatypes(1, &enum_sort, new_sorts)); + VERIFY(dt.mk_datatypes(1, &enum_sort, 0, 0, new_sorts)); del_constructor_decls(3, constrs); sort* rgb = new_sorts[0].get(); @@ -104,7 +104,7 @@ void test2() { VERIFY(l_true == fd_solver->check_sat(0,0)); fd_solver->get_model(mr); - SASSERT(mr.get()); + ENSURE(mr.get()); model_smt2_pp(std::cout, m, *mr.get(), 0); } diff --git a/src/test/get_implied_equalities.cpp b/src/test/get_implied_equalities.cpp index 37fbe2004..8ddcdb1e9 100644 --- a/src/test/get_implied_equalities.cpp +++ b/src/test/get_implied_equalities.cpp @@ -47,13 +47,13 @@ static void tst_get_implied_equalities1() { for (i = 0; i < num_terms; ++i) { printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); } - SASSERT(class_ids[1] == class_ids[0]); - SASSERT(class_ids[2] != class_ids[0]); - SASSERT(class_ids[3] == class_ids[0]); - SASSERT(class_ids[4] != class_ids[0]); - SASSERT(class_ids[5] != class_ids[0]); - SASSERT(class_ids[6] != class_ids[0]); - SASSERT(class_ids[4] == class_ids[5]); + ENSURE(class_ids[1] == class_ids[0]); + ENSURE(class_ids[2] != class_ids[0]); + ENSURE(class_ids[3] == class_ids[0]); + ENSURE(class_ids[4] != class_ids[0]); + ENSURE(class_ids[5] != class_ids[0]); + ENSURE(class_ids[6] != class_ids[0]); + ENSURE(class_ids[4] == class_ids[5]); printf("asserting b <= f(a)\n"); Z3_solver_assert(ctx, solver, Z3_mk_le(ctx, b, fa)); @@ -61,12 +61,12 @@ static void tst_get_implied_equalities1() { for (i = 0; i < num_terms; ++i) { printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); } - SASSERT(class_ids[1] == class_ids[0]); - SASSERT(class_ids[2] != class_ids[0]); - SASSERT(class_ids[3] == class_ids[0]); - SASSERT(class_ids[4] == class_ids[0]); - SASSERT(class_ids[5] == class_ids[0]); - SASSERT(class_ids[6] == class_ids[0]); + ENSURE(class_ids[1] == class_ids[0]); + ENSURE(class_ids[2] != class_ids[0]); + ENSURE(class_ids[3] == class_ids[0]); + ENSURE(class_ids[4] == class_ids[0]); + ENSURE(class_ids[5] == class_ids[0]); + ENSURE(class_ids[6] == class_ids[0]); Z3_solver_dec_ref(ctx, solver); @@ -103,15 +103,15 @@ static void tst_get_implied_equalities2() { printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); } - SASSERT(class_ids[1] != class_ids[0]); - SASSERT(class_ids[2] != class_ids[0]); - SASSERT(class_ids[3] != class_ids[0]); - SASSERT(class_ids[4] != class_ids[0]); - SASSERT(class_ids[4] == class_ids[2]); - SASSERT(class_ids[2] != class_ids[1]); - SASSERT(class_ids[3] != class_ids[1]); - SASSERT(class_ids[4] != class_ids[1]); - SASSERT(class_ids[3] != class_ids[2]); + ENSURE(class_ids[1] != class_ids[0]); + ENSURE(class_ids[2] != class_ids[0]); + ENSURE(class_ids[3] != class_ids[0]); + ENSURE(class_ids[4] != class_ids[0]); + ENSURE(class_ids[4] == class_ids[2]); + ENSURE(class_ids[2] != class_ids[1]); + ENSURE(class_ids[3] != class_ids[1]); + ENSURE(class_ids[4] != class_ids[1]); + ENSURE(class_ids[3] != class_ids[2]); /* delete logical context */ Z3_solver_dec_ref(ctx, solver); diff --git a/src/test/hashtable.cpp b/src/test/hashtable.cpp index 47fae454a..0290ac161 100644 --- a/src/test/hashtable.cpp +++ b/src/test/hashtable.cpp @@ -23,10 +23,6 @@ Revision History: #include"hashtable.h" -#ifndef Z3DEBUG -#undef SASSERT -#define SASSERT(COND) { if (!(COND)) std::cerr << "ERROR: " << #COND << "\n"; } ((void) 0) -#endif struct int_hash_proc { unsigned operator()(int x) const { return x * 3; } }; typedef int_hashtable > int_set; @@ -48,16 +44,16 @@ static void tst1() { int v = rand() % (N / 2); h1.insert(v); vals[i] = v; - SASSERT(contains(h1, v)); + ENSURE(contains(h1, v)); } std::cout << "step1\n"; std::cout.flush(); for (int i = 1; i < N; i ++) { - SASSERT(contains(h1, vals[i])); + ENSURE(contains(h1, vals[i])); } std::cout << "step2\n"; std::cout.flush(); for (int i = 1; i < N; i += 2) { h1.erase(vals[i]); - SASSERT(!contains(h1, vals[i])); + ENSURE(!contains(h1, vals[i])); } std::cout << "step3\n"; std::cout.flush(); for (int i = 1; i < N; i += 2) { @@ -65,7 +61,7 @@ static void tst1() { } std::cout << "step4\n"; std::cout.flush(); for (int i = 1; i < N; i ++) { - SASSERT(contains(h1, vals[i])); + ENSURE(contains(h1, vals[i])); } } @@ -78,19 +74,19 @@ static void tst2() { if (rand() % 3 == 2) { h1.erase(v); h2.erase(v); - SASSERT(!contains(h1, v)); + ENSURE(!contains(h1, v)); } else { h1.insert(v); h2.insert(v); - SASSERT(contains(h1, v)); + ENSURE(contains(h1, v)); } } { safe_int_set::iterator it = h2.begin(); safe_int_set::iterator end = h2.end(); for(; it != end; ++it) { - SASSERT(contains(h1, *it)); + ENSURE(contains(h1, *it)); } } { @@ -98,12 +94,12 @@ static void tst2() { int_set::iterator end = h1.end(); int n = 0; for (; it != end; ++it) { - SASSERT(contains(h1, *it)); + ENSURE(contains(h1, *it)); n++; } - SASSERT(n == h1.size()); + ENSURE(n == h1.size()); } - SASSERT(h1.size() == h2.size()); + ENSURE(h1.size() == h2.size()); // std::cout << "size: " << h1.size() << ", capacity: " << h1.capacity() << "\n"; std::cout.flush(); } @@ -114,13 +110,13 @@ static void tst3() { h1.insert(30); h1.erase(20); int_set h2(h1); - SASSERT(h1.contains(10)); - SASSERT(!h1.contains(20)); - SASSERT(h1.contains(30)); - SASSERT(h2.contains(10)); - SASSERT(!h2.contains(20)); - SASSERT(h2.contains(30)); - SASSERT(h2.size() == 2); + ENSURE(h1.contains(10)); + ENSURE(!h1.contains(20)); + ENSURE(h1.contains(30)); + ENSURE(h2.contains(10)); + ENSURE(!h2.contains(20)); + ENSURE(h2.contains(30)); + ENSURE(h2.size() == 2); } void tst_hashtable() { diff --git a/src/test/heap.cpp b/src/test/heap.cpp index e745463ff..6f827b5e8 100644 --- a/src/test/heap.cpp +++ b/src/test/heap.cpp @@ -33,32 +33,33 @@ static void tst1() { for (int i = 0; i < N * 3; i++) { int val = rand() % N; if (!h.contains(val)) { - SASSERT(!t.contains(val)); + ENSURE(!t.contains(val)); h.insert(val); t.insert(val); } else { - SASSERT(t.contains(val)); + ENSURE(t.contains(val)); } } - SASSERT(h.check_invariant()); + ENSURE(h.check_invariant()); int_set::iterator it = t.begin(); int_set::iterator end = t.end(); for (; it != end; ++it) { - SASSERT(h.contains(*it)); + ENSURE(h.contains(*it)); } - int last = -1; while (!h.empty()) { int m1 = h.min_value(); int m2 = h.erase_min(); - SASSERT(m1 == m2); - SASSERT(last < m2); + (void)m1; + (void)m2; + ENSURE(m1 == m2); + ENSURE(-1 < m2); } } int g_value[N]; -struct lt_proc2 { bool operator()(int v1, int v2) const { SASSERT(v1 < N && v2 < N); return g_value[v1] < g_value[v2]; } }; +struct lt_proc2 { bool operator()(int v1, int v2) const { ENSURE(v1 < N && v2 < N); return g_value[v1] < g_value[v2]; } }; typedef heap int_heap2; static void init_values() { @@ -76,6 +77,7 @@ static void dump_heap(const int_heap2 & h, std::ostream & out) { } static void tst2() { + (void)dump_heap; int_heap2 h(N); for (int i = 0; i < N * 10; i++) { if (i % 1000 == 0) std::cout << "i: " << i << std::endl; @@ -87,7 +89,7 @@ static void tst2() { TRACE("heap", tout << "inserting: " << val << "\n";); h.insert(val); TRACE("heap", dump_heap(h, tout);); - SASSERT(h.contains(val)); + ENSURE(h.contains(val)); } } else if (cmd <= 6) { @@ -96,7 +98,7 @@ static void tst2() { TRACE("heap", tout << "removing: " << val << "\n";); h.erase(val); TRACE("heap", dump_heap(h, tout);); - SASSERT(!h.contains(val)); + ENSURE(!h.contains(val)); } } else if (cmd <= 8) { @@ -117,10 +119,10 @@ static void tst2() { } } else { - SASSERT(h.check_invariant()); + ENSURE(h.check_invariant()); } } - SASSERT(h.check_invariant()); + ENSURE(h.check_invariant()); } void tst_heap() { diff --git a/src/test/hilbert_basis.cpp b/src/test/hilbert_basis.cpp index b46ede849..f2ca8a375 100644 --- a/src/test/hilbert_basis.cpp +++ b/src/test/hilbert_basis.cpp @@ -286,8 +286,8 @@ static void gorrila_test(unsigned seed, unsigned n, unsigned k, unsigned bound, random_gen rand(seed); reslimit rl; hilbert_basis hb(rl); - SASSERT(0 < bound); - SASSERT(k <= n); + ENSURE(0 < bound); + ENSURE(k <= n); int ibound = static_cast(bound); for (unsigned i = 0; i < num_ineqs; ++i) { vector nv; diff --git a/src/test/hwf.cpp b/src/test/hwf.cpp index be32b5400..310d69be2 100644 --- a/src/test/hwf.cpp +++ b/src/test/hwf.cpp @@ -25,16 +25,16 @@ static void bug_set_double() { hwf a; m.set(a, 0.1); - SASSERT(m.is_regular(a)); + ENSURE(m.is_regular(a)); m.set(a, 1.1); - SASSERT(m.is_regular(a)); + ENSURE(m.is_regular(a)); m.set(a, 11.3); - SASSERT(m.is_regular(a)); + ENSURE(m.is_regular(a)); m.set(a, 0.0); - SASSERT(m.is_regular(a)); + ENSURE(m.is_regular(a)); } static void bug_to_rational() { @@ -44,49 +44,49 @@ static void bug_to_rational() { unsynch_mpq_manager mq; scoped_mpq r(mq); - double ad, rd; + double ad = 0, rd = 0; m.set(a, 0.0); m.to_rational(a, r); ad = m.to_double(a); rd = mq.get_double(r); - SASSERT(ad == rd); + VERIFY(ad == rd); m.set(a, 1.0); m.to_rational(a, r); ad = m.to_double(a); rd = mq.get_double(r); - SASSERT(ad == rd); + VERIFY(ad == rd); m.set(a, 1.5); m.to_rational(a, r); ad = m.to_double(a); rd = mq.get_double(r); - SASSERT(ad == rd); + ENSURE(ad == rd); m.set(a, 0.875); m.to_rational(a, r); ad = m.to_double(a); rd = mq.get_double(r); - SASSERT(ad == rd); + ENSURE(ad == rd); m.set(a, -1.0); m.to_rational(a, r); ad = m.to_double(a); rd = mq.get_double(r); - SASSERT(ad == rd); + ENSURE(ad == rd); m.set(a, -1.5); m.to_rational(a, r); ad = m.to_double(a); rd = mq.get_double(r); - SASSERT(ad == rd); + ENSURE(ad == rd); m.set(a, -0.875); m.to_rational(a, r); ad = m.to_double(a); rd = mq.get_double(r); - SASSERT(ad == rd); + ENSURE(ad == rd); m.set(a, 0.1); m.to_rational(a, r); @@ -96,7 +96,7 @@ static void bug_to_rational() { // CMW: This one depends on the rounding mode, // which is implicit in both hwf::set and in mpq::to_double. double diff = (ad-rd); - SASSERT(diff >= -DBL_EPSILON && diff <= DBL_EPSILON); + ENSURE(diff >= -DBL_EPSILON && diff <= DBL_EPSILON); #endif } @@ -107,7 +107,7 @@ static void bug_is_int() { hwf_manager m; hwf a; m.set(a, val); - SASSERT(!m.is_int(a)); + ENSURE(!m.is_int(a)); } void tst_hwf() { diff --git a/src/test/inf_rational.cpp b/src/test/inf_rational.cpp index 1b0a293ce..64d2ab921 100644 --- a/src/test/inf_rational.cpp +++ b/src/test/inf_rational.cpp @@ -23,8 +23,8 @@ Revision History: static void tst0() { inf_rational n(rational(0), false); TRACE("inf_rational", tout << n << "\n";); - SASSERT(n < inf_rational::zero()); - SASSERT(!(n >= inf_rational::zero())); + ENSURE(n < inf_rational::zero()); + ENSURE(!(n >= inf_rational::zero())); } void test_inc_dec( @@ -36,44 +36,44 @@ void test_inc_dec( ) { r += rational(1,5); - SASSERT (r == b_8_5); + ENSURE (r == b_8_5); r -= rational(1,5); - SASSERT (r == b_7_5); + ENSURE (r == b_7_5); r += inf_rational(1,5); - SASSERT (r == b_8_5); + ENSURE (r == b_8_5); r -= inf_rational(1,5); - SASSERT (r == b_7_5); + ENSURE (r == b_7_5); r /= rational(2,1); - SASSERT (r == b_7_10); + ENSURE (r == b_7_10); inf_rational r_pre = r++; - SASSERT (r_pre == b_7_10); - SASSERT (r == b_17_10); + ENSURE (r_pre == b_7_10); + ENSURE (r == b_17_10); inf_rational r_post = --r; - SASSERT (r_post == b_7_10); - SASSERT (r == b_7_10); + ENSURE (r_post == b_7_10); + ENSURE (r == b_7_10); r_post = ++r; - SASSERT (r_post == b_17_10); - SASSERT (r == b_17_10); + ENSURE (r_post == b_17_10); + ENSURE (r == b_17_10); r_pre = r--; - SASSERT (r_pre == b_17_10); - SASSERT (r == b_7_10); + ENSURE (r_pre == b_17_10); + ENSURE (r == b_7_10); r_pre = r; r_pre += inf_rational(1,2); r_post = r_pre; r_post -= inf_rational(1,2); - SASSERT(r == r_post); - SASSERT(r + inf_rational(1,2) == r_pre); + ENSURE(r == r_post); + ENSURE(r + inf_rational(1,2) == r_pre); r_pre = r; r_pre /= rational(2,1); r_post = r_pre; r_post /= rational(1,2); - SASSERT(r == r_post); - SASSERT(rational(1,2) * r == r_pre); - SASSERT(r == r_pre / rational(1,2)); + ENSURE(r == r_post); + ENSURE(rational(1,2) * r == r_pre); + ENSURE(r == r_pre / rational(1,2)); } @@ -84,27 +84,27 @@ tst_inf_rational() inf_rational r1; inf_rational r2(r1); - SASSERT (r1 == r2); + ENSURE (r1 == r2); inf_rational r3(1); inf_rational r4(0); - SASSERT (r4 == r1); - SASSERT (r3 != r4); + ENSURE (r4 == r1); + ENSURE (r3 != r4); inf_rational r5(0,1); inf_rational r6(1,1); inf_rational r7(2,2); inf_rational r8(7,5); - SASSERT (r1 == r5); - SASSERT (r6 == r3); - SASSERT (r7 == r3); + ENSURE (r1 == r5); + ENSURE (r6 == r3); + ENSURE (r7 == r3); inf_rational r9(rational(7,5)); - SASSERT (r8 == r9); + ENSURE (r8 == r9); r9.reset(); - SASSERT (r1 == r9); - SASSERT (r1.is_int()); - SASSERT (!r8.is_int()); - SASSERT (0 == r1.get_int64()); + ENSURE (r1 == r9); + ENSURE (r1.is_int()); + ENSURE (!r8.is_int()); + ENSURE (0 == r1.get_int64()); r9 = r8; - SASSERT (r8 == r9); + ENSURE (r8 == r9); inf_rational n = numerator(r7); inf_rational d = denominator(r7); @@ -130,50 +130,50 @@ tst_inf_rational() } - SASSERT(inf_rational(rational(1,2),true) > inf_rational(rational(1,2))); - SASSERT(inf_rational(rational(1,2),false) < inf_rational(rational(1,2))); - SASSERT(inf_rational(rational(1,2),true) >= inf_rational(rational(1,2))); - SASSERT(inf_rational(rational(1,2)) >= inf_rational(rational(1,2),false)); - SASSERT(inf_rational(rational(1,2),false) != inf_rational(rational(1,2))); - SASSERT(inf_rational(rational(1,2),true) != inf_rational(rational(1,2))); - SASSERT(inf_rational(rational(1,2),false) != inf_rational(rational(1,2),true)); + ENSURE(inf_rational(rational(1,2),true) > inf_rational(rational(1,2))); + ENSURE(inf_rational(rational(1,2),false) < inf_rational(rational(1,2))); + ENSURE(inf_rational(rational(1,2),true) >= inf_rational(rational(1,2))); + ENSURE(inf_rational(rational(1,2)) >= inf_rational(rational(1,2),false)); + ENSURE(inf_rational(rational(1,2),false) != inf_rational(rational(1,2))); + ENSURE(inf_rational(rational(1,2),true) != inf_rational(rational(1,2))); + ENSURE(inf_rational(rational(1,2),false) != inf_rational(rational(1,2),true)); inf_rational h_neg(rational(1,2),false); inf_rational h_pos(rational(1,2),true); h_neg.neg(); - SASSERT(h_neg == -inf_rational(rational(1,2),false)); + ENSURE(h_neg == -inf_rational(rational(1,2),false)); h_neg.neg(); - SASSERT(h_neg == inf_rational(rational(1,2),false)); + ENSURE(h_neg == inf_rational(rational(1,2),false)); - SASSERT(r1.is_zero() && !r1.is_one() && !r1.is_neg() && r1.is_nonneg() && r1.is_nonpos() && !r1.is_pos()); - SASSERT(!r3.is_zero() && r3.is_one() && !r3.is_neg() && r3.is_nonneg() && !r3.is_nonpos() && r3.is_pos()); + ENSURE(r1.is_zero() && !r1.is_one() && !r1.is_neg() && r1.is_nonneg() && r1.is_nonpos() && !r1.is_pos()); + ENSURE(!r3.is_zero() && r3.is_one() && !r3.is_neg() && r3.is_nonneg() && !r3.is_nonpos() && r3.is_pos()); - SASSERT(floor(inf_rational(rational(1,2),false)) == rational()); - SASSERT(floor(inf_rational(rational(1,2))) == rational()); - SASSERT(floor(inf_rational(rational(),false)) == rational(-1)); - SASSERT(floor(inf_rational(rational())) == rational()); - SASSERT(floor(inf_rational(rational(),true)) == rational()); - SASSERT(floor(inf_rational(rational(1),false)) == rational()); - SASSERT(floor(inf_rational(rational(1))) == rational(1)); - SASSERT(floor(inf_rational(rational(1),true)) == rational(1)); + ENSURE(floor(inf_rational(rational(1,2),false)) == rational()); + ENSURE(floor(inf_rational(rational(1,2))) == rational()); + ENSURE(floor(inf_rational(rational(),false)) == rational(-1)); + ENSURE(floor(inf_rational(rational())) == rational()); + ENSURE(floor(inf_rational(rational(),true)) == rational()); + ENSURE(floor(inf_rational(rational(1),false)) == rational()); + ENSURE(floor(inf_rational(rational(1))) == rational(1)); + ENSURE(floor(inf_rational(rational(1),true)) == rational(1)); - SASSERT(ceil(inf_rational(rational(1,2),false)) == rational(1)); - SASSERT(ceil(inf_rational(rational(1,2))) == rational(1)); - SASSERT(ceil(inf_rational(rational(),false)) == rational()); - SASSERT(ceil(inf_rational(rational())) == rational()); - SASSERT(ceil(inf_rational(rational(),true)) == rational(1)); - SASSERT(ceil(inf_rational(rational(1),false)) == rational(1)); - SASSERT(ceil(inf_rational(rational(1))) == rational(1)); - SASSERT(ceil(inf_rational(rational(1),true)) == rational(2)); + ENSURE(ceil(inf_rational(rational(1,2),false)) == rational(1)); + ENSURE(ceil(inf_rational(rational(1,2))) == rational(1)); + ENSURE(ceil(inf_rational(rational(),false)) == rational()); + ENSURE(ceil(inf_rational(rational())) == rational()); + ENSURE(ceil(inf_rational(rational(),true)) == rational(1)); + ENSURE(ceil(inf_rational(rational(1),false)) == rational(1)); + ENSURE(ceil(inf_rational(rational(1))) == rational(1)); + ENSURE(ceil(inf_rational(rational(1),true)) == rational(2)); inf_rational x(rational(1,2),true); inf_rational y(1,2); x.swap(y); - SASSERT (x == inf_rational(1,2)); - SASSERT (y == inf_rational(rational(1,2),true)); + ENSURE (x == inf_rational(1,2)); + ENSURE (y == inf_rational(rational(1,2),true)); - SASSERT(inf_rational(1,2) == abs(-inf_rational(1,2))); + ENSURE(inf_rational(1,2) == abs(-inf_rational(1,2))); } diff --git a/src/test/interval.cpp b/src/test/interval.cpp index ac242cc60..c22156988 100644 --- a/src/test/interval.cpp +++ b/src/test/interval.cpp @@ -438,7 +438,7 @@ void tst_pi() { im.pi(i, r); nm.display_decimal(std::cout, im.lower(r), 32); std::cout << " "; nm.display_decimal(std::cout, im.upper(r), 32); std::cout << "\n"; - SASSERT(nm.lt(im.lower(r), im.upper(r))); + ENSURE(nm.lt(im.lower(r), im.upper(r))); } del_interval(imc, r); } diff --git a/src/test/karr.cpp b/src/test/karr.cpp index c5581cc66..11e7ae17f 100644 --- a/src/test/karr.cpp +++ b/src/test/karr.cpp @@ -58,7 +58,7 @@ namespace karr { } lbool is_sat = hb.saturate(); hb.display(std::cout); - SASSERT(is_sat == l_true); + VERIFY(is_sat == l_true); dst.reset(); unsigned basis_size = hb.get_basis_size(); for (unsigned i = 0; i < basis_size; ++i) { @@ -85,7 +85,7 @@ namespace karr { } lbool is_sat = hb.saturate(); hb.display(std::cout); - SASSERT(is_sat == l_true); + VERIFY(is_sat == l_true); dst.reset(); unsigned basis_size = hb.get_basis_size(); bool first_initial = true; @@ -131,7 +131,7 @@ namespace karr { matrix T; // length of rows in Ab are twice as long as // length of rows in src. - SASSERT(2*src.A[0].size() == Ab.A[0].size()); + ENSURE(2*src.A[0].size() == Ab.A[0].size()); vector zeros; for (unsigned i = 0; i < src.A[0].size(); ++i) { zeros.push_back(rational(0)); diff --git a/src/test/list.cpp b/src/test/list.cpp index 5672f4246..e377e7bbf 100644 --- a/src/test/list.cpp +++ b/src/test/list.cpp @@ -27,14 +27,15 @@ static void tst1() { list * l2 = new (r) list(20, l1); list * l3 = new (r) list(30); list * l4 = new (r) list(40, l3); - SASSERT(append(r, l1, static_cast *>(0)) == l1); - SASSERT(append(r, l2, static_cast *>(0)) == l2); - SASSERT(append(r, static_cast *>(0), l2) == l2); - SASSERT(append(r, static_cast *>(0), static_cast *>(0)) == 0); + ENSURE(append(r, l1, static_cast *>(0)) == l1); + ENSURE(append(r, l2, static_cast *>(0)) == l2); + ENSURE(append(r, static_cast *>(0), l2) == l2); + ENSURE(append(r, static_cast *>(0), static_cast *>(0)) == 0); TRACE("list", display(tout, l2->begin(), l2->end()); tout << "\n";); list * l5 = append(r, l4, l2); TRACE("list", display(tout, l5->begin(), l5->end()); tout << "\n";); list * l6 = append(r, l5, l5); + (void) l6; TRACE("list", display(tout, l6->begin(), l6->end()); tout << "\n";); } diff --git a/src/test/lp/CMakeLists.txt b/src/test/lp/CMakeLists.txt new file mode 100644 index 000000000..6683a1758 --- /dev/null +++ b/src/test/lp/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(lp_tst lp_main.cpp lp.cpp $ $ $ $ ) +target_compile_definitions(lp_tst PRIVATE ${Z3_COMPONENT_CXX_DEFINES}) +target_compile_options(lp_tst PRIVATE ${Z3_COMPONENT_CXX_FLAGS}) +target_include_directories(lp_tst PRIVATE ${Z3_COMPONENT_EXTRA_INCLUDE_DIRS}) +target_link_libraries(lp_tst PRIVATE ${Z3_DEPENDENT_LIBS}) +z3_append_linker_flag_list_to_target(lp_tst ${Z3_DEPENDENT_EXTRA_CXX_LINK_FLAGS}) diff --git a/src/test/lp/argument_parser.h b/src/test/lp/argument_parser.h index 706167f49..9590baf7b 100644 --- a/src/test/lp/argument_parser.h +++ b/src/test/lp/argument_parser.h @@ -11,7 +11,7 @@ Author: Lev Nachmanson #include #include -namespace lean { +namespace lp { class argument_parser { std::unordered_map m_options; std::unordered_map m_options_with_after_string; diff --git a/src/test/lp/lp.cpp b/src/test/lp/lp.cpp index 71032d013..d402d4ff7 100644 --- a/src/test/lp/lp.cpp +++ b/src/test/lp/lp.cpp @@ -31,7 +31,7 @@ Author: Lev Nachmanson #include "util/lp/stacked_unordered_set.h" #include "util/lp/int_set.h" #include "util/stopwatch.h" -namespace lean { +namespace lp { unsigned seed = 1; random_gen g_rand; @@ -78,7 +78,7 @@ void test_matrix(sparse_matrix & a) { a.set(i, j, t); - lean_assert(a.get(i, j) == t); + lp_assert(a.get(i, j) == t); unsigned j1; if (j < m - 1) { @@ -170,7 +170,7 @@ vector allocate_basis_heading(unsigned count) { // the rest of initilizatio void init_basic_part_of_basis_heading(vector & basis, vector & basis_heading) { - lean_assert(basis_heading.size() >= basis.size()); + lp_assert(basis_heading.size() >= basis.size()); unsigned m = basis.size(); for (unsigned i = 0; i < m; i++) { unsigned column = basis[i]; @@ -225,7 +225,7 @@ void test_small_lu(lp_settings & settings) { vector non_basic_columns; init_basis_heading_and_non_basic_columns_vector(basis, heading, non_basic_columns); lu l(m, basis, settings); - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); indexed_vector w(m.row_count()); std::cout << "entering 2, leaving 0" << std::endl; l.prepare_entering(2, w); // to init vector w @@ -235,7 +235,7 @@ void test_small_lu(lp_settings & settings) { // std::cout << "we were factoring " << std::endl; // print_matrix(get_B(l)); // #endif - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); std::cout << "entering 4, leaving 3" << std::endl; l.prepare_entering(4, w); // to init vector w l.replace_column(0, w, heading[3]); @@ -247,7 +247,7 @@ void test_small_lu(lp_settings & settings) { print_matrix(&bl, std::cout); } #endif - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); std::cout << "entering 5, leaving 1" << std::endl; l.prepare_entering(5, w); // to init vector w @@ -260,7 +260,7 @@ void test_small_lu(lp_settings & settings) { print_matrix(&bl, std::cout); } #endif - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); std::cout << "entering 3, leaving 2" << std::endl; l.prepare_entering(3, w); // to init vector w l.replace_column(0, w, heading[2]); @@ -272,7 +272,7 @@ void test_small_lu(lp_settings & settings) { print_matrix(&bl, std::cout); } #endif - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); m.add_row(); m.add_column(); @@ -291,7 +291,7 @@ void test_small_lu(lp_settings & settings) { auto columns_to_replace = l.get_set_of_columns_to_replace_for_add_last_rows(heading); l.add_last_rows_to_B(heading, columns_to_replace); std::cout << "here" << std::endl; - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); } #endif @@ -373,7 +373,7 @@ void test_larger_lu_exp(lp_settings & settings) { dense_matrix left_side = l.get_left_side(basis); dense_matrix right_side = l.get_right_side(); - lean_assert(left_side == right_side); + lp_assert(left_side == right_side); int leaving = 3; int entering = 8; for (unsigned i = 0; i < m.row_count(); i++) { @@ -385,12 +385,12 @@ void test_larger_lu_exp(lp_settings & settings) { l.prepare_entering(entering, w); l.replace_column(0, w, heading[leaving]); change_basis(entering, leaving, basis, non_basic_columns, heading); - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); l.prepare_entering(11, w); // to init vector w l.replace_column(0, w, heading[0]); change_basis(11, 0, basis, non_basic_columns, heading); - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); } void test_larger_lu_with_holes(lp_settings & settings) { @@ -432,7 +432,7 @@ void test_larger_lu_with_holes(lp_settings & settings) { l.prepare_entering(8, w); // to init vector w l.replace_column(0, w, heading[0]); change_basis(8, 0, basis, non_basic_columns, heading); - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); } @@ -479,7 +479,7 @@ void test_larger_lu(lp_settings& settings) { l.prepare_entering(9, w); // to init vector w l.replace_column(0, w, heading[0]); change_basis(9, 0, basis, non_basic_columns, heading); - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); } @@ -612,7 +612,7 @@ void test_swap_rows_with_permutation(sparse_matrix& m){ dense_matrix original(&m); permutation_matrix q(dim); print_matrix(m, std::cout); - lean_assert(original == q * m); + lp_assert(original == q * m); for (int i = 0; i < 100; i++) { unsigned row1 = my_random() % dim; unsigned row2 = my_random() % dim; @@ -620,7 +620,7 @@ void test_swap_rows_with_permutation(sparse_matrix& m){ std::cout << "swap " << row1 << " " << row2 << std::endl; m.swap_rows(row1, row2); q.transpose_from_left(row1, row2); - lean_assert(original == q * m); + lp_assert(original == q * m); print_matrix(m, std::cout); std::cout << std::endl; } @@ -636,7 +636,7 @@ void test_swap_cols_with_permutation(sparse_matrix& m){ dense_matrix original(&m); permutation_matrix q(dim); print_matrix(m, std::cout); - lean_assert(original == q * m); + lp_assert(original == q * m); for (int i = 0; i < 100; i++) { unsigned row1 = my_random() % dim; unsigned row2 = my_random() % dim; @@ -644,7 +644,7 @@ void test_swap_cols_with_permutation(sparse_matrix& m){ std::cout << "swap " << row1 << " " << row2 << std::endl; m.swap_rows(row1, row2); q.transpose_from_right(row1, row2); - lean_assert(original == q * m); + lp_assert(original == q * m); print_matrix(m, std::cout); std::cout << std::endl; } @@ -663,8 +663,8 @@ void test_swap_rows(sparse_matrix& m, unsigned i0, unsigned i1){ m.swap_rows(i0, i1); for (unsigned j = 0; j < m.dimension(); j++) { - lean_assert(mcopy(i0, j) == m(i1, j)); - lean_assert(mcopy(i1, j) == m(i0, j)); + lp_assert(mcopy(i0, j) == m(i1, j)); + lp_assert(mcopy(i1, j) == m(i0, j)); } } template @@ -678,15 +678,15 @@ void test_swap_columns(sparse_matrix& m, unsigned i0, unsigned i1){ m.swap_columns(i0, i1); for (unsigned j = 0; j < m.dimension(); j++) { - lean_assert(mcopy(j, i0) == m(j, i1)); - lean_assert(mcopy(j, i1) == m(j, i0)); + lp_assert(mcopy(j, i0) == m(j, i1)); + lp_assert(mcopy(j, i1) == m(j, i0)); } for (unsigned i = 0; i < m.dimension(); i++) { if (i == i0 || i == i1) continue; for (unsigned j = 0; j < m.dimension(); j++) { - lean_assert(mcopy(j, i)== m(j, i)); + lp_assert(mcopy(j, i)== m(j, i)); } } } @@ -748,7 +748,7 @@ void test_pivot_like_swaps_and_pivot(){ m.pivot_row_to_row(pivot_row_0, beta, target_row, settings); // print_matrix(m); for (unsigned j = 0; j < m.dimension(); j++) { - lean_assert(abs(row[j] - m(target_row, j)) < 0.00000001); + lp_assert(abs(row[j] - m(target_row, j)) < 0.00000001); } } @@ -853,57 +853,57 @@ void sparse_matrix_with_permutaions_test() { m.multiply_from_left(q0); for (unsigned i = 0; i < dim; i++) { for (unsigned j = 0; j < dim; j++) { - lean_assert(m(i, j) == dm0.get_elem(q0[i], j)); + lp_assert(m(i, j) == dm0.get_elem(q0[i], j)); } } auto q0_dm = q0 * dm; - lean_assert(m == q0_dm); + lp_assert(m == q0_dm); m.multiply_from_left(q1); for (unsigned i = 0; i < dim; i++) { for (unsigned j = 0; j < dim; j++) { - lean_assert(m(i, j) == dm0.get_elem(q0[q1[i]], j)); + lp_assert(m(i, j) == dm0.get_elem(q0[q1[i]], j)); } } auto q1_q0_dm = q1 * q0_dm; - lean_assert(m == q1_q0_dm); + lp_assert(m == q1_q0_dm); m.multiply_from_right(p0); for (unsigned i = 0; i < dim; i++) { for (unsigned j = 0; j < dim; j++) { - lean_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p0[j])); + lp_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p0[j])); } } auto q1_q0_dm_p0 = q1_q0_dm * p0; - lean_assert(m == q1_q0_dm_p0); + lp_assert(m == q1_q0_dm_p0); m.multiply_from_right(p1); for (unsigned i = 0; i < dim; i++) { for (unsigned j = 0; j < dim; j++) { - lean_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p1[p0[j]])); + lp_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p1[p0[j]])); } } auto q1_q0_dm_p0_p1 = q1_q0_dm_p0 * p1; - lean_assert(m == q1_q0_dm_p0_p1); + lp_assert(m == q1_q0_dm_p0_p1); m.multiply_from_right(p1); for (unsigned i = 0; i < dim; i++) { for (unsigned j = 0; j < dim; j++) { - lean_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p1[p1[p0[j]]])); + lp_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p1[p1[p0[j]]])); } } auto q1_q0_dm_p0_p1_p1 = q1_q0_dm_p0_p1 * p1; - lean_assert(m == q1_q0_dm_p0_p1_p1); + lp_assert(m == q1_q0_dm_p0_p1_p1); } void test_swap_columns() { @@ -1024,7 +1024,7 @@ void test_apply_reverse_from_right_to_perm(permutation_matrix & #ifdef LEAN_DEBUG auto rev = l.get_inverse(); auto rs = pclone * rev; - lean_assert(p == rs) + lp_assert(p == rs) #endif } @@ -1051,8 +1051,8 @@ void test_permutations() { p.apply_reverse_from_right_to_T(v); p.apply_reverse_from_right_to_T(vi); - lean_assert(vectors_are_equal(v, vi.m_data)); - lean_assert(vi.is_OK()); + lp_assert(vectors_are_equal(v, vi.m_data)); + lp_assert(vi.is_OK()); } void lp_solver_test() { @@ -1200,7 +1200,7 @@ void solve_mps_double(std::string file_name, bool look_for_min, unsigned max_ite compare_solutions(reader, primal_solver, solver); print_x(reader, primal_solver); std::cout << "dual cost is " << cost << ", but primal cost is " << primal_cost << std::endl; - lean_assert(false); + lp_assert(false); } } } @@ -1210,7 +1210,7 @@ void solve_mps_double(std::string file_name, bool look_for_min, unsigned max_ite } void solve_mps_rational(std::string file_name, bool look_for_min, unsigned max_iterations, unsigned time_limit, bool dual, argument_parser & args_parser) { - mps_reader reader(file_name); + mps_reader reader(file_name); reader.read(); if (reader.is_ok()) { auto * solver = reader.create_solver(dual); @@ -1224,7 +1224,7 @@ void solve_mps_rational(std::string file_name, bool look_for_min, unsigned max_i // for (auto name: reader.column_names()) { // std::cout << name << "=" << solver->get_column_value_by_name(name) << ' '; // } - lean::mpq cost = solver->get_current_cost(); + lp::mpq cost = solver->get_current_cost(); if (look_for_min) { cost = -cost; } @@ -1262,7 +1262,7 @@ void solve_mps(std::string file_name, argument_parser & args_parser) { void solve_mps_in_rational(std::string file_name, bool dual, argument_parser & /*args_parser*/) { std::cout << "solving " << file_name << std::endl; - mps_reader reader(file_name); + mps_reader reader(file_name); reader.read(); if (reader.is_ok()) { auto * solver = reader.create_solver(dual); @@ -1274,7 +1274,7 @@ void solve_mps_in_rational(std::string file_name, bool dual, argument_parser & / std::cout << name << "=" << solver->get_column_value_by_name(name).get_double() << ' '; } } - std::cout << std::endl << "cost = " << numeric_traits::get_double(solver->get_current_cost()) << std::endl; + std::cout << std::endl << "cost = " << numeric_traits::get_double(solver->get_current_cost()) << std::endl; } delete solver; } else { @@ -1318,7 +1318,7 @@ void test_binary_priority_queue() { for (unsigned i = 0; i < 10; i++) { unsigned de = q.dequeue(); - lean_assert(i == de); + lp_assert(i == de); std::cout << de << std::endl; } q.enqueue(2, 2); @@ -1341,7 +1341,7 @@ void test_binary_priority_queue() { unsigned t = 0; while (q.size() > 0) { unsigned d =q.dequeue(); - lean_assert(t++ == d); + lp_assert(t++ == d); std::cout << d << std::endl; } #endif @@ -1370,7 +1370,7 @@ void solve_mps_with_known_solution(std::string file_name, std::unordered_mapget_status()) << std::endl; if (status != solver->get_status()){ std::cout << "status should be " << lp_status_to_string(status) << std::endl; - lean_assert(status == solver->get_status()); + lp_assert(status == solver->get_status()); throw "status is wrong"; } if (solver->get_status() == lp_status::OPTIMAL) { @@ -1381,7 +1381,7 @@ void solve_mps_with_known_solution(std::string file_name, std::unordered_mapget_column_value_by_name(it.first) << std::endl; } - lean_assert(fabs(it.second - solver->get_column_value_by_name(it.first)) < 0.000001); + lp_assert(fabs(it.second - solver->get_column_value_by_name(it.first)) < 0.000001); } } if (reader.column_names().size() < 20) { @@ -1466,127 +1466,127 @@ void fill_file_names(vector &file_names, std::set & m return; } std::string home_dir_str(home_dir); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l0redund.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l1.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l2.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l3.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l4.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l4fix.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/plan.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/samp2.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/murtagh.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l0.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/AFIRO.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SC50B.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SC50A.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/KB2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SC105.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STOCFOR1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/ADLITTLE.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BLEND.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCAGR7.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SC205.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHARE2B.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/RECIPELP.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/LOTFI.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/VTP-BASE.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHARE1B.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BOEING2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BORE3D.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCORPION.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/CAPRI.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BRANDY.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCAGR25.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCTAP1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/ISRAEL.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCFXM1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BANDM.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/E226.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/AGG.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GROW7.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/ETAMACRO.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FINNIS.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCSD1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STANDATA.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STANDGUB.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BEACONFD.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STAIR.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STANDMPS.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GFRD-PNC.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCRS8.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BOEING1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/MODSZK1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/DEGEN2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FORPLAN.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/AGG2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/AGG3.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCFXM2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHELL.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOT4.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCSD6.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP04S.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SEBA.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GROW15.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FFFFF800.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BNL1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PEROLD.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/QAP8.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCFXM3.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP04L.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GANGES.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCTAP2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GROW22.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP08S.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOT-WE.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/MAROS.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STOCFOR2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/25FV47.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP12S.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCSD8.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FIT1P.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCTAP3.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SIERRA.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOTNOV.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/CZPROB.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FIT1D.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOT-JA.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP08L.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BNL2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/NESM.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/CYCLE.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/acc-tight5.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP12L.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/DEGEN3.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GREENBEA.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GREENBEB.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/80BAU3B.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/TRUSS.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/D2Q06C.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/WOODW.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/QAP12.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/D6CUBE.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOT.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/DFL001.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/WOOD1P.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FIT2P.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOT87.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STOCFOR3.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/QAP15.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FIT2D.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/MAROS-R7.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/FIT2P.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/DFL001.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/D2Q06C.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/80BAU3B.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/GREENBEB.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/GREENBEA.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/BNL2.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/SHIP08L.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/FIT1D.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/SCTAP3.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/SCSD8.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/SCSD6.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/MAROS-R7.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l0redund.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l1.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l2.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l3.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l4.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l4fix.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/plan.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/samp2.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/murtagh.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l0.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/AFIRO.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SC50B.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SC50A.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/KB2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SC105.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STOCFOR1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/ADLITTLE.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BLEND.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCAGR7.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SC205.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHARE2B.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/RECIPELP.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/LOTFI.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/VTP-BASE.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHARE1B.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BOEING2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BORE3D.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCORPION.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/CAPRI.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BRANDY.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCAGR25.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCTAP1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/ISRAEL.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCFXM1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BANDM.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/E226.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/AGG.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GROW7.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/ETAMACRO.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FINNIS.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCSD1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STANDATA.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STANDGUB.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BEACONFD.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STAIR.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STANDMPS.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GFRD-PNC.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCRS8.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BOEING1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/MODSZK1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/DEGEN2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FORPLAN.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/AGG2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/AGG3.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCFXM2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHELL.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOT4.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCSD6.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP04S.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SEBA.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GROW15.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FFFFF800.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BNL1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PEROLD.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/QAP8.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCFXM3.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP04L.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GANGES.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCTAP2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GROW22.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP08S.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOT-WE.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/MAROS.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STOCFOR2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/25FV47.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP12S.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCSD8.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FIT1P.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCTAP3.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SIERRA.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOTNOV.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/CZPROB.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FIT1D.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOT-JA.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP08L.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BNL2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/NESM.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/CYCLE.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/acc-tight5.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP12L.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/DEGEN3.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GREENBEA.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GREENBEB.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/80BAU3B.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/TRUSS.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/D2Q06C.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/WOODW.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/QAP12.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/D6CUBE.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOT.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/DFL001.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/WOOD1P.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FIT2P.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOT87.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STOCFOR3.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/QAP15.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FIT2D.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/MAROS-R7.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/FIT2P.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/DFL001.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/D2Q06C.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/80BAU3B.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/GREENBEB.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/GREENBEA.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/BNL2.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/SHIP08L.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/FIT1D.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/SCTAP3.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/SCSD8.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/SCSD6.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/MAROS-R7.SIF"); } void test_out_dir(std::string out_dir) { @@ -1656,7 +1656,7 @@ void solve_some_mps(argument_parser & args_parser) { } if (!solve_for_rational) { solve_mps(file_names[6], false, 0, time_limit, false, dual, compare_with_primal, args_parser); - solve_mps_with_known_solution(file_names[3], nullptr, INFEASIBLE, dual); // chvatal: 135(d) + solve_mps_with_known_solution(file_names[3], nullptr, lp_status::INFEASIBLE, dual); // chvatal: 135(d) std::unordered_map sol; sol["X1"] = 0; sol["X2"] = 6; @@ -1666,8 +1666,8 @@ void solve_some_mps(argument_parser & args_parser) { sol["X6"] = 1; sol["X7"] = 1; sol["X8"] = 0; - solve_mps_with_known_solution(file_names[9], &sol, OPTIMAL, dual); - solve_mps_with_known_solution(file_names[0], &sol, OPTIMAL, dual); + solve_mps_with_known_solution(file_names[9], &sol, lp_status::OPTIMAL, dual); + solve_mps_with_known_solution(file_names[0], &sol, lp_status::OPTIMAL, dual); sol.clear(); sol["X1"] = 25.0/14.0; // sol["X2"] = 0; @@ -1676,10 +1676,10 @@ void solve_some_mps(argument_parser & args_parser) { // sol["X5"] = 0; // sol["X6"] = 0; // sol["X7"] = 9.0/14.0; - solve_mps_with_known_solution(file_names[5], &sol, OPTIMAL, dual); // chvatal: 135(e) - solve_mps_with_known_solution(file_names[4], &sol, OPTIMAL, dual); // chvatal: 135(e) - solve_mps_with_known_solution(file_names[2], nullptr, UNBOUNDED, dual); // chvatal: 135(c) - solve_mps_with_known_solution(file_names[1], nullptr, UNBOUNDED, dual); // chvatal: 135(b) + solve_mps_with_known_solution(file_names[5], &sol, lp_status::OPTIMAL, dual); // chvatal: 135(e) + solve_mps_with_known_solution(file_names[4], &sol, lp_status::OPTIMAL, dual); // chvatal: 135(e) + solve_mps_with_known_solution(file_names[2], nullptr, lp_status::UNBOUNDED, dual); // chvatal: 135(c) + solve_mps_with_known_solution(file_names[1], nullptr, lp_status::UNBOUNDED, dual); // chvatal: 135(b) solve_mps(file_names[8], false, 0, time_limit, false, dual, compare_with_primal, args_parser); // return; for (auto& s : file_names) { @@ -1706,48 +1706,48 @@ void solve_some_mps(argument_parser & args_parser) { #endif void solve_rational() { - lp_primal_simplex solver; - solver.add_constraint(lp_relation::Equal, lean::mpq(7), 0); - solver.add_constraint(lp_relation::Equal, lean::mpq(-3), 1); + lp_primal_simplex solver; + solver.add_constraint(lp_relation::Equal, lp::mpq(7), 0); + solver.add_constraint(lp_relation::Equal, lp::mpq(-3), 1); // setting the cost int cost[] = {-3, -1, -1, 2, -1, 1, 1, -4}; std::string var_names[8] = {"x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8"}; for (unsigned i = 0; i < 8; i++) { - solver.set_cost_for_column(i, lean::mpq(cost[i])); + solver.set_cost_for_column(i, lp::mpq(cost[i])); solver.give_symbolic_name_to_column(var_names[i], i); } int row0[] = {1, 0, 3, 1, -5, -2 , 4, -6}; for (unsigned i = 0; i < 8; i++) { - solver.set_row_column_coefficient(0, i, lean::mpq(row0[i])); + solver.set_row_column_coefficient(0, i, lp::mpq(row0[i])); } int row1[] = {0, 1, -2, -1, 4, 1, -3, 5}; for (unsigned i = 0; i < 8; i++) { - solver.set_row_column_coefficient(1, i, lean::mpq(row1[i])); + solver.set_row_column_coefficient(1, i, lp::mpq(row1[i])); } int bounds[] = {8, 6, 4, 15, 2, 10, 10, 3}; for (unsigned i = 0; i < 8; i++) { - solver.set_low_bound(i, lean::mpq(0)); - solver.set_upper_bound(i, lean::mpq(bounds[i])); + solver.set_low_bound(i, lp::mpq(0)); + solver.set_upper_bound(i, lp::mpq(bounds[i])); } - std::unordered_map expected_sol; - expected_sol["x1"] = lean::mpq(0); - expected_sol["x2"] = lean::mpq(6); - expected_sol["x3"] = lean::mpq(0); - expected_sol["x4"] = lean::mpq(15); - expected_sol["x5"] = lean::mpq(2); - expected_sol["x6"] = lean::mpq(1); - expected_sol["x7"] = lean::mpq(1); - expected_sol["x8"] = lean::mpq(0); + std::unordered_map expected_sol; + expected_sol["x1"] = lp::mpq(0); + expected_sol["x2"] = lp::mpq(6); + expected_sol["x3"] = lp::mpq(0); + expected_sol["x4"] = lp::mpq(15); + expected_sol["x5"] = lp::mpq(2); + expected_sol["x6"] = lp::mpq(1); + expected_sol["x7"] = lp::mpq(1); + expected_sol["x8"] = lp::mpq(0); solver.find_maximal_solution(); - lean_assert(solver.get_status() == OPTIMAL); + lp_assert(solver.get_status() == lp_status::OPTIMAL); for (auto it : expected_sol) { - lean_assert(it.second == solver.get_column_value_by_name(it.first)); + lp_assert(it.second == solver.get_column_value_by_name(it.first)); } } @@ -1805,7 +1805,7 @@ std::unordered_map * get_solution_from_glpsol_output(std::s return ret; } - lean_assert(split.size() > 3); + lp_assert(split.size() > 3); (*ret)[split[1]] = atof(split[3].c_str()); } while (true); } @@ -1829,7 +1829,7 @@ void test_init_U() { for (unsigned i = 0; i < 3; i++) { for (unsigned j = 0; j < 3; j ++) { - lean_assert(m(i, basis[j]) == u(i, j)); + lp_assert(m(i, basis[j]) == u(i, j)); } } @@ -1857,7 +1857,7 @@ void test_replace_column() { for (unsigned column_to_replace = 0; column_to_replace < m.dimension(); column_to_replace ++) { m.replace_column(column_to_replace, w, settings); for (unsigned i = 0; i < m.dimension(); i++) { - lean_assert(abs(w[i] - m(i, column_to_replace)) < 0.00000001); + lp_assert(abs(w[i] - m(i, column_to_replace)) < 0.00000001); } } } @@ -1961,7 +1961,7 @@ void test_stacked_unsigned() { v = 3; v = 4; v.pop(); - lean_assert(v == 2); + lp_assert(v == 2); v ++; v++; std::cout << "before push v=" << v << std::endl; @@ -1971,7 +1971,7 @@ void test_stacked_unsigned() { v+=1; std::cout << "v = " << v << std::endl; v.pop(2); - lean_assert(v == 4); + lp_assert(v == 4); const unsigned & rr = v; std::cout << rr << std:: endl; @@ -2020,7 +2020,7 @@ void test_stacked_set() { s.push(); s.insert(4); s.pop(); - lean_assert(s() == scopy); + lp_assert(s() == scopy); s.push(); s.push(); s.insert(4); @@ -2028,7 +2028,7 @@ void test_stacked_set() { s.push(); s.insert(4); s.pop(3); - lean_assert(s() == scopy); + lp_assert(s() == scopy); #endif } @@ -2397,15 +2397,15 @@ void test_files_from_directory(std::string test_file_dir, argument_parser & args } -std::unordered_map get_solution_map(lp_solver * lps, mps_reader & reader) { - std::unordered_map ret; +std::unordered_map get_solution_map(lp_solver * lps, mps_reader & reader) { + std::unordered_map ret; for (auto it : reader.column_names()) { ret[it] = lps->get_column_value_by_name(it); } return ret; } -void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_reader * reader) { +void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_reader * reader) { std::string maxng = args_parser.get_option_value("--maxng"); if (maxng.size() > 0) { solver->settings().max_number_of_iterations_with_no_improvements = atoi(maxng.c_str()); @@ -2425,7 +2425,7 @@ void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_read } auto * lps = reader->create_solver(false); lps->find_maximal_solution(); - std::unordered_map sol = get_solution_map(lps, *reader); + std::unordered_map sol = get_solution_map(lps, *reader); std::cout << "status = " << lp_status_to_string(solver->get_status()) << std::endl; return; } @@ -2433,12 +2433,12 @@ void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_read sw.start(); lp_status status = solver->solve(); std::cout << "status is " << lp_status_to_string(status) << ", processed for " << sw.get_current_seconds() <<" seconds, and " << solver->get_total_iterations() << " iterations" << std::endl; - if (solver->get_status() == INFEASIBLE) { - vector> evidence; + if (solver->get_status() == lp_status::INFEASIBLE) { + vector> evidence; solver->get_infeasibility_explanation(evidence); } if (args_parser.option_is_used("--randomize_lar")) { - if (solver->get_status() != OPTIMAL) { + if (solver->get_status() != lp_status::OPTIMAL) { std::cout << "cannot check randomize on an infeazible problem" << std::endl; return; } @@ -2467,7 +2467,7 @@ lar_solver * create_lar_solver_from_file(std::string file_name, argument_parser } return reader.create_lar_solver(); } - mps_reader reader(file_name); + mps_reader reader(file_name); reader.read(); if (!reader.is_ok()) { std::cout << "cannot process " << file_name << std::endl; @@ -2478,8 +2478,8 @@ lar_solver * create_lar_solver_from_file(std::string file_name, argument_parser void test_lar_on_file(std::string file_name, argument_parser & args_parser) { lar_solver * solver = create_lar_solver_from_file(file_name, args_parser); - mps_reader reader(file_name); - mps_reader * mps_reader = nullptr; + mps_reader reader(file_name); + mps_reader * mps_reader = nullptr; reader.read(); if (reader.is_ok()) { mps_reader = & reader; @@ -2524,28 +2524,28 @@ void test_lar_solver(argument_parser & args_parser) { } void test_numeric_pair() { - numeric_pair a; - numeric_pair b(2, lean::mpq(6, 2)); + numeric_pair a; + numeric_pair b(2, lp::mpq(6, 2)); a = b; - numeric_pair c(0.1, 0.5); + numeric_pair c(0.1, 0.5); a += 2*c; a -= c; - lean_assert (a == b + c); - numeric_pair d = a * 2; + lp_assert (a == b + c); + numeric_pair d = a * 2; std::cout << a << std::endl; - lean_assert(b == b); - lean_assert(b < a); - lean_assert(b <= a); - lean_assert(a > b); - lean_assert(a != b); - lean_assert(a >= b); - lean_assert(-a < b); - lean_assert(a < 2 * b); - lean_assert(b + b > a); - lean_assert(lean::mpq(2.1) * b + b > a); - lean_assert(-b * lean::mpq(2.1) - b < lean::mpq(0.99) * a); - std::cout << - b * lean::mpq(2.1) - b << std::endl; - lean_assert(-b *(lean::mpq(2.1) + 1) == - b * lean::mpq(2.1) - b); + lp_assert(b == b); + lp_assert(b < a); + lp_assert(b <= a); + lp_assert(a > b); + lp_assert(a != b); + lp_assert(a >= b); + lp_assert(-a < b); + lp_assert(a < 2 * b); + lp_assert(b + b > a); + lp_assert(lp::mpq(2.1) * b + b > a); + lp_assert(-b * lp::mpq(2.1) - b < lp::mpq(0.99) * a); + std::cout << - b * lp::mpq(2.1) - b << std::endl; + lp_assert(-b *(lp::mpq(2.1) + 1) == - b * lp::mpq(2.1) - b); } void get_matrix_dimensions(std::ifstream & f, unsigned & m, unsigned & n) { @@ -2566,7 +2566,7 @@ void read_row_cols(unsigned i, static_matrix& A, std::ifstream & if (line== "row_end") break; auto r = split_and_trim(line); - lean_assert(r.size() == 4); + lp_assert(r.size() == 4); unsigned j = atoi(r[1].c_str()); double v = atof(r[3].c_str()); A.set(i, j, v); @@ -2594,7 +2594,7 @@ void read_basis(vector & basis, std::ifstream & f) { std::cout << "reading basis" << std::endl; std::string line; getline(f, line); - lean_assert(line == "basis_start"); + lp_assert(line == "basis_start"); do { getline(f, line); if (line == "basis_end") @@ -2607,7 +2607,7 @@ void read_basis(vector & basis, std::ifstream & f) { void read_indexed_vector(indexed_vector & v, std::ifstream & f) { std::string line; getline(f, line); - lean_assert(line == "vector_start"); + lp_assert(line == "vector_start"); do { getline(f, line); if (line == "vector_end") break; @@ -2647,7 +2647,7 @@ void check_lu_from_file(std::string lufile_name) { A.copy_column_to_vector(entering, a); indexed_vector cd(d); B.apply_from_left(cd.m_data, settings); - lean_assert(vectors_are_equal(cd.m_data , a)); + lp_assert(vectors_are_equal(cd.m_data , a)); #endif } @@ -2717,7 +2717,7 @@ void test_term() { auto status = solver.solve(); std::cout << lp_status_to_string(status) << std::endl; std::unordered_map model; - if (status != OPTIMAL) + if (status != lp_status::OPTIMAL) return; solver.get_model(model); @@ -2745,7 +2745,7 @@ void test_evidence_for_total_inf_simple(argument_parser & args_parser) { auto status = solver.solve(); std::cout << lp_status_to_string(status) << std::endl; std::unordered_map model; - lean_assert(solver.get_status() == INFEASIBLE); + lp_assert(solver.get_status() == lp_status::INFEASIBLE); } void test_bound_propagation_one_small_sample1() { /* @@ -2941,8 +2941,8 @@ void test_total_case_l(){ ls.solve(); bound_propagator bp(ls); ls.propagate_bounds_for_touched_rows(bp); - lean_assert(ev.size() == 4); - lean_assert(contains_j_kind(x, GE, - one_of_type(), ev)); + lp_assert(ev.size() == 4); + lp_assert(contains_j_kind(x, GE, - one_of_type(), ev)); } void test_bound_propagation() { test_total_case_u(); @@ -2962,17 +2962,17 @@ void test_int_set() { s.insert(1); s.insert(2); s.print(std::cout); - lean_assert(s.contains(2)); - lean_assert(s.size() == 2); + lp_assert(s.contains(2)); + lp_assert(s.size() == 2); s.erase(2); - lean_assert(s.size() == 1); + lp_assert(s.size() == 1); s.erase(2); - lean_assert(s.size() == 1); + lp_assert(s.size() == 1); s.print(std::cout); s.insert(3); s.insert(2); s.clear(); - lean_assert(s.size() == 0); + lp_assert(s.size() == 0); } @@ -3226,7 +3226,7 @@ void test_lp_local(int argn, char**argv) { ret = 0; return finalize(ret); } - // lean::ccc = 0; + // lp::ccc = 0; return finalize(0); test_init_U(); test_replace_column(); @@ -3243,5 +3243,5 @@ void test_lp_local(int argn, char**argv) { } } void tst_lp(char ** argv, int argc, int& i) { - lean::test_lp_local(argc - 2, argv + 2); + lp::test_lp_local(argc - 2, argv + 2); } diff --git a/src/test/lp/lp_main.cpp b/src/test/lp/lp_main.cpp index a301f38c6..450664fd0 100644 --- a/src/test/lp/lp_main.cpp +++ b/src/test/lp/lp_main.cpp @@ -2,12 +2,12 @@ void gparams_register_modules(){} void mem_initialize() {} void mem_finalize() {} #include "util/rational.h" -namespace lean { +namespace lp { void test_lp_local(int argc, char**argv); } int main(int argn, char**argv){ rational::initialize(); - lean::test_lp_local(argn, argv); + lp::test_lp_local(argn, argv); rational::finalize(); return 0; } diff --git a/src/test/lp/smt_reader.h b/src/test/lp/smt_reader.h index dd38c6bcd..a2ee0f271 100644 --- a/src/test/lp/smt_reader.h +++ b/src/test/lp/smt_reader.h @@ -23,7 +23,7 @@ #include "util/lp/lar_constraints.h" #include #include -namespace lean { +namespace lp { template T from_string(const std::string& str) { @@ -108,13 +108,13 @@ namespace lean { void fill_simple_elem(lisp_elem & lm) { int separator = first_separator(); - lean_assert(-1 != separator && separator != 0); + lp_assert(-1 != separator && separator != 0); lm.m_head = m_line.substr(0, separator); m_line = m_line.substr(separator); } void fill_nested_elem(lisp_elem & lm) { - lean_assert(m_line[0] == '('); + lp_assert(m_line[0] == '('); m_line = m_line.substr(1); int separator = first_separator(); lm.m_head = m_line.substr(0, separator); @@ -181,11 +181,11 @@ namespace lean { } void adjust_rigth_side(formula_constraint & /* c*/, lisp_elem & /*el*/) { - // lean_assert(el.m_head == "0"); // do nothing for the time being + // lp_assert(el.m_head == "0"); // do nothing for the time being } void set_constraint_coeffs(formula_constraint & c, lisp_elem & el) { - lean_assert(el.m_elems.size() == 2); + lp_assert(el.m_elems.size() == 2); set_constraint_coeffs_on_coeff_element(c, el.m_elems[0]); adjust_rigth_side(c, el.m_elems[1]); } @@ -201,7 +201,7 @@ namespace lean { add_mult_elem(c, el.m_elems); } else if (el.m_head == "~") { lisp_elem & minel = el.m_elems[0]; - lean_assert(minel.is_simple()); + lp_assert(minel.is_simple()); c.m_right_side += mpq(str_to_int(minel.m_head)); } else { std::cout << "unexpected input " << el.m_head << std::endl; @@ -211,14 +211,14 @@ namespace lean { } std::string get_name(lisp_elem & name) { - lean_assert(name.is_simple()); - lean_assert(!is_integer(name.m_head)); + lp_assert(name.is_simple()); + lp_assert(!is_integer(name.m_head)); return name.m_head; } void add_mult_elem(formula_constraint & c, std::vector & els) { - lean_assert(els.size() == 2); + lp_assert(els.size() == 2); mpq coeff = get_coeff(els[0]); std::string col_name = get_name(els[1]); c.add_pair(coeff, col_name); @@ -228,16 +228,16 @@ namespace lean { if (le.is_simple()) { return mpq(str_to_int(le.m_head)); } else { - lean_assert(le.m_head == "~"); - lean_assert(le.size() == 1); + lp_assert(le.m_head == "~"); + lp_assert(le.size() == 1); lisp_elem & el = le.m_elems[0]; - lean_assert(el.is_simple()); + lp_assert(el.is_simple()); return -mpq(str_to_int(el.m_head)); } } int str_to_int(std::string & s) { - lean_assert(is_integer(s)); + lp_assert(is_integer(s)); return atoi(s.c_str()); } @@ -245,7 +245,7 @@ namespace lean { if (el.size()) { add_complex_sum_elem(c, el); } else { - lean_assert(is_integer(el.m_head)); + lp_assert(is_integer(el.m_head)); int v = atoi(el.m_head.c_str()); mpq vr(v); c.m_right_side -= vr; @@ -263,7 +263,7 @@ namespace lean { } else if (el.m_head == "+") { add_sum(c, el.m_elems); } else { - lean_assert(false); // unexpected input + lp_assert(false); // unexpected input } } diff --git a/src/test/lp/test_file_reader.h b/src/test/lp/test_file_reader.h index c7a9e3b8b..5daeb21b6 100644 --- a/src/test/lp/test_file_reader.h +++ b/src/test/lp/test_file_reader.h @@ -15,7 +15,7 @@ Author: Lev Nachmanson #include "util/lp/lp_utils.h" #include "util/lp/lp_solver.h" -namespace lean { +namespace lp { template struct test_result { diff --git a/src/test/map.cpp b/src/test/map.cpp index 7e2cc7e70..c0b084b73 100644 --- a/src/test/map.cpp +++ b/src/test/map.cpp @@ -22,22 +22,22 @@ Revision History: static void tst1() { map str2int; str2int.insert("foo", 35); - SASSERT(str2int.contains("foo")); - SASSERT(str2int.find_iterator("foo") != str2int.end()); - SASSERT((*(str2int.find_iterator("foo"))).m_value == 35); - SASSERT(str2int.size() == 1); + ENSURE(str2int.contains("foo")); + ENSURE(str2int.find_iterator("foo") != str2int.end()); + ENSURE((*(str2int.find_iterator("foo"))).m_value == 35); + ENSURE(str2int.size() == 1); str2int.insert("boo", 32); - SASSERT(str2int.contains("foo")); - SASSERT(str2int.find_iterator("foo") != str2int.end()); - SASSERT((*(str2int.find_iterator("foo"))).m_value == 35); - SASSERT(str2int.contains("boo")); - SASSERT(str2int.find_iterator("boo") != str2int.end()); - SASSERT((*(str2int.find_iterator("boo"))).m_value == 32); - SASSERT(str2int.size() == 2); + ENSURE(str2int.contains("foo")); + ENSURE(str2int.find_iterator("foo") != str2int.end()); + ENSURE((*(str2int.find_iterator("foo"))).m_value == 35); + ENSURE(str2int.contains("boo")); + ENSURE(str2int.find_iterator("boo") != str2int.end()); + ENSURE((*(str2int.find_iterator("boo"))).m_value == 32); + ENSURE(str2int.size() == 2); str2int.remove("boo"); - SASSERT(str2int.size() == 1); - SASSERT(!str2int.contains("boo")); - SASSERT(str2int.contains("foo")); + ENSURE(str2int.size() == 1); + ENSURE(!str2int.contains("boo")); + ENSURE(str2int.contains("foo")); } void tst_map() { diff --git a/src/test/model_based_opt.cpp b/src/test/model_based_opt.cpp index 64b2df285..5ee671a4a 100644 --- a/src/test/model_based_opt.cpp +++ b/src/test/model_based_opt.cpp @@ -20,6 +20,7 @@ static void add_ineq(opt::model_based_opt& mbo, mbo.add_constraint(vars, rational(k), rel); } +#if 0 static void add_ineq(opt::model_based_opt& mbo, unsigned x, int a, unsigned y, int b, @@ -31,6 +32,7 @@ static void add_ineq(opt::model_based_opt& mbo, vars.push_back(var(z, rational(c))); mbo.add_constraint(vars, rational(k), rel); } +#endif static void add_random_ineq(opt::model_based_opt& mbo, random_gen& r, @@ -295,7 +297,7 @@ static void test8() { unsigned z = mbo.add_var(rational(4)); unsigned u = mbo.add_var(rational(5)); unsigned v = mbo.add_var(rational(6)); - unsigned w = mbo.add_var(rational(6)); + // unsigned w = mbo.add_var(rational(6)); add_ineq(mbo, x0, 1, y, -1, 0, opt::t_le); add_ineq(mbo, x, 1, y, -1, 0, opt::t_lt); diff --git a/src/test/model_evaluator.cpp b/src/test/model_evaluator.cpp index 0b509fba6..00048b230 100644 --- a/src/test/model_evaluator.cpp +++ b/src/test/model_evaluator.cpp @@ -28,7 +28,6 @@ void tst_model_evaluator() { expr_ref vB2(m.mk_var(2, m.mk_bool_sort()), m); expr* vI0p = vI0.get(); expr* vI1p = vI1.get(); - expr* vB0p = vB0.get(); expr* vB1p = vB1.get(); expr* vB2p = vB2.get(); diff --git a/src/test/mpf.cpp b/src/test/mpf.cpp index d12675b6d..f00152b09 100644 --- a/src/test/mpf.cpp +++ b/src/test/mpf.cpp @@ -24,38 +24,38 @@ static void bug_set_int() { scoped_mpf a(fm); fm.set(a, 11, 53, 3); - SASSERT(fm.to_double(a) == 3.0); + ENSURE(fm.to_double(a) == 3.0); fm.set(a, 11, 53, 0); - SASSERT(fm.to_double(a) == 0.0); + ENSURE(fm.to_double(a) == 0.0); fm.set(a, 11, 53, -1); - SASSERT(fm.to_double(a) == -1.0); + ENSURE(fm.to_double(a) == -1.0); fm.set(a, 11, 53, INT_MAX); - SASSERT(fm.to_double(a) == (double)INT_MAX); + ENSURE(fm.to_double(a) == (double)INT_MAX); fm.set(a, 11, 53, INT_MIN); - SASSERT(fm.to_double(a) == (double)INT_MIN); + ENSURE(fm.to_double(a) == (double)INT_MIN); fm.set(a, 8, 24, 3); - SASSERT(fm.to_float(a) == 3.0); - SASSERT(fm.to_double(a) == 3.0); + ENSURE(fm.to_float(a) == 3.0); + ENSURE(fm.to_double(a) == 3.0); fm.set(a, 8, 24, 0); - SASSERT(fm.to_float(a) == 0.0); - SASSERT(fm.to_double(a) == 0.0); + ENSURE(fm.to_float(a) == 0.0); + ENSURE(fm.to_double(a) == 0.0); fm.set(a, 8, 24, -1); - SASSERT(fm.to_float(a) == -1.0); - SASSERT(fm.to_double(a) == -1.0); + ENSURE(fm.to_float(a) == -1.0); + ENSURE(fm.to_double(a) == -1.0); fm.set(a, 8, 24, INT_MIN); - SASSERT(fm.to_float(a) == (float)INT_MIN); + ENSURE(fm.to_float(a) == (float)INT_MIN); // CMW: This one depends on the rounding mode, but fm.set(..., int) doesn't have one. // fm.set(a, 8, 24, INT_MAX); - // SASSERT(fm.to_float(a) == (float)INT_MAX); + // ENSURE(fm.to_float(a) == (float)INT_MAX); } static void bug_set_double() { @@ -63,22 +63,22 @@ static void bug_set_double() { scoped_mpf a(fm); fm.set(a, 11, 53, 2.5); - SASSERT(fm.to_double(a) == 2.5); + ENSURE(fm.to_double(a) == 2.5); fm.set(a, 11, 53, -42.25); - SASSERT(fm.to_double(a) == -42.25); + ENSURE(fm.to_double(a) == -42.25); fm.set(a, 8, 24, (double)2.5); - SASSERT(fm.to_double(a) == 2.5); + ENSURE(fm.to_double(a) == 2.5); fm.set(a, 8, 24, (double)-42.25); - SASSERT(fm.to_double(a) == -42.25); + ENSURE(fm.to_double(a) == -42.25); fm.set(a, 8, 24, (float)2.5); - SASSERT(fm.to_float(a) == 2.5); + ENSURE(fm.to_float(a) == 2.5); fm.set(a, 8, 24, (float)-42.25); - SASSERT(fm.to_float(a) == -42.25); + ENSURE(fm.to_float(a) == -42.25); } void tst_mpf() { diff --git a/src/test/mpff.cpp b/src/test/mpff.cpp index 44930f2bd..af67d9ff5 100644 --- a/src/test/mpff.cpp +++ b/src/test/mpff.cpp @@ -77,10 +77,10 @@ static void tst5() { scoped_mpff a(m), b(m); m.set(a, static_cast(1) << 63); m.display_raw(std::cout, a); std::cout << "\n"; - SASSERT(m.is_zero(b)); - SASSERT(m.lt(b, a)); + ENSURE(m.is_zero(b)); + ENSURE(m.lt(b, a)); m.set(b, -1); - SASSERT(m.lt(b, a)); + ENSURE(m.lt(b, a)); } static void tst6() { @@ -90,10 +90,10 @@ static void tst6() { std::cout << "mpff(1/3) " << a << "\n"; b = a; m.next(b); - SASSERT(m.lt(a, b)); + ENSURE(m.lt(a, b)); std::cout << "b: " << b << "\n"; m.prev(b); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); m.ceil(b); std::cout << "b: " << b << "\n"; m.set(b, 4, 3); @@ -135,15 +135,15 @@ static void tst_ ## OP ## _core(int64 n1, uint64 d1, int64 n2, uint64 d2, unsign fm.round_to_plus_inf(); \ fm.OP(fa, fb, fc1); \ fm.to_mpq(fc1, qm, qt); \ - SASSERT(qm.le(qc, qt)); \ + ENSURE(qm.le(qc, qt)); \ } \ { \ fm.round_to_minus_inf(); \ fm.OP(fa, fb, fc2); \ fm.to_mpq(fc2, qm, qt); \ - SASSERT(qm.le(qt, qc)); \ + ENSURE(qm.le(qt, qc)); \ } \ - SASSERT(fm.le(fc2, fc1)); \ + ENSURE(fm.le(fc2, fc1)); \ } MK_BIN_OP(add); @@ -182,7 +182,7 @@ static void tst_bug() { scoped_mpq b(qm), c(qm); qm.set(b, 41, 36); fm.to_mpq(a, qm, c); - SASSERT(qm.le(b, c)); + ENSURE(qm.le(b, c)); } static void tst_bug2() { @@ -191,16 +191,16 @@ static void tst_bug2() { fm.set(b, 1); fm.sub(a, b, b); fm.set(a, -1); - SASSERT(fm.eq(a, b)); + ENSURE(fm.eq(a, b)); fm.set(a, 1); fm.set(b, 0); fm.sub(a, b, a); fm.set(b, 1); - SASSERT(fm.eq(a, b)); + ENSURE(fm.eq(a, b)); fm.set(a, 1); fm.set(b, 1); fm.sub(a, b, a); - SASSERT(fm.is_zero(a)); + ENSURE(fm.is_zero(a)); } static void tst_set64(unsigned N, unsigned prec) { @@ -208,69 +208,69 @@ static void tst_set64(unsigned N, unsigned prec) { scoped_mpff a(fm); fm.set(a, static_cast(INT64_MAX)); - SASSERT(fm.is_int64(a)); - SASSERT(fm.is_uint64(a)); + ENSURE(fm.is_int64(a)); + ENSURE(fm.is_uint64(a)); fm.inc(a); - SASSERT(!fm.is_int64(a)); - SASSERT(fm.is_uint64(a)); - SASSERT(fm.is_int(a)); + ENSURE(!fm.is_int64(a)); + ENSURE(fm.is_uint64(a)); + ENSURE(fm.is_int(a)); fm.dec(a); - SASSERT(fm.is_int64(a)); - SASSERT(fm.is_uint64(a)); + ENSURE(fm.is_int64(a)); + ENSURE(fm.is_uint64(a)); fm.dec(a); - SASSERT(fm.is_int64(a)); - SASSERT(fm.is_uint64(a)); + ENSURE(fm.is_int64(a)); + ENSURE(fm.is_uint64(a)); fm.set(a, static_cast(INT64_MIN)); - SASSERT(fm.is_int64(a)); - SASSERT(!fm.is_uint64(a)); + ENSURE(fm.is_int64(a)); + ENSURE(!fm.is_uint64(a)); fm.dec(a); - SASSERT(!fm.is_int64(a)); - SASSERT(!fm.is_uint64(a)); - SASSERT(fm.is_int(a)); + ENSURE(!fm.is_int64(a)); + ENSURE(!fm.is_uint64(a)); + ENSURE(fm.is_int(a)); fm.inc(a); - SASSERT(fm.is_int64(a)); - SASSERT(!fm.is_uint64(a)); + ENSURE(fm.is_int64(a)); + ENSURE(!fm.is_uint64(a)); fm.inc(a); - SASSERT(fm.is_int64(a)); - SASSERT(!fm.is_uint64(a)); + ENSURE(fm.is_int64(a)); + ENSURE(!fm.is_uint64(a)); fm.set(a, static_cast(UINT64_MAX)); - SASSERT(fm.is_uint64(a)); - SASSERT(!fm.is_int64(a)); + ENSURE(fm.is_uint64(a)); + ENSURE(!fm.is_int64(a)); fm.inc(a); - SASSERT(!fm.is_uint64(a)); - SASSERT(!fm.is_int64(a)); + ENSURE(!fm.is_uint64(a)); + ENSURE(!fm.is_int64(a)); fm.dec(a); - SASSERT(fm.is_uint64(a)); - SASSERT(!fm.is_int64(a)); + ENSURE(fm.is_uint64(a)); + ENSURE(!fm.is_int64(a)); fm.dec(a); - SASSERT(fm.is_uint64(a)); - SASSERT(!fm.is_int64(a)); + ENSURE(fm.is_uint64(a)); + ENSURE(!fm.is_int64(a)); for (unsigned i = 0; i < N; i++) { { uint64 v = (static_cast(rand()) << 32) + static_cast(rand()); fm.set(a, v); - SASSERT(fm.is_uint64(a)); + ENSURE(fm.is_uint64(a)); v = (static_cast(rand() % 3) << 32) + static_cast(rand()); fm.set(a, v); - SASSERT(fm.is_uint64(a)); + ENSURE(fm.is_uint64(a)); } { int64 v = (static_cast(rand() % INT_MAX) << 32) + static_cast(rand()); if (rand()%2 == 0) v = -v; fm.set(a, v); - SASSERT(fm.is_int64(a)); + ENSURE(fm.is_int64(a)); v = (static_cast(rand() % 3) << 32) + static_cast(rand()); if (rand()%2 == 0) v = -v; fm.set(a, v); - SASSERT(fm.is_int64(a)); + ENSURE(fm.is_int64(a)); } } } @@ -282,12 +282,12 @@ static void tst_capacity(unsigned prec = 2) { for (unsigned i = 0; i < 50000; i++) { m.set(a, i); v.push_back(a); - SASSERT(m.is_int(v.back())); - SASSERT(m.is_int64(v.back())); - SASSERT(m.is_uint64(v.back())); + ENSURE(m.is_int(v.back())); + ENSURE(m.is_int64(v.back())); + ENSURE(m.is_uint64(v.back())); } for (unsigned i = 0; i < 50000; i++) { - SASSERT(m.get_int64(v[i]) == i); + ENSURE(m.get_int64(v[i]) == i); } } @@ -296,241 +296,239 @@ static void tst_power(unsigned prec = 2) { scoped_mpff a(m), b(m); // 0^k == 0 - SASSERT(m.is_zero(a)); + ENSURE(m.is_zero(a)); m.power(a, 10, a); - SASSERT(m.is_zero(a)); + ENSURE(m.is_zero(a)); // a != 0 ==> a^0 == 1 m.set(a, 33); m.power(a, 0, a); - SASSERT(m.is_one(a)); + ENSURE(m.is_one(a)); m.set(a, -33); m.power(a, 0, a); - SASSERT(m.is_one(a)); + ENSURE(m.is_one(a)); // a^1 == a m.set(a, 33); m.power(a, 1, b); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); m.set(a, -33); m.power(a, 1, b); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); // checking special support for powers of 2 -#ifdef Z3DEBUG unsigned k; -#endif m.set(a, 1); - SASSERT(m.is_power_of_two(a, k) && k == 0); + ENSURE(m.is_power_of_two(a, k) && k == 0); m.set(a, 2); - SASSERT(m.is_power_of_two(a, k) && k == 1); + ENSURE(m.is_power_of_two(a, k) && k == 1); m.set(a, 3); - SASSERT(!m.is_power_of_two(a, k)); + ENSURE(!m.is_power_of_two(a, k)); m.set(a, 4); - SASSERT(m.is_power_of_two(a, k) && k == 2); + ENSURE(m.is_power_of_two(a, k) && k == 2); m.set(a, -4); - SASSERT(!m.is_power_of_two(a, k)); + ENSURE(!m.is_power_of_two(a, k)); m.set(a, 8); - SASSERT(m.is_power_of_two(a, k) && k == 3); + ENSURE(m.is_power_of_two(a, k) && k == 3); m.set(a, 0); - SASSERT(!m.is_power_of_two(a)); + ENSURE(!m.is_power_of_two(a)); m.set(a, UINT_MAX); m.inc(a); - SASSERT(m.is_power_of_two(a, k) && k == 32); - SASSERT(m.get_uint64(a) == static_cast(UINT_MAX) + 1); + ENSURE(m.is_power_of_two(a, k) && k == 32); + ENSURE(m.get_uint64(a) == static_cast(UINT_MAX) + 1); m.power(a, 2, a); - SASSERT(m.is_power_of_two(a, k) && k == 64); + ENSURE(m.is_power_of_two(a, k) && k == 64); m.power(a, 4, a); - SASSERT(m.is_power_of_two(a, k) && k == 256); + ENSURE(m.is_power_of_two(a, k) && k == 256); m.round_to_plus_inf(); m.inc(a); - SASSERT(!m.is_power_of_two(a, k)); + ENSURE(!m.is_power_of_two(a, k)); m.set(a, -4); m.power(a, 3, a); m.set(b, -64); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); m.set(a, -4); m.power(a, 4, a); m.set(b, 256); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); // additional tests m.set(a, 5); m.power(a, 3, a); m.set(b, 5*5*5); - SASSERT(m.eq(a,b)); + ENSURE(m.eq(a,b)); m.set(a, -5); m.power(a, 3, a); m.set(b, -5*5*5); - SASSERT(m.eq(a,b)); + ENSURE(m.eq(a,b)); } static void tst_sgn(unsigned prec) { mpff_manager m(prec); scoped_mpff a(m), b(m); - SASSERT(m.is_zero(a) && !m.is_pos(a) && !m.is_neg(a) && m.is_nonpos(a) && m.is_nonneg(a)); + ENSURE(m.is_zero(a) && !m.is_pos(a) && !m.is_neg(a) && m.is_nonpos(a) && m.is_nonneg(a)); m.set(a, 3); - SASSERT(!m.is_zero(a) && m.is_pos(a) && !m.is_neg(a) && !m.is_nonpos(a) && m.is_nonneg(a)); + ENSURE(!m.is_zero(a) && m.is_pos(a) && !m.is_neg(a) && !m.is_nonpos(a) && m.is_nonneg(a)); m.set(a, -3); - SASSERT(!m.is_zero(a) && !m.is_pos(a) && m.is_neg(a) && m.is_nonpos(a) && !m.is_nonneg(a)); + ENSURE(!m.is_zero(a) && !m.is_pos(a) && m.is_neg(a) && m.is_nonpos(a) && !m.is_nonneg(a)); m.set(a, 8); m.power(a, 256, a); - SASSERT(!m.is_zero(a) && m.is_pos(a) && !m.is_neg(a) && !m.is_nonpos(a) && m.is_nonneg(a)); + ENSURE(!m.is_zero(a) && m.is_pos(a) && !m.is_neg(a) && !m.is_nonpos(a) && m.is_nonneg(a)); b = a; m.neg(a); - SASSERT(m.neq(a, b)); - SASSERT(!m.is_zero(a) && !m.is_pos(a) && m.is_neg(a) && m.is_nonpos(a) && !m.is_nonneg(a)); + ENSURE(m.neq(a, b)); + ENSURE(!m.is_zero(a) && !m.is_pos(a) && m.is_neg(a) && m.is_nonpos(a) && !m.is_nonneg(a)); m.neg(a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); m.set(a, 1); - SASSERT(m.is_one(a) && !m.is_zero(a) && !m.is_minus_one(a) && m.is_abs_one(a)); + ENSURE(m.is_one(a) && !m.is_zero(a) && !m.is_minus_one(a) && m.is_abs_one(a)); m.neg(a); - SASSERT(!m.is_one(a) && !m.is_zero(a) && m.is_minus_one(a) && m.is_abs_one(a)); + ENSURE(!m.is_one(a) && !m.is_zero(a) && m.is_minus_one(a) && m.is_abs_one(a)); m.set(a, 3); - SASSERT(!m.is_one(a) && !m.is_zero(a) && !m.is_minus_one(a)); + ENSURE(!m.is_one(a) && !m.is_zero(a) && !m.is_minus_one(a)); m.set(a, 3); b = a; m.abs(a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); m.set(a, -3); b = a; m.abs(a); - SASSERT(!m.eq(a,b) && m.is_pos(a)); + ENSURE(!m.eq(a,b) && m.is_pos(a)); m.set(a, 1); m.swap(a, a); - SASSERT(m.is_one(a)); + ENSURE(m.is_one(a)); m.set(b, -1); m.swap(a, b); - SASSERT(m.is_one(b) && m.is_minus_one(a)); + ENSURE(m.is_one(b) && m.is_minus_one(a)); m.neg(a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); } static void tst_limits(unsigned prec) { mpff_manager m(prec); scoped_mpff a(m), b(m), two(m); m.set_max(a); - SASSERT(m.is_pos(a)); + ENSURE(m.is_pos(a)); m.set_min(b); - SASSERT(m.is_neg(b)); + ENSURE(m.is_neg(b)); m.neg(a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); m.set_max(a); m.set_max(b); m.round_to_minus_inf(); m.inc(a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); m.dec(a); - SASSERT(m.lt(a, b)); + ENSURE(m.lt(a, b)); m.set_max(a); m.round_to_plus_inf(); bool overflow = false; try { m.inc(a); } catch (mpff_manager::overflow_exception) { overflow = true; } - SASSERT(overflow); + VERIFY(overflow); m.set_max(a); m.dec(a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); m.set_min(a); m.set_min(b); m.round_to_minus_inf(); m.inc(a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); overflow = true; try { m.dec(a); } catch (mpff_manager::overflow_exception) { overflow = true; } - SASSERT(overflow); + ENSURE(overflow); m.round_to_plus_inf(); m.set_min(a); m.inc(a); - SASSERT(m.gt(a,b)); + ENSURE(m.gt(a,b)); m.set_min(a); m.dec(a); - SASSERT(m.eq(a,b)); + ENSURE(m.eq(a,b)); m.set_plus_epsilon(a); m.set_plus_epsilon(b); - SASSERT(!m.is_zero(a) && m.is_pos(a)); + ENSURE(!m.is_zero(a) && m.is_pos(a)); m.set(two, 2); m.round_to_plus_inf(); m.div(a, two, a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); m.round_to_minus_inf(); m.div(a, two, a); - SASSERT(m.is_zero(a)); + ENSURE(m.is_zero(a)); m.round_to_plus_inf(); m.set_plus_epsilon(a); m.add(a, a, a); - SASSERT(m.gt(a, b)); + ENSURE(m.gt(a, b)); m.round_to_minus_inf(); m.set_plus_epsilon(a); m.add(a, a, a); - SASSERT(m.gt(a, b)); + ENSURE(m.gt(a, b)); m.set_plus_epsilon(a); m.sub(a, a, a); - SASSERT(m.is_zero(a)); + ENSURE(m.is_zero(a)); m.set_plus_epsilon(a); - SASSERT(m.is_plus_epsilon(a)); - SASSERT(!m.is_minus_epsilon(a)); + ENSURE(m.is_plus_epsilon(a)); + ENSURE(!m.is_minus_epsilon(a)); m.neg(a); - SASSERT(!m.is_plus_epsilon(a)); - SASSERT(m.is_minus_epsilon(a)); + ENSURE(!m.is_plus_epsilon(a)); + ENSURE(m.is_minus_epsilon(a)); for (unsigned i = 0; i < 2; i++) { m.set_rounding(i == 0); m.set_plus_epsilon(a); m.floor(a); - SASSERT(m.is_zero(a)); + ENSURE(m.is_zero(a)); m.set_plus_epsilon(a); m.ceil(a); - SASSERT(m.is_one(a)); + ENSURE(m.is_one(a)); m.set_minus_epsilon(a); m.floor(a); - SASSERT(m.is_minus_one(a)); + ENSURE(m.is_minus_one(a)); m.set_minus_epsilon(a); m.ceil(a); - SASSERT(m.is_zero(a)); + ENSURE(m.is_zero(a)); } m.set_minus_epsilon(a); m.set_minus_epsilon(b); - SASSERT(!m.is_zero(a) && m.is_neg(a)); + ENSURE(!m.is_zero(a) && m.is_neg(a)); m.set(two, 2); m.round_to_minus_inf(); m.div(a, two, a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); m.round_to_plus_inf(); m.div(a, two, a); - SASSERT(m.is_zero(a)); + ENSURE(m.is_zero(a)); m.round_to_plus_inf(); m.set_minus_epsilon(a); m.add(a, a, a); - SASSERT(m.lt(a, b)); + ENSURE(m.lt(a, b)); m.round_to_minus_inf(); m.set_minus_epsilon(a); m.add(a, a, a); - SASSERT(m.lt(a, b)); + ENSURE(m.lt(a, b)); m.set_minus_epsilon(a); m.sub(a, a, a); - SASSERT(m.is_zero(a)); + ENSURE(m.is_zero(a)); m.set_minus_epsilon(a); - SASSERT(!m.is_plus_epsilon(a)); - SASSERT(m.is_minus_epsilon(a)); + ENSURE(!m.is_plus_epsilon(a)); + ENSURE(m.is_minus_epsilon(a)); m.neg(a); - SASSERT(m.is_plus_epsilon(a)); - SASSERT(!m.is_minus_epsilon(a)); + ENSURE(m.is_plus_epsilon(a)); + ENSURE(!m.is_minus_epsilon(a)); } #if 0 @@ -549,7 +547,7 @@ static void tst_decimal(int64 n, uint64 d, bool to_plus_inf, unsigned prec, char m.display_decimal(std::cout, a, decimal_places); std::cout << std::endl; std::ostringstream buffer; m.display_decimal(buffer, a, decimal_places); - SASSERT(strcmp(expected, buffer.str().c_str()) == 0); + ENSURE(strcmp(expected, buffer.str().c_str()) == 0); } static void tst_decimal() { @@ -573,7 +571,7 @@ static void tst_prev_power_2(int64 n, uint64 d, unsigned expected) { mpff_manager m; scoped_mpff a(m); m.set(a, n, d); - SASSERT(m.prev_power_of_two(a) == expected); + ENSURE(m.prev_power_of_two(a) == expected); } static void tst_prev_power_2() { diff --git a/src/test/mpfx.cpp b/src/test/mpfx.cpp index 9e8882a26..c83f73bad 100644 --- a/src/test/mpfx.cpp +++ b/src/test/mpfx.cpp @@ -39,7 +39,7 @@ static void tst_prev_power_2(int64 n, uint64 d, unsigned expected) { mpfx_manager m; scoped_mpfx a(m); m.set(a, n, d); - SASSERT(m.prev_power_of_two(a) == expected); + ENSURE(m.prev_power_of_two(a) == expected); } static void tst_prev_power_2() { diff --git a/src/test/mpq.cpp b/src/test/mpq.cpp index 68c7d8bb3..0da7a584a 100644 --- a/src/test/mpq.cpp +++ b/src/test/mpq.cpp @@ -27,7 +27,7 @@ static void tst0() { m.set(a, 2, 3); m.set(b, 4, 3); m.div(a, b, b); - SASSERT(m.eq(b, m.mk_q(1, 2))); + ENSURE(m.eq(b, m.mk_q(1, 2))); } static void tst1() { @@ -41,15 +41,15 @@ static void tst1() { std::cout << "*-2 = \n" << m.to_string(v2) << "\n"; m.add(v, v2, v3); m.neg(v3); - SASSERT(m.eq(v, v3)); - SASSERT(m.le(v, v3)); - SASSERT(m.ge(v, v3)); - SASSERT(m.lt(v2, v)); - SASSERT(m.le(v2, v)); - SASSERT(m.gt(v, v2)); - SASSERT(m.ge(v, v2)); - SASSERT(m.neq(v, v2)); - SASSERT(!m.neq(v, v3)); + ENSURE(m.eq(v, v3)); + ENSURE(m.le(v, v3)); + ENSURE(m.ge(v, v3)); + ENSURE(m.lt(v2, v)); + ENSURE(m.le(v2, v)); + ENSURE(m.gt(v, v2)); + ENSURE(m.ge(v, v2)); + ENSURE(m.neq(v, v2)); + ENSURE(!m.neq(v, v3)); m.del(v); m.del(v2); m.del(v3); @@ -68,7 +68,7 @@ static void mk_random_num_str(unsigned buffer_sz, char * buffer) { if (div_pos == 0) div_pos++; } - SASSERT(sz < buffer_sz); + ENSURE(sz < buffer_sz); for (unsigned i = 0; i < sz-1; i++) { if (i == div_pos && i < sz-2) { buffer[i] = '/'; @@ -90,7 +90,7 @@ static void bug1() { m.set(a, 2); m.set(b, 1, 2); m.inv(a, a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); } static void bug2() { @@ -100,7 +100,7 @@ static void bug2() { m.set(a, -2); m.set(b, -1, 2); m.inv(a, a); - SASSERT(m.eq(a, b)); + ENSURE(m.eq(a, b)); } static void tst2() { @@ -122,22 +122,22 @@ static void set_str_bug() { m.set(a, "1.0"); std::cout << a << "\n"; m.set(b, 1); - SASSERT(a == b); + ENSURE(a == b); m.set(a, "1.1"); std::cout << a << "\n"; m.set(b, 11, 10); - SASSERT(a == b); + ENSURE(a == b); m.set(a, "1/3"); m.set(b, 1, 3); std::cout << a << "\n"; - SASSERT(a == b); + ENSURE(a == b); } static void tst_prev_power_2(int64 n, uint64 d, unsigned expected) { unsynch_mpq_manager m; scoped_mpq a(m); m.set(a, n, d); - SASSERT(m.prev_power_of_two(a) == expected); + ENSURE(m.prev_power_of_two(a) == expected); } static void tst_prev_power_2() { diff --git a/src/test/mpz.cpp b/src/test/mpz.cpp index ee7cf39f1..1c587f8e9 100644 --- a/src/test/mpz.cpp +++ b/src/test/mpz.cpp @@ -33,15 +33,15 @@ static void tst1() { std::cout << "*-2 = \n" << m.to_string(v2) << "\n"; m.add(v, v2, v3); m.neg(v3); - SASSERT(m.eq(v, v3)); - SASSERT(m.le(v, v3)); - SASSERT(m.ge(v, v3)); - SASSERT(m.lt(v2, v)); - SASSERT(m.le(v2, v)); - SASSERT(m.gt(v, v2)); - SASSERT(m.ge(v, v2)); - SASSERT(m.neq(v, v2)); - SASSERT(!m.neq(v, v3)); + ENSURE(m.eq(v, v3)); + ENSURE(m.le(v, v3)); + ENSURE(m.ge(v, v3)); + ENSURE(m.lt(v2, v)); + ENSURE(m.le(v2, v)); + ENSURE(m.gt(v, v2)); + ENSURE(m.ge(v, v2)); + ENSURE(m.neq(v, v2)); + ENSURE(!m.neq(v, v3)); m.del(v); m.del(v2); m.del(v3); @@ -80,7 +80,7 @@ static void tst2b() { #if 0 static void mk_random_num_str(unsigned buffer_sz, char * buffer) { unsigned sz = (rand() % (buffer_sz-2)) + 1; - SASSERT(sz < buffer_sz); + ENSURE(sz < buffer_sz); for (unsigned i = 0; i < sz-1; i++) { buffer[i] = '0' + (rand() % 10); } @@ -96,7 +96,7 @@ static void bug1() { m.set(v1, "1002043949858757875676767675747473"); mpz v2; m.sub(v1, v1, v2); - SASSERT(m.is_zero(v2)); + ENSURE(m.is_zero(v2)); m.del(v1); m.del(v2); } @@ -119,7 +119,7 @@ static void bug3() { m.set(v2, INT_MAX); m.add(v2, m.mk_z(1), v2); m.neg(v1); - SASSERT(m.eq(v1, v2)); + ENSURE(m.eq(v1, v2)); m.del(v1); m.del(v2); } @@ -137,7 +137,7 @@ static void bug4() { m.bitwise_or(result2, y, result2); std::cout << m.to_string(result1) << " " << m.to_string(result2) << "\n"; - SASSERT(m.eq(result1, result2)); + ENSURE(m.eq(result1, result2)); m.del(x); m.del(y); m.del(result1); m.del(result2); } @@ -147,8 +147,9 @@ void tst_div2k(synch_mpz_manager & m, mpz const & v, unsigned k) { m.power(two, k, pw); m.machine_div(v, pw, y); bool is_eq = m.eq(x, y); + (void)is_eq; CTRACE("mpz_2k", !is_eq, tout << "div: " << m.to_string(v) << ", k: " << k << " r: " << m.to_string(x) << ", expected: " << m.to_string(y) << "\n";); - SASSERT(is_eq); + ENSURE(is_eq); m.del(x); m.del(y); m.del(pw); @@ -174,8 +175,9 @@ void tst_mul2k(synch_mpz_manager & m, mpz const & v, unsigned k) { m.power(two, k, pw); m.mul(v, pw, y); bool is_eq = m.eq(x, y); + (void)is_eq; CTRACE("mpz_2k", !is_eq, tout << "mul: " << m.to_string(v) << ", k: " << k << " r: " << m.to_string(x) << ", expected: " << m.to_string(y) << "\n";); - SASSERT(is_eq); + ENSURE(is_eq); m.del(x); m.del(y); m.del(pw); @@ -284,7 +286,7 @@ void tst_int_min_bug() { m.set(expected, "18446744075857035263"); m.sub(big, intmin, r); std::cout << "r: " << m.to_string(r) << "\nexpected: " << m.to_string(expected) << "\n"; - SASSERT(m.eq(r, expected)); + ENSURE(m.eq(r, expected)); m.del(intmin); m.del(big); m.del(expected); @@ -394,9 +396,9 @@ void tst_log2(unsynch_mpz_manager & m, mpz const & a) { scoped_mpz b(m); unsigned k = m.log2(a); m.power(mpz(2), k, b); - SASSERT(m.is_zero(a) || m.le(b, a)); + ENSURE(m.is_zero(a) || m.le(b, a)); m.power(mpz(2), k+1, b); - SASSERT(m.le(a, b)); + ENSURE(m.le(a, b)); scoped_mpz neg_a(m); m.set(neg_a, a); @@ -404,10 +406,10 @@ void tst_log2(unsynch_mpz_manager & m, mpz const & a) { k = m.mlog2(neg_a); m.power(mpz(2), k, b); m.neg(b); - SASSERT(m.is_zero(neg_a) || m.le(neg_a, b)); + ENSURE(m.is_zero(neg_a) || m.le(neg_a, b)); m.power(mpz(2), k+1, b); m.neg(b); - SASSERT(m.le(b, neg_a)); + ENSURE(m.le(b, neg_a)); } void tst_log2() { @@ -430,20 +432,20 @@ void tst_root() { m.set(a, 213); VERIFY(!m.root(a, 5)); std::cout << "213^{1/5}: " << a << "\n"; - SASSERT(m.eq(a, mpz(3))); + ENSURE(m.eq(a, mpz(3))); m.set(a, -213); VERIFY(!m.root(a, 5)); std::cout << "-213^{1/5}: " << a << "\n"; - SASSERT(m.eq(a, mpz(-2))); + ENSURE(m.eq(a, mpz(-2))); m.set(a, 0); VERIFY(m.root(a, 3)); - SASSERT(m.is_zero(a)); + ENSURE(m.is_zero(a)); m.set(a, 8); VERIFY(m.root(a, 3)); - SASSERT(m.eq(a, mpz(2))); + ENSURE(m.eq(a, mpz(2))); m.set(a, -8); VERIFY(m.root(a, 3)); - SASSERT(m.eq(a, mpz(-2))); + ENSURE(m.eq(a, mpz(-2))); } void tst_gcd_bug() { diff --git a/src/test/nlsat.cpp b/src/test/nlsat.cpp index 27a0aa1da..ccb534214 100644 --- a/src/test/nlsat.cpp +++ b/src/test/nlsat.cpp @@ -35,25 +35,25 @@ nlsat::interval_set_ref tst_interval(nlsat::interval_set_ref const & s1, std::cout << "s2: " << s2 << "\n"; r = ism.mk_union(s1, s2); std::cout << "union(s1, s2): " << r << std::endl; - SASSERT(!check_num_intervals || ism.num_intervals(r) == expected_num_intervals); - SASSERT(ism.subset(s1, r)); - SASSERT(ism.subset(s2, r)); + ENSURE(!check_num_intervals || ism.num_intervals(r) == expected_num_intervals); + ENSURE(ism.subset(s1, r)); + ENSURE(ism.subset(s2, r)); if (ism.set_eq(s1, s2)) { - SASSERT(ism.set_eq(s1, r)); - SASSERT(ism.set_eq(s2, r)); + ENSURE(ism.set_eq(s1, r)); + ENSURE(ism.set_eq(s2, r)); } else { - SASSERT(ism.subset(s1, s2) || !ism.subset(r, s2)); - SASSERT(ism.subset(s2, s1) || !ism.subset(r, s1)); + ENSURE(ism.subset(s1, s2) || !ism.subset(r, s2)); + ENSURE(ism.subset(s2, s1) || !ism.subset(r, s1)); } nlsat::interval_set_ref r2(ism); r2 = ism.mk_union(s2, s1); - SASSERT(ism.set_eq(r, r2)); + ENSURE(ism.set_eq(r, r2)); anum zero; nlsat::interval_set_ref full(ism); nlsat::literal dummy(131, false); full = ism.mk(true, true, zero, true, true, zero, dummy); - SASSERT(ism.set_eq(r, full) == ism.is_full(r)); + ENSURE(ism.set_eq(r, full) == ism.is_full(r)); return r; } @@ -178,8 +178,8 @@ static void tst3() { static nlsat::interval_set_ref mk_random(nlsat::interval_set_manager & ism, anum_manager & am, int range, int space, int tries, bool minus_inf, bool plus_inf, nlsat::literal lit) { static random_gen gen; - SASSERT(range > 0); - SASSERT(space > 0); + ENSURE(range > 0); + ENSURE(space > 0); nlsat::interval_set_ref r(ism), curr(ism); scoped_anum lower(am); scoped_anum upper(am); @@ -227,17 +227,17 @@ static void check_subset_result(nlsat::interval_set_ref const & s1, unsigned num = ism.num_intervals(r); nlsat::literal_vector lits; ism.get_justifications(r, lits); - SASSERT(lits.size() <= 2); + ENSURE(lits.size() <= 2); for (unsigned i = 0; i < num; i++) { tmp = ism.get_interval(r, i); ism.get_justifications(tmp, lits); - SASSERT(lits.size() == 1); + ENSURE(lits.size() == 1); if (lits[0] == l1) { - SASSERT(ism.subset(tmp, s1)); + ENSURE(ism.subset(tmp, s1)); } else { - SASSERT(lits[0] == l2); - SASSERT(ism.subset(tmp, s2)); + ENSURE(lits[0] == l2); + ENSURE(ism.subset(tmp, s2)); } } } @@ -293,7 +293,7 @@ static void tst5() { bool is_even[1] = { false }; nlsat::bool_var b = s.mk_ineq_atom(nlsat::atom::GT, 1, _p, is_even); nlsat::atom * a = s.bool_var2atom(b); - SASSERT(a != 0); + ENSURE(a != 0); scoped_anum zero(am); am.set(zero, 0); as.set(0, zero); @@ -391,7 +391,6 @@ static void tst7() { params_ref ps; reslimit rlim; nlsat::solver s(rlim, ps); - anum_manager & am = s.am(); nlsat::pmanager & pm = s.pm(); nlsat::var x0, x1, x2, a, b, c, d; a = s.mk_var(false); @@ -423,7 +422,7 @@ static void tst7() { nlsat::literal_vector litsv(lits.size(), lits.c_ptr()); lbool res = s.check(litsv); - SASSERT(res == l_false); + VERIFY(res == l_false); for (unsigned i = 0; i < litsv.size(); ++i) { s.display(std::cout, litsv[i]); std::cout << " "; @@ -433,7 +432,7 @@ static void tst7() { litsv.reset(); litsv.append(2, lits.c_ptr()); res = s.check(litsv); - SASSERT(res == l_true); + ENSURE(res == l_true); s.display(std::cout); s.am().display(std::cout, s.value(x0)); std::cout << "\n"; s.am().display(std::cout, s.value(x1)); std::cout << "\n"; diff --git a/src/test/no_overflow.cpp b/src/test/no_overflow.cpp index d795bc1fd..c528b0dbe 100644 --- a/src/test/no_overflow.cpp +++ b/src/test/no_overflow.cpp @@ -28,12 +28,12 @@ Revision History: { \ Z3_solver_push(ctx, s); \ Z3_solver_assert(ctx, s, TEST_NAME); \ - SASSERT(Z3_solver_check(ctx, s) == TEST_OUTCOME); \ + ENSURE(Z3_solver_check(ctx, s) == TEST_OUTCOME); \ Z3_solver_pop(ctx, s, 1); \ \ Z3_solver_push(ctx, s); \ Z3_solver_assert(ctx, s, Z3_mk_not(ctx, TEST_NAME)); \ - SASSERT(Z3_solver_check(ctx, s) == NEG_TEST_OUTCOME); \ + ENSURE(Z3_solver_check(ctx, s) == NEG_TEST_OUTCOME); \ Z3_solver_pop(ctx, s, 1); \ } \ } while (0) @@ -630,7 +630,7 @@ void test_equiv(Equivalence_params params, unsigned bvsize, bool is_signed) { equiv = Z3_mk_implies(ctx, cond, equiv); } Z3_solver_assert(ctx, s, Z3_mk_not(ctx, equiv)); - SASSERT(Z3_solver_check(ctx, s) == Z3_L_FALSE); + ENSURE(Z3_solver_check(ctx, s) == Z3_L_FALSE); Z3_solver_pop(ctx, s, 1); Z3_solver_dec_ref(ctx, s); @@ -662,7 +662,7 @@ void test_equiv(Equivalence_params params, unsigned bvsize, bool is_signed) { // Z3_solver_assert(ctx, s, Z3_mk_eq(ctx, t2, Z3_mk_numeral(ctx, "1", bv))); // //TEST_NO_UNDERFLOW; // Z3_solver_assert(ctx, s, test_udfl); -// SASSERT(Z3_check(ctx) == Z3_TRUE); +// ENSURE(Z3_check(ctx) == Z3_TRUE); // Z3_solver_pop(ctx, s, 1); // // Z3_del_config(cfg); diff --git a/src/test/object_allocator.cpp b/src/test/object_allocator.cpp index 16b9331e2..3ea646c0c 100644 --- a/src/test/object_allocator.cpp +++ b/src/test/object_allocator.cpp @@ -61,12 +61,13 @@ static void tst1() { m.recycle(c1); cell * c3 = m.allocate(); - SASSERT(c3->m_coeff.is_zero()); + (void)c3; + ENSURE(c3->m_coeff.is_zero()); } static void tst2() { cell_allocator m; - SASSERT(m.capacity() >= 2); + ENSURE(m.capacity() >= 2); cell_allocator::worker_object_allocator m1 = m.get_worker_allocator(0); cell_allocator::worker_object_allocator m2 = m.get_worker_allocator(1); m.enable_concurrent(true); @@ -82,7 +83,7 @@ static void tst2() { c = m1.allocate(); else c = m2.allocate(); - SASSERT(c->m_coeff.is_zero()); + ENSURE(c->m_coeff.is_zero()); int val = rand(); c->m_coeff = rational(val); object_coeff_pairs.push_back(std::make_pair(c, val)); @@ -92,7 +93,7 @@ static void tst2() { unsigned idx = rand() % object_coeff_pairs.size(); cell * c = object_coeff_pairs[idx].first; CTRACE("object_allocator", c->m_coeff != rational(object_coeff_pairs[idx].second), tout << c->m_coeff << " != " << rational(object_coeff_pairs[idx].second) << "\n";); - SASSERT(c->m_coeff == rational(object_coeff_pairs[idx].second)); + ENSURE(c->m_coeff == rational(object_coeff_pairs[idx].second)); if (idx < 5) m1.recycle(c); else @@ -117,5 +118,5 @@ void tst_object_allocator() { tst2(); TRACE("object_allocator", tout << "num. allocated cells: " << cell::g_num_allocated_cells << "\nnum. deallocated cells: " << cell::g_num_deallocated_cells << "\nnum. recycled cells: " << cell::g_num_recycled_cells << "\n";); - SASSERT(cell::g_num_allocated_cells == cell::g_num_deallocated_cells); + ENSURE(cell::g_num_allocated_cells == cell::g_num_deallocated_cells); } diff --git a/src/test/old_interval.cpp b/src/test/old_interval.cpp index 92064c03e..da41d0d38 100644 --- a/src/test/old_interval.cpp +++ b/src/test/old_interval.cpp @@ -23,96 +23,96 @@ static void tst1() { ext_numeral minus_inf(false); ext_numeral zero(0); - SASSERT(ext_numeral(10) + ext_numeral(3) == ext_numeral(13)); - SASSERT(inf + zero == inf); - SASSERT(minus_inf + zero == minus_inf); - SASSERT(minus_inf + ext_numeral(3) == minus_inf); - SASSERT(inf + inf == inf); - SASSERT(minus_inf + minus_inf == minus_inf); - SASSERT(minus_inf + ext_numeral(10) == minus_inf); - SASSERT(minus_inf + ext_numeral(-10) == minus_inf); - SASSERT(inf + ext_numeral(10) == inf); - SASSERT(inf + ext_numeral(-10) == inf); + ENSURE(ext_numeral(10) + ext_numeral(3) == ext_numeral(13)); + ENSURE(inf + zero == inf); + ENSURE(minus_inf + zero == minus_inf); + ENSURE(minus_inf + ext_numeral(3) == minus_inf); + ENSURE(inf + inf == inf); + ENSURE(minus_inf + minus_inf == minus_inf); + ENSURE(minus_inf + ext_numeral(10) == minus_inf); + ENSURE(minus_inf + ext_numeral(-10) == minus_inf); + ENSURE(inf + ext_numeral(10) == inf); + ENSURE(inf + ext_numeral(-10) == inf); - SASSERT(ext_numeral(10) - ext_numeral(3) == ext_numeral(7)); - SASSERT(inf - zero == inf); - SASSERT(minus_inf - zero == minus_inf); - SASSERT(minus_inf - ext_numeral(3) == minus_inf); - SASSERT(inf - minus_inf == inf); - SASSERT(minus_inf - inf == minus_inf); - SASSERT(zero - minus_inf == inf); - SASSERT(zero - inf == minus_inf); - SASSERT(ext_numeral(-10) - minus_inf == inf); - SASSERT(ext_numeral(10) - minus_inf == inf); - SASSERT(ext_numeral(-10) - inf == minus_inf); - SASSERT(ext_numeral(10) - inf == minus_inf); + ENSURE(ext_numeral(10) - ext_numeral(3) == ext_numeral(7)); + ENSURE(inf - zero == inf); + ENSURE(minus_inf - zero == minus_inf); + ENSURE(minus_inf - ext_numeral(3) == minus_inf); + ENSURE(inf - minus_inf == inf); + ENSURE(minus_inf - inf == minus_inf); + ENSURE(zero - minus_inf == inf); + ENSURE(zero - inf == minus_inf); + ENSURE(ext_numeral(-10) - minus_inf == inf); + ENSURE(ext_numeral(10) - minus_inf == inf); + ENSURE(ext_numeral(-10) - inf == minus_inf); + ENSURE(ext_numeral(10) - inf == minus_inf); - SASSERT(ext_numeral(10) * inf == inf); - SASSERT(ext_numeral(-10) * inf == minus_inf); - SASSERT(zero * inf == zero); - SASSERT(zero * minus_inf == zero); - SASSERT(zero * ext_numeral(10) == zero); - SASSERT(ext_numeral(10) * ext_numeral(-20) == ext_numeral(-200)); - SASSERT(ext_numeral(3) * ext_numeral(2) == ext_numeral(6)); - SASSERT(inf * inf == inf); - SASSERT(inf * minus_inf == minus_inf); - SASSERT(minus_inf * minus_inf == inf); - SASSERT(minus_inf * inf == minus_inf); - SASSERT(minus_inf * ext_numeral(10) == minus_inf); - SASSERT(minus_inf * ext_numeral(-10) == inf); + ENSURE(ext_numeral(10) * inf == inf); + ENSURE(ext_numeral(-10) * inf == minus_inf); + ENSURE(zero * inf == zero); + ENSURE(zero * minus_inf == zero); + ENSURE(zero * ext_numeral(10) == zero); + ENSURE(ext_numeral(10) * ext_numeral(-20) == ext_numeral(-200)); + ENSURE(ext_numeral(3) * ext_numeral(2) == ext_numeral(6)); + ENSURE(inf * inf == inf); + ENSURE(inf * minus_inf == minus_inf); + ENSURE(minus_inf * minus_inf == inf); + ENSURE(minus_inf * inf == minus_inf); + ENSURE(minus_inf * ext_numeral(10) == minus_inf); + ENSURE(minus_inf * ext_numeral(-10) == inf); - SASSERT(minus_inf < inf); - SASSERT(!(inf < minus_inf)); - SASSERT(minus_inf < ext_numeral(10)); - SASSERT(ext_numeral(-3) < inf); - SASSERT(ext_numeral(-10) < ext_numeral(4)); - SASSERT(ext_numeral(2) < ext_numeral(10)); - SASSERT(!(inf < ext_numeral(30))); - SASSERT(!(ext_numeral(10) < minus_inf)); - SASSERT(!(inf < inf)); - SASSERT(!(minus_inf < minus_inf)); - SASSERT(!(zero < zero)); - SASSERT(!(ext_numeral(10) < ext_numeral(10))); - SASSERT(inf > minus_inf); - SASSERT(inf > zero); - SASSERT(inf > ext_numeral(10)); - SASSERT(ext_numeral(10) > minus_inf); - SASSERT(zero > minus_inf); - SASSERT(!(zero > inf)); - SASSERT(!(minus_inf > inf)); - SASSERT(inf >= minus_inf); - SASSERT(inf >= inf); - SASSERT(minus_inf >= minus_inf); - SASSERT(inf >= zero); - SASSERT(zero >= minus_inf); - SASSERT(inf <= inf); - SASSERT(minus_inf <= minus_inf); - SASSERT(zero <= inf); - SASSERT(minus_inf <= zero); + ENSURE(minus_inf < inf); + ENSURE(!(inf < minus_inf)); + ENSURE(minus_inf < ext_numeral(10)); + ENSURE(ext_numeral(-3) < inf); + ENSURE(ext_numeral(-10) < ext_numeral(4)); + ENSURE(ext_numeral(2) < ext_numeral(10)); + ENSURE(!(inf < ext_numeral(30))); + ENSURE(!(ext_numeral(10) < minus_inf)); + ENSURE(!(inf < inf)); + ENSURE(!(minus_inf < minus_inf)); + ENSURE(!(zero < zero)); + ENSURE(!(ext_numeral(10) < ext_numeral(10))); + ENSURE(inf > minus_inf); + ENSURE(inf > zero); + ENSURE(inf > ext_numeral(10)); + ENSURE(ext_numeral(10) > minus_inf); + ENSURE(zero > minus_inf); + ENSURE(!(zero > inf)); + ENSURE(!(minus_inf > inf)); + ENSURE(inf >= minus_inf); + ENSURE(inf >= inf); + ENSURE(minus_inf >= minus_inf); + ENSURE(inf >= zero); + ENSURE(zero >= minus_inf); + ENSURE(inf <= inf); + ENSURE(minus_inf <= minus_inf); + ENSURE(zero <= inf); + ENSURE(minus_inf <= zero); ext_numeral val(10); val.neg(); - SASSERT(val == ext_numeral(-10)); + ENSURE(val == ext_numeral(-10)); val = inf; val.neg(); - SASSERT(val == minus_inf); + ENSURE(val == minus_inf); val.neg(); - SASSERT(val == inf); + ENSURE(val == inf); - SASSERT(minus_inf.sign()); - SASSERT(!zero.sign()); - SASSERT(!inf.sign()); - SASSERT(ext_numeral(-10).sign()); - SASSERT(!ext_numeral(10).sign()); + ENSURE(minus_inf.sign()); + ENSURE(!zero.sign()); + ENSURE(!inf.sign()); + ENSURE(ext_numeral(-10).sign()); + ENSURE(!ext_numeral(10).sign()); - SASSERT(inf.is_infinite()); - SASSERT(minus_inf.is_infinite()); - SASSERT(!zero.is_infinite()); - SASSERT(!ext_numeral(10).is_infinite()); - SASSERT(!inf.is_zero()); - SASSERT(!minus_inf.is_zero()); - SASSERT(zero.is_zero()); - SASSERT(!ext_numeral(10).is_zero()); + ENSURE(inf.is_infinite()); + ENSURE(minus_inf.is_infinite()); + ENSURE(!zero.is_infinite()); + ENSURE(!ext_numeral(10).is_infinite()); + ENSURE(!inf.is_zero()); + ENSURE(!minus_inf.is_zero()); + ENSURE(zero.is_zero()); + ENSURE(!ext_numeral(10).is_zero()); } class interval_tester { @@ -120,9 +120,9 @@ class interval_tester { interval singleton(int i) { return interval(m, rational(i)); } interval all() { return interval(m); } - interval l(int i, bool o = false, int idx = 0) { return interval(m, rational(i), o, true, idx == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx))); } - interval r(int i, bool o = false, int idx = 0) { return interval(m, rational(i), o, false, idx == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx))); } - interval b(int l, int u, bool lo = false, bool uo = false, int idx_l = 0, int idx_u = 0) { + interval l(int i, bool o = false, size_t idx = 0) { return interval(m, rational(i), o, true, idx == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx))); } + interval r(int i, bool o = false, size_t idx = 0) { return interval(m, rational(i), o, false, idx == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx))); } + interval b(int l, int u, bool lo = false, bool uo = false, size_t idx_l = 0, size_t idx_u = 0) { return interval(m, rational(l), lo, idx_l == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx_l)), rational(u), uo, idx_u == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx_u))); } @@ -182,12 +182,12 @@ static void tst2() { m.set(y, mpz(-2), mpz(3)); m.add(x, y, z); std::cout << "x: " << x << ", y: " << y << ", z: " << z << "\n"; - SASSERT(nm.eq(z.lower(), mpz(-1))); - SASSERT(nm.eq(z.upper(), mpz(5))); + ENSURE(nm.eq(z.lower(), mpz(-1))); + ENSURE(nm.eq(z.upper(), mpz(5))); m.mul(x, y, z); std::cout << "x: " << x << ", y: " << y << ", z: " << z << "\n"; - SASSERT(nm.eq(z.lower(), mpz(-4))); - SASSERT(nm.eq(z.upper(), mpz(6))); + ENSURE(nm.eq(z.lower(), mpz(-4))); + ENSURE(nm.eq(z.upper(), mpz(6))); } void tst_old_interval() { diff --git a/src/test/optional.cpp b/src/test/optional.cpp index 81b84cd59..40ca383a5 100644 --- a/src/test/optional.cpp +++ b/src/test/optional.cpp @@ -22,11 +22,11 @@ Revision History: static void tst1() { optional v; - SASSERT(!v); - SASSERT(v == false); + ENSURE(!v); + ENSURE(v == false); v = 10; - SASSERT(v); - SASSERT(*v == 10); + ENSURE(v); + ENSURE(*v == 10); TRACE("optional", tout << sizeof(v) << "\n";); } @@ -45,25 +45,25 @@ struct OptFoo { static void tst2() { optional v; - SASSERT(!v); + ENSURE(!v); v = OptFoo(10, 20); - SASSERT(v->m_x == 10); - SASSERT(v->m_y == 20); + ENSURE(v->m_x == 10); + ENSURE(v->m_y == 20); v = OptFoo(200, 300); - SASSERT(v->m_x == 200); - SASSERT(v->m_y == 300); + ENSURE(v->m_x == 200); + ENSURE(v->m_y == 300); TRACE("optional", tout << sizeof(v) << "\n";); } static void tst3() { optional v; - SASSERT(!v); + ENSURE(!v); int x = 10; v = &x; - SASSERT(v); - SASSERT(*v == &x); + ENSURE(v); + ENSURE(*v == &x); TRACE("optional", tout << sizeof(v) << "\n";); - SASSERT(*(*v) == 10); + ENSURE(*(*v) == 10); } void tst_optional() { diff --git a/src/test/parray.cpp b/src/test/parray.cpp index 7976971d8..df0fde516 100644 --- a/src/test/parray.cpp +++ b/src/test/parray.cpp @@ -46,36 +46,36 @@ static void tst1() { int_array a3; m.mk(a1); - SASSERT(m.size(a1) == 0); + ENSURE(m.size(a1) == 0); m.push_back(a1, 10, a2); TRACE("parray", m.display_info(tout, a1); tout << "\n"; m.display_info(tout, a2); tout << "\n";); - SASSERT(m.size(a1) == 0); - SASSERT(m.size(a2) == 1); + ENSURE(m.size(a1) == 0); + ENSURE(m.size(a2) == 1); m.push_back(a1, 20, a1); m.push_back(a1, 30, a1); TRACE("parray", m.display_info(tout, a1); tout << "\n"; m.display_info(tout, a2); tout << "\n";); - SASSERT(m.get(a1, 0) == 20); - SASSERT(m.get(a1, 1) == 30); - SASSERT(m.get(a2, 0) == 10); - SASSERT(m.size(a1) == 2); - SASSERT(m.size(a2) == 1); - SASSERT(m.size(a3) == 0); + ENSURE(m.get(a1, 0) == 20); + ENSURE(m.get(a1, 1) == 30); + ENSURE(m.get(a2, 0) == 10); + ENSURE(m.size(a1) == 2); + ENSURE(m.size(a2) == 1); + ENSURE(m.size(a3) == 0); m.push_back(a2, 100, a3); - SASSERT(m.size(a3) == 2); - SASSERT(m.get(a3, 0) == 10); - SASSERT(m.get(a3, 1) == 100); + ENSURE(m.size(a3) == 2); + ENSURE(m.get(a3, 0) == 10); + ENSURE(m.get(a3, 1) == 100); TRACE("parray", m.display_info(tout, a1); tout << "\n"; m.display_info(tout, a2); tout << "\n"; m.display_info(tout, a3); tout << "\n";); m.push_back(a2, 50); - SASSERT(m.get(a2, 0) == 10); - SASSERT(m.get(a2, 1) == 50); - SASSERT(m.size(a2) == 2); + ENSURE(m.get(a2, 0) == 10); + ENSURE(m.get(a2, 1) == 50); + ENSURE(m.size(a2) == 2); TRACE("parray", m.display_info(tout, a1); tout << "\n"; m.display_info(tout, a2); tout << "\n"; @@ -100,22 +100,22 @@ static void tst2() { for (unsigned i = 0; i < 100; i++) m.push_back(a1, i); - SASSERT(m.size(a1) == 100); + ENSURE(m.size(a1) == 100); m.push_back(a1, 100, a2); for (unsigned i = 0; i < 10; i++) m.push_back(a2, i+101); TRACE("parray", m.display_info(tout, a1); tout << "\n"; m.display_info(tout, a2); tout << "\n";); - SASSERT(m.get(a1, 0) == 0); + ENSURE(m.get(a1, 0) == 0); TRACE("parray", m.display_info(tout, a1); tout << "\n"; m.display_info(tout, a2); tout << "\n";); for (unsigned i = 0; i < m.size(a1); i++) { - SASSERT(static_cast(m.get(a1, i)) == i); + ENSURE(static_cast(m.get(a1, i)) == i); } for (unsigned i = 0; i < m.size(a2); i++) { - SASSERT(static_cast(m.get(a2, i)) == i); + ENSURE(static_cast(m.get(a2, i)) == i); } TRACE("parray", m.display_info(tout, a1); tout << "\n"; @@ -145,7 +145,7 @@ static void tst3() { for (unsigned i = 0; i < 20; i++) m.push_back(a1, i); - SASSERT(m.size(a1) == 20); + ENSURE(m.size(a1) == 20); m.set(a1, 0, 1, a2); for (unsigned i = 1; i < 20; i++) { if (i == 6) { @@ -161,7 +161,7 @@ static void tst3() { m.push_back(a4, 30); for (unsigned i = 0; i < 20; i++) { - SASSERT(static_cast(m.get(a2, i)) == i+1); + ENSURE(static_cast(m.get(a2, i)) == i+1); } TRACE("parray", m.display_info(tout, a1); tout << "\n"; @@ -169,7 +169,7 @@ static void tst3() { m.display_info(tout, a3); tout << "\n"; m.display_info(tout, a4); tout << "\n"; ); - SASSERT(m.get(a1, 10) == 10); + ENSURE(m.get(a1, 10) == 10); TRACE("parray", tout << "after rerooting...\n"; m.display_info(tout, a1); tout << "\n"; @@ -177,19 +177,19 @@ static void tst3() { m.display_info(tout, a3); tout << "\n"; m.display_info(tout, a4); tout << "\n"; ); - SASSERT(m.size(a1) == 20); - SASSERT(m.size(a2) == 20); - SASSERT(m.size(a3) == 19); - SASSERT(m.size(a4) == 19); + ENSURE(m.size(a1) == 20); + ENSURE(m.size(a2) == 20); + ENSURE(m.size(a3) == 19); + ENSURE(m.size(a4) == 19); for (unsigned i = 0; i < 20; i++) { - SASSERT(static_cast(m.get(a1, i)) == i); - SASSERT(static_cast(m.get(a2, i)) == i+1); - SASSERT(i >= 18 || static_cast(m.get(a4, i)) == i+1); - SASSERT(i >= 6 || static_cast(m.get(a3, i)) == i+1); - SASSERT(!(6 <= i && i <= 17) || static_cast(m.get(a3, i)) == i); + ENSURE(static_cast(m.get(a1, i)) == i); + ENSURE(static_cast(m.get(a2, i)) == i+1); + ENSURE(i >= 18 || static_cast(m.get(a4, i)) == i+1); + ENSURE(i >= 6 || static_cast(m.get(a3, i)) == i+1); + ENSURE(!(6 <= i && i <= 17) || static_cast(m.get(a3, i)) == i); } - SASSERT(m.get(a4, 18) == 30); - SASSERT(m.get(a3, 18) == 40); + ENSURE(m.get(a4, 18) == 30); + ENSURE(m.get(a3, 18) == 40); TRACE("parray", tout << "after many gets...\n"; m.display_info(tout, a1); tout << "\n"; diff --git a/src/test/pb2bv.cpp b/src/test/pb2bv.cpp index c114997c5..07cb047b3 100644 --- a/src/test/pb2bv.cpp +++ b/src/test/pb2bv.cpp @@ -81,12 +81,12 @@ static void test_semantics(ast_manager& m, expr_ref_vector const& vars, vectorcheck_sat(0,0); - SASSERT(res == l_true); + VERIFY(res == l_true); slv->assert_expr(m.is_true(result2) ? m.mk_not(result1) : result1.get()); res = slv->check_sat(0,0); - SASSERT(res == l_false); + VERIFY(res == l_false); } } diff --git a/src/test/permutation.cpp b/src/test/permutation.cpp index d5929b6c0..e0d208520 100644 --- a/src/test/permutation.cpp +++ b/src/test/permutation.cpp @@ -48,7 +48,7 @@ static void tst1(unsigned sz, unsigned num_tries, unsigned max = UINT_MAX) { apply_permutation(sz, data.c_ptr(), p.c_ptr()); // std::cout << "data: "; display(std::cout, data.begin(), data.end()); std::cout << "\n"; for (unsigned i = 0; i < 0; i++) - SASSERT(data[i] == new_data[i]); + ENSURE(data[i] == new_data[i]); } #endif } diff --git a/src/test/polynomial.cpp b/src/test/polynomial.cpp index 03eb321cd..0a6418a6c 100644 --- a/src/test/polynomial.cpp +++ b/src/test/polynomial.cpp @@ -39,7 +39,7 @@ static void tst1() { p = (x0^3) + x1*x0 + 2; std::cout << p << "\n"; std::cout << "max_var(p): " << max_var(p) << "\n"; - SASSERT(max_var(p) == 1); + ENSURE(max_var(p) == 1); std::cout << (2*x2 - x1*x0) << "\n"; std::cout << (p + (2*x2 - x1*x0)) << "\n"; std::cout << (p*p + 2*x2) << "\n"; @@ -79,7 +79,7 @@ static void tst_pseudo_div(polynomial_ref const & A, polynomial_ref const & B, p std::cout << "l_B^d: " << l_B_d << "\n"; std::cout << "Q * B + R: " << Q * B + R << "\n"; std::cout << "l_B_d * A: " << l_B_d * A << "\n"; - SASSERT(eq((Q * B + R), (l_B_d * A))); + ENSURE(eq((Q * B + R), (l_B_d * A))); } static void tst2() { @@ -329,13 +329,13 @@ static void tst11() { polynomial_ref d(m); d = exact_div(p, q); std::cout << "p: " << p << "\nq: " << q << "\nd: " << d << "\n"; - SASSERT(eq(q * d, p)); + ENSURE(eq(q * d, p)); q = ((x1^3) + x1 + 1)*((x2^2) + x2 + x2 + 1)*((x3^2) + 2); p = (x1 + (x3^2) + x3 + x2 + (x2^2) + 1)*((x1^3) + x1 + 1)*((x2^2) + x2 + x2 + 1)*((x3^2) + 2); d = exact_div(p, q); std::cout << "p: " << p << "\nq: " << q << "\nd: " << d << "\n"; - SASSERT(eq(q * d, p)); + ENSURE(eq(q * d, p)); } static void tst_discriminant(polynomial_ref const & p, polynomial::var x, polynomial_ref const & expected) { @@ -344,7 +344,7 @@ static void tst_discriminant(polynomial_ref const & p, polynomial::var x, polyno r = discriminant(p, x); std::cout << "r: " << r << "\n"; std::cout << "expected: " << expected << "\n"; - SASSERT(eq(r, expected)); + ENSURE(eq(r, expected)); m.lex_sort(r); std::cout << "r (sorted): " << r << "\n"; } @@ -463,7 +463,7 @@ static void tst_resultant(polynomial_ref const & p, polynomial_ref const & q, po std::cout << "expected: " << expected << "\n"; if (degree(p, x) > 0 && degree(q, x) > 0) std::cout << "quasi-resultant: " << quasi_resultant(p, q, x) << "\n"; - SASSERT(eq(r, expected)); + ENSURE(eq(r, expected)); m.lex_sort(r); std::cout << "r (sorted): " << r << "\n"; } @@ -570,8 +570,8 @@ static void tst_compose() { p = (x0^3) - x0 + 3; std::cout << "p: " << p << "\np(x - y): " << compose_x_minus_y(p, 1) << "\np(x + y): " << compose_x_plus_y(p, 1) << "\np(x - x): " << compose_x_minus_y(p, 0) << "\np(x + x): " << compose_x_plus_y(p, 0) << "\n"; - SASSERT(eq(compose_x_minus_y(p, 1), (x0^3) - 3*(x0^2)*x1 + 3*x0*(x1^2) - (x1^3) - x0 + x1 + 3)); - SASSERT(eq(compose_x_plus_y(p, 1), (x0^3) + 3*(x0^2)*x1 + 3*x0*(x1^2) + (x1^3) - x0 - x1 + 3)); + ENSURE(eq(compose_x_minus_y(p, 1), (x0^3) - 3*(x0^2)*x1 + 3*x0*(x1^2) - (x1^3) - x0 + x1 + 3)); + ENSURE(eq(compose_x_plus_y(p, 1), (x0^3) + 3*(x0^2)*x1 + 3*x0*(x1^2) + (x1^3) - x0 - x1 + 3)); } void tst_prem() { @@ -604,11 +604,11 @@ void tst_sqrt() { p = (4*x*y + 3*(x^2)*y + (y^2) + 3)^4; polynomial_ref q(m); VERIFY(sqrt(p, q)); - SASSERT(eq(p, q*q)); + ENSURE(eq(p, q*q)); std::cout << "p: " << p << "\n"; std::cout << "q: " << q << "\n"; p = p - 1; - SASSERT(!sqrt(p, q)); + ENSURE(!sqrt(p, q)); } static void tst_content(polynomial_ref const & p, polynomial::var x, polynomial_ref const & expected) { @@ -616,7 +616,7 @@ static void tst_content(polynomial_ref const & p, polynomial::var x, polynomial_ std::cout << "p: " << p << std::endl; std::cout << "content(p): " << content(p, x) << std::endl; std::cout << "expected: " << expected << std::endl; - SASSERT(eq(content(p, x), expected)); + ENSURE(eq(content(p, x), expected)); } static void tst_primitive(polynomial_ref const & p, polynomial::var x, polynomial_ref const & expected) { @@ -624,7 +624,7 @@ static void tst_primitive(polynomial_ref const & p, polynomial::var x, polynomia std::cout << "p: " << p << std::endl; std::cout << "primitive(p): " << primitive(p, x) << std::endl; std::cout << "expected: " << expected << std::endl; - SASSERT(eq(primitive(p, x), expected)); + ENSURE(eq(primitive(p, x), expected)); } static void tst_gcd(polynomial_ref const & p, polynomial_ref const & q, polynomial_ref const & expected) { @@ -635,7 +635,7 @@ static void tst_gcd(polynomial_ref const & p, polynomial_ref const & q, polynomi r = gcd(p, q); std::cout << "gcd(p, q): " << r << std::endl; std::cout << "expected: " << expected << std::endl; - SASSERT(eq(r, expected)); + ENSURE(eq(r, expected)); } static void tst_gcd() { @@ -711,15 +711,15 @@ static void tst_psc(polynomial_ref const & p, polynomial_ref const & q, polynomi std::cout << "S_" << i << ": " << polynomial_ref(S.get(i), m) << std::endl; } if (sz > 0) { - SASSERT(m.eq(S.get(0), first) || m.eq(S.get(0), neg(first))); + ENSURE(m.eq(S.get(0), first) || m.eq(S.get(0), neg(first))); } if (sz > 1) { - SASSERT(m.eq(S.get(1), second) || m.eq(S.get(1), neg(second))); + ENSURE(m.eq(S.get(1), second) || m.eq(S.get(1), neg(second))); } if (sz > 0) { polynomial_ref Res(m); Res = resultant(p, q, x); - SASSERT(m.eq(Res, S.get(0)) || m.eq(S.get(0), neg(Res))); + ENSURE(m.eq(Res, S.get(0)) || m.eq(S.get(0), neg(Res))); } } @@ -843,11 +843,11 @@ static void tst_vars(polynomial_ref const & p, unsigned sz, polynomial::var * xs std::cout << r[i] << " "; } std::cout << std::endl; - SASSERT(r.size() == sz); + ENSURE(r.size() == sz); std::sort(r.begin(), r.end()); std::sort(xs, xs + sz); for (unsigned i = 0; i < r.size(); i++) { - SASSERT(r[i] == xs[i]); + ENSURE(r[i] == xs[i]); } } @@ -886,9 +886,9 @@ static void tst_sqf(polynomial_ref const & p, polynomial_ref const & expected) { r = square_free(p); std::cout << "sqf(p): " << r << std::endl; std::cout << "expected: " << expected << std::endl; - SASSERT(is_square_free(r)); - SASSERT(!eq(r, p) || is_square_free(p)); - SASSERT(eq(expected, r)); + ENSURE(is_square_free(r)); + ENSURE(!eq(r, p) || is_square_free(p)); + ENSURE(eq(expected, r)); } static void tst_sqf() { @@ -931,7 +931,7 @@ static void tst_substitute(polynomial_ref const & p, r = p.m().substitute(p, 2, xs, vs.c_ptr()); std::cout << "r: " << r << std::endl; std::cout << "expected: " << expected << std::endl; - SASSERT(eq(r, expected)); + ENSURE(eq(r, expected)); p.m().lex_sort(r); std::cout << "r (sorted): " << r << std::endl; } @@ -972,7 +972,7 @@ static void tst_qsubstitute(polynomial_ref const & p, r = p.m().substitute(p, 2, xs, vs.c_ptr()); std::cout << "r: " << r << std::endl; std::cout << "expected (modulo a constant): " << expected << std::endl; - SASSERT(eq(r, normalize(expected))); + ENSURE(eq(r, normalize(expected))); p.m().lex_sort(r); std::cout << "r (sorted): " << r << std::endl; } @@ -1024,10 +1024,10 @@ void tst_mfact(polynomial_ref const & p, unsigned num_distinct_factors) { for (unsigned i = 0; i < fs.distinct_factors(); i++) { std::cout << "*(" << fs[i] << ")^" << fs.get_degree(i) << std::endl; } - SASSERT(fs.distinct_factors() == num_distinct_factors); + ENSURE(fs.distinct_factors() == num_distinct_factors); polynomial_ref p2(p.m()); fs.multiply(p2); - SASSERT(eq(p, p2)); + ENSURE(eq(p, p2)); } static void tst_mfact() { @@ -1247,7 +1247,7 @@ static void tst_translate(polynomial_ref const & p, polynomial::var x0, int v0, polynomial_ref r(p.m()); p.m().translate(p, 3, xs, vs, r); std::cout << "r: " << r << std::endl; - SASSERT(eq(expected, r)); + ENSURE(eq(expected, r)); } static void tst_translate() { @@ -1326,11 +1326,11 @@ static void tst_mm() { std::cout << "p1: " << p1 << "\n"; p2 = convert(pm1, p1, pm2); std::cout << "p2: " << p2 << "\n"; - SASSERT(pm1.get_monomial(p1, 0) == pm2.get_monomial(p2, 0)); + ENSURE(pm1.get_monomial(p1, 0) == pm2.get_monomial(p2, 0)); polynomial_ref p3(pm3); p3 = convert(pm1, p1, pm3); - SASSERT(pm1.get_monomial(p1, 0) != pm3.get_monomial(p3, 0)); + ENSURE(pm1.get_monomial(p1, 0) != pm3.get_monomial(p3, 0)); } dealloc(pm1_ptr); // p2 is still ok @@ -1351,7 +1351,7 @@ static void tst_eval(polynomial_ref const & p, polynomial::var x0, rational v0, std::cout << "r: " << r << "\nexpected: " << expected << "\n"; scoped_mpq ex(qm); qm.set(ex, expected.to_mpq()); - SASSERT(qm.eq(r, ex)); + ENSURE(qm.eq(r, ex)); } static void tst_eval() { @@ -1407,18 +1407,18 @@ static void tst_mk_unique() { std::cout << "p: " << p << "\n"; std::cout << "q: " << q << "\n"; std::cout << "r: " << r << "\n"; - SASSERT(m.eq(p, q)); - SASSERT(!m.eq(p, r)); - SASSERT(p.get() != q.get()); + ENSURE(m.eq(p, q)); + ENSURE(!m.eq(p, r)); + ENSURE(p.get() != q.get()); q = uniq.mk_unique(q); p = uniq.mk_unique(p); r = uniq.mk_unique(r); std::cout << "after mk_unique\np: " << p << "\n"; std::cout << "q: " << q << "\n"; std::cout << "r: " << r << "\n"; - SASSERT(m.eq(p, q)); - SASSERT(!m.eq(r, q)); - SASSERT(p.get() == q.get()); + ENSURE(m.eq(p, q)); + ENSURE(!m.eq(r, q)); + ENSURE(p.get() == q.get()); } struct dummy_del_eh : public polynomial::manager::del_eh { @@ -1442,24 +1442,24 @@ static void tst_del_eh() { m.add_del_eh(&eh1); x1 = 0; - SASSERT(eh1.m_counter == 1); + ENSURE(eh1.m_counter == 1); m.add_del_eh(&eh2); x1 = m.mk_polynomial(m.mk_var()); x1 = 0; - SASSERT(eh1.m_counter == 2); - SASSERT(eh2.m_counter == 1); + ENSURE(eh1.m_counter == 2); + ENSURE(eh2.m_counter == 1); m.remove_del_eh(&eh1); x0 = 0; x1 = m.mk_polynomial(m.mk_var()); x1 = 0; - SASSERT(eh1.m_counter == 2); - SASSERT(eh2.m_counter == 3); + ENSURE(eh1.m_counter == 2); + ENSURE(eh2.m_counter == 3); m.remove_del_eh(&eh2); x1 = m.mk_polynomial(m.mk_var()); x1 = 0; - SASSERT(eh1.m_counter == 2); - SASSERT(eh2.m_counter == 3); + ENSURE(eh1.m_counter == 2); + ENSURE(eh2.m_counter == 3); } static void tst_const_coeff() { @@ -1475,36 +1475,36 @@ static void tst_const_coeff() { polynomial_ref p(m); p = (x0^2)*x1 + 3*x0 + x1; - SASSERT(!m.const_coeff(p, 0, 2, c)); - SASSERT(m.const_coeff(p, 0, 1, c) && c == 3); - SASSERT(!m.const_coeff(p, 0, 0, c)); + ENSURE(!m.const_coeff(p, 0, 2, c)); + ENSURE(m.const_coeff(p, 0, 1, c) && c == 3); + ENSURE(!m.const_coeff(p, 0, 0, c)); p = (x0^2)*x1 + 3*x0 + x1 + 1; - SASSERT(!m.const_coeff(p, 0, 2, c)); - SASSERT(m.const_coeff(p, 0, 1, c) && c == 3); - SASSERT(!m.const_coeff(p, 0, 0, c)); + ENSURE(!m.const_coeff(p, 0, 2, c)); + ENSURE(m.const_coeff(p, 0, 1, c) && c == 3); + ENSURE(!m.const_coeff(p, 0, 0, c)); p = (x0^2)*x1 + 3*x0 + 1; - SASSERT(!m.const_coeff(p, 0, 2, c)); - SASSERT(m.const_coeff(p, 0, 1, c) && c == 3); - SASSERT(m.const_coeff(p, 0, 0, c) && c == 1); + ENSURE(!m.const_coeff(p, 0, 2, c)); + ENSURE(m.const_coeff(p, 0, 1, c) && c == 3); + ENSURE(m.const_coeff(p, 0, 0, c) && c == 1); p = x1 + 3*x0 + 1; - SASSERT(m.const_coeff(p, 0, 2, c) && c == 0); - SASSERT(m.const_coeff(p, 0, 1, c) && c == 3); - SASSERT(!m.const_coeff(p, 0, 0, c)); + ENSURE(m.const_coeff(p, 0, 2, c) && c == 0); + ENSURE(m.const_coeff(p, 0, 1, c) && c == 3); + ENSURE(!m.const_coeff(p, 0, 0, c)); p = 5*(x0^2) + 3*x0 + 7; - SASSERT(m.const_coeff(p, 0, 5, c) && c == 0); - SASSERT(m.const_coeff(p, 0, 2, c) && c == 5); - SASSERT(m.const_coeff(p, 0, 1, c) && c == 3); - SASSERT(m.const_coeff(p, 0, 0, c) && c == 7); + ENSURE(m.const_coeff(p, 0, 5, c) && c == 0); + ENSURE(m.const_coeff(p, 0, 2, c) && c == 5); + ENSURE(m.const_coeff(p, 0, 1, c) && c == 3); + ENSURE(m.const_coeff(p, 0, 0, c) && c == 7); p = 5*(x0^2) + 3*x0; - SASSERT(m.const_coeff(p, 0, 0, c) && c == 0); + ENSURE(m.const_coeff(p, 0, 0, c) && c == 0); p = - x0*x1 - x1 + 1; - SASSERT(!m.const_coeff(p, 0, 1, c)); + ENSURE(!m.const_coeff(p, 0, 1, c)); } static void tst_gcd2() { @@ -1669,7 +1669,7 @@ static void tst_newton_interpolation() { m.newton_interpolation(0, 2, ins.c_ptr(), outs, r); } std::cout << "interpolation result: " << r << "\n"; - SASSERT(m.eq((x^2)*y + 5*x*y + 41*x - 9*y - 21, r)); + ENSURE(m.eq((x^2)*y + 5*x*y + 41*x - 9*y - 21, r)); } static void tst_slow_mod_gcd() { @@ -1732,9 +1732,9 @@ void tst_linear_solver() { solver.add(2, as.c_ptr(), b); VERIFY(solver.solve(xs.c_ptr())); - SASSERT(qm.eq(xs[0], mpq(2))); - SASSERT(qm.eq(xs[1], mpq(3))); - SASSERT(qm.eq(xs[2], mpq(-1))); + ENSURE(qm.eq(xs[0], mpq(2))); + ENSURE(qm.eq(xs[1], mpq(3))); + ENSURE(qm.eq(xs[2], mpq(-1))); } static void tst_lex(polynomial_ref const & p1, polynomial_ref const & p2, int lex_expected, polynomial::var min, int lex2_expected) { @@ -1746,11 +1746,11 @@ static void tst_lex(polynomial_ref const & p1, polynomial_ref const & p2, int le std::cout << " "; std::cout.flush(); int r1 = lex_compare(m.get_monomial(p1, 0), m.get_monomial(p2, 0)); int r2 = lex_compare2(m.get_monomial(p1, 0), m.get_monomial(p2, 0), min); - SASSERT(r1 == lex_expected); - SASSERT(r2 == lex2_expected); + ENSURE(r1 == lex_expected); + ENSURE(r2 == lex2_expected); std::cout << r1 << " " << r2 << "\n"; - SASSERT(lex_compare(m.get_monomial(p2, 0), m.get_monomial(p1, 0)) == -r1); - SASSERT(lex_compare2(m.get_monomial(p2, 0), m.get_monomial(p1, 0), min) == -r2); + ENSURE(lex_compare(m.get_monomial(p2, 0), m.get_monomial(p1, 0)) == -r1); + ENSURE(lex_compare2(m.get_monomial(p2, 0), m.get_monomial(p1, 0), min) == -r2); } static void tst_lex() { diff --git a/src/test/polynorm.cpp b/src/test/polynorm.cpp index a8f4ab861..03735fef9 100644 --- a/src/test/polynorm.cpp +++ b/src/test/polynorm.cpp @@ -25,7 +25,7 @@ static expr_ref parse_fml(ast_manager& m, char const* str) { << "(assert " << str << ")\n"; std::istringstream is(buffer.str()); VERIFY(parse_smt2_commands(ctx, is)); - SASSERT(ctx.begin_assertions() != ctx.end_assertions()); + ENSURE(ctx.begin_assertions() != ctx.end_assertions()); result = *ctx.begin_assertions(); return result; } @@ -88,6 +88,8 @@ private: expr_ref_vector& factors = poly.factors(); expr_ref_vector& coefficients = poly.coefficients(); expr_ref& coefficient = poly.coefficient(); + (void) coefficient; + (void) coefficients; m_rw(term); @@ -123,8 +125,8 @@ private: else if (m_arith.is_numeral(f, r)) { factors[i] = factors.back(); factors.pop_back(); - SASSERT(coefficient.is_zero()); - SASSERT(!r.is_zero()); + ENSURE(coefficient.is_zero()); + ENSURE(!r.is_zero()); coefficient = r; --i; // repeat examining 'i' } @@ -170,7 +172,7 @@ static expr_ref mk_mul(arith_util& arith, unsigned num_args, expr* const* args) static void nf(expr_ref& term) { ast_manager& m = term.get_manager(); - expr *e1, *e2; + expr *e1 = 0, *e2 = 0; th_rewriter rw(m); arith_util arith(m); @@ -203,8 +205,8 @@ static void nf(expr_ref& term) { else if (arith.is_numeral(f, r)) { factors[i] = factors.back(); factors.pop_back(); - SASSERT(coefficient.is_zero()); - SASSERT(!r.is_zero()); + ENSURE(coefficient.is_zero()); + ENSURE(!r.is_zero()); coefficient = r; --i; // repeat examining 'i' } diff --git a/src/test/prime_generator.cpp b/src/test/prime_generator.cpp index a2610b35e..5af014e0a 100644 --- a/src/test/prime_generator.cpp +++ b/src/test/prime_generator.cpp @@ -35,7 +35,7 @@ void tst_prime_generator() { m.root(sqrt_p, 2); uint64 k = m.get_uint64(sqrt_p); for (uint64 i = 2; i <= k; i++) { - SASSERT(p % i != 0); + ENSURE(p % i != 0); } } std::cout << std::endl; diff --git a/src/test/proof_checker.cpp b/src/test/proof_checker.cpp index 7f9827187..035326b26 100644 --- a/src/test/proof_checker.cpp +++ b/src/test/proof_checker.cpp @@ -11,7 +11,6 @@ void tst_checker1() { ast_manager m(PGM_FINE); expr_ref a(m); proof_ref p1(m), p2(m), p3(m), p4(m); - bool result; expr_ref_vector side_conditions(m); a = m.mk_const(symbol("a"), m.mk_bool_sort()); @@ -26,8 +25,7 @@ void tst_checker1() { proof_checker checker(m); p4 = m.mk_lemma(p3.get(), m.mk_or(a.get(), m.mk_not(a.get()))); ast_ll_pp(std::cout, m, p4.get()); - result = checker.check(p4.get(), side_conditions); - SASSERT(result); + VERIFY(checker.check(p4.get(), side_conditions)); } void tst_proof_checker() { diff --git a/src/test/qe_arith.cpp b/src/test/qe_arith.cpp index a73f7ed38..83b6e2620 100644 --- a/src/test/qe_arith.cpp +++ b/src/test/qe_arith.cpp @@ -37,7 +37,7 @@ static expr_ref parse_fml(ast_manager& m, char const* str) { << "(assert " << str << ")\n"; std::istringstream is(buffer.str()); VERIFY(parse_smt2_commands(ctx, is)); - SASSERT(ctx.begin_assertions() != ctx.end_assertions()); + ENSURE(ctx.begin_assertions() != ctx.end_assertions()); result = *ctx.begin_assertions(); return result; } @@ -163,7 +163,7 @@ static app_ref generate_ineqs(ast_manager& m, sort* s, vector& app* x = vars[0].get(); app* y = vars[1].get(); - app* z = vars[2].get(); + // app* z = vars[2].get(); // // ax <= by, ax < by, not (ax >= by), not (ax > by) // @@ -247,7 +247,7 @@ static void test2(char const *ex) { ctx.push(); ctx.assert_expr(fml); lbool result = ctx.check(); - SASSERT(result == l_true); + VERIFY(result == l_true); ref md; ctx.get_model(md); ctx.pop(1); diff --git a/src/test/quant_solve.cpp b/src/test/quant_solve.cpp index ed332ce26..2dc987d77 100644 --- a/src/test/quant_solve.cpp +++ b/src/test/quant_solve.cpp @@ -39,7 +39,7 @@ static void validate_quant_solution(ast_manager& m, expr* fml, expr* guard, qe:: smt::kernel solver(m, fp); solver.assert_expr(tmp); lbool res = solver.check(); - //SASSERT(res == l_false); + //ENSURE(res == l_false); if (res != l_false) { std::cout << "Validation failed: " << res << "\n"; std::cout << mk_pp(tmp, m) << "\n"; @@ -75,7 +75,7 @@ static void validate_quant_solutions(app* x, expr* fml, expr_ref_vector& guards) solver.assert_expr(tmp); lbool res = solver.check(); std::cout << "checked\n"; - SASSERT(res == l_false); + ENSURE(res == l_false); if (res != l_false) { std::cout << res << "\n"; fatal_error(0); @@ -131,7 +131,7 @@ static expr_ref parse_fml(ast_manager& m, char const* str) { << "(assert " << str << ")\n"; std::istringstream is(buffer.str()); VERIFY(parse_smt2_commands(ctx, is)); - SASSERT(ctx.begin_assertions() != ctx.end_assertions()); + ENSURE(ctx.begin_assertions() != ctx.end_assertions()); result = *ctx.begin_assertions(); return result; } diff --git a/src/test/rational.cpp b/src/test/rational.cpp index 834aab92f..6fa1005b0 100644 --- a/src/test/rational.cpp +++ b/src/test/rational.cpp @@ -27,85 +27,85 @@ static void tst1() { rational r1(1); rational r2(1,2); rational r3(2,4); - SASSERT(r2 == r3); - SASSERT(r1 != r2); - SASSERT(r2 + r3 == r1); - SASSERT(r1.is_pos()); - SASSERT((r2 - r1).is_neg()); - SASSERT((r2 - r3).is_zero()); - SASSERT(floor(r2).is_zero()); - SASSERT(ceil(r2).is_one()); + ENSURE(r2 == r3); + ENSURE(r1 != r2); + ENSURE(r2 + r3 == r1); + ENSURE(r1.is_pos()); + ENSURE((r2 - r1).is_neg()); + ENSURE((r2 - r3).is_zero()); + ENSURE(floor(r2).is_zero()); + ENSURE(ceil(r2).is_one()); // std::cout << "-r2: " << (-r2) << ", floor(-r2):" << floor(-r2) << "\n"; - SASSERT(floor(-r2).is_minus_one()); - SASSERT(ceil(-r2).is_zero()); - SASSERT(floor(r1) == r1); - SASSERT(ceil(r1) == r1); + ENSURE(floor(-r2).is_minus_one()); + ENSURE(ceil(-r2).is_zero()); + ENSURE(floor(r1) == r1); + ENSURE(ceil(r1) == r1); rational r4(3,5); - SASSERT(r3 * r4 == rational(3, 10)); - SASSERT(r3 / r4 == rational(5, 6)); + ENSURE(r3 * r4 == rational(3, 10)); + ENSURE(r3 / r4 == rational(5, 6)); rational r5(2,3); - SASSERT(r4 * r5 == rational(2, 5)); + ENSURE(r4 * r5 == rational(2, 5)); --r2; - SASSERT(r2 == -r3); + ENSURE(r2 == -r3); r2.neg(); - SASSERT(r2 == r3); + ENSURE(r2 == r3); --r2; r2 = abs(r2); - SASSERT(r2 == r3); + ENSURE(r2 == r3); --r2; ++r2; - SASSERT(r2 == r3); - SASSERT(r2 == abs(r2)); - SASSERT(r4 * rational(1) == r4); - SASSERT((r4 * rational(0)).is_zero()); - SASSERT(r4 * rational(-1) == -r4); - SASSERT(rational(1) * r4 == r4); - SASSERT((rational(0) * r4).is_zero()); - SASSERT(rational(-1) * r4 == -r4); - SASSERT(r4 + rational(0) == r4); - SASSERT(ceil(r4).is_one()); + ENSURE(r2 == r3); + ENSURE(r2 == abs(r2)); + ENSURE(r4 * rational(1) == r4); + ENSURE((r4 * rational(0)).is_zero()); + ENSURE(r4 * rational(-1) == -r4); + ENSURE(rational(1) * r4 == r4); + ENSURE((rational(0) * r4).is_zero()); + ENSURE(rational(-1) * r4 == -r4); + ENSURE(r4 + rational(0) == r4); + ENSURE(ceil(r4).is_one()); // std::cout << "r3: " << r3 << ", r4: " << r4 << ", -r4: " << -r4 << ", r3 / (-r4): " << (r3 / (-r4)) << "\n"; - SASSERT(r3 / (-r4) == rational(5,-6)); - SASSERT(div(rational(7), rational(2)) == rational(3)); - SASSERT(rational(7) % rational(4) == rational(3)); - SASSERT(div(rational(7), rational(-2)) == rational(-3)); - SASSERT(rational(3) + rational(5) == rational(8)); - SASSERT(rational("13/10") + rational("7/10") == rational(2)); - SASSERT(rational("100/20") == rational(5)); - SASSERT(gcd(rational(12), rational(8)) == rational(4)); - SASSERT(ceil(rational(-3,2)) == rational(-1)); - SASSERT(floor(rational(-3,2)) == rational(-2)); - SASSERT(ceil(rational(3,2)) == rational(2)); - SASSERT(floor(rational(3,2)) == rational(1)); - SASSERT(rational(3).is_pos()); - SASSERT(rational(0).is_nonneg()); - SASSERT(rational(3).is_pos()); - SASSERT(rational(3).is_nonneg()); - SASSERT(rational(0).is_nonneg()); - SASSERT(!rational(3).is_zero()); - SASSERT(!rational(-3).is_zero()); - SASSERT(rational(0).is_zero()); - SASSERT(rational(1).is_one()); - SASSERT(!rational(2).is_one()); - SASSERT(rational(3,4) >= rational(2,8)); - SASSERT(rational(3,4) <= rational(7,8)); - SASSERT(rational(3,4) <= rational(3,4)); - SASSERT(rational(3,4) >= rational(3,4)); - SASSERT(rational(3,4) > rational(2,8)); - SASSERT(rational(3,4) < rational(7,8)); + ENSURE(r3 / (-r4) == rational(5,-6)); + ENSURE(div(rational(7), rational(2)) == rational(3)); + ENSURE(rational(7) % rational(4) == rational(3)); + ENSURE(div(rational(7), rational(-2)) == rational(-3)); + ENSURE(rational(3) + rational(5) == rational(8)); + ENSURE(rational("13/10") + rational("7/10") == rational(2)); + ENSURE(rational("100/20") == rational(5)); + ENSURE(gcd(rational(12), rational(8)) == rational(4)); + ENSURE(ceil(rational(-3,2)) == rational(-1)); + ENSURE(floor(rational(-3,2)) == rational(-2)); + ENSURE(ceil(rational(3,2)) == rational(2)); + ENSURE(floor(rational(3,2)) == rational(1)); + ENSURE(rational(3).is_pos()); + ENSURE(rational(0).is_nonneg()); + ENSURE(rational(3).is_pos()); + ENSURE(rational(3).is_nonneg()); + ENSURE(rational(0).is_nonneg()); + ENSURE(!rational(3).is_zero()); + ENSURE(!rational(-3).is_zero()); + ENSURE(rational(0).is_zero()); + ENSURE(rational(1).is_one()); + ENSURE(!rational(2).is_one()); + ENSURE(rational(3,4) >= rational(2,8)); + ENSURE(rational(3,4) <= rational(7,8)); + ENSURE(rational(3,4) <= rational(3,4)); + ENSURE(rational(3,4) >= rational(3,4)); + ENSURE(rational(3,4) > rational(2,8)); + ENSURE(rational(3,4) < rational(7,8)); TRACE("rational", tout << rational(3,4) << "\n";); TRACE("rational", tout << rational(7,9) << "\n";); TRACE("rational", tout << rational(-3,7) << "\n";); TRACE("rational", tout << rational(5,8) << "\n";); TRACE("rational", tout << rational(4,2) << "\n";); - SASSERT(rational(3) + rational(2) == rational(5)); - SASSERT(rational(3) - rational(2) == rational(1)); - SASSERT(rational(3) * rational(2) == rational(6)); - SASSERT(rational(6) / rational(2) == rational(3)); - SASSERT(rational(6) % rational(4) == rational(2)); - SASSERT(power(rational(2),0) == rational(1)); - SASSERT(power(rational(2),1) == rational(2)); - SASSERT(power(rational(2),3) == rational(8)); + ENSURE(rational(3) + rational(2) == rational(5)); + ENSURE(rational(3) - rational(2) == rational(1)); + ENSURE(rational(3) * rational(2) == rational(6)); + ENSURE(rational(6) / rational(2) == rational(3)); + ENSURE(rational(6) % rational(4) == rational(2)); + ENSURE(power(rational(2),0) == rational(1)); + ENSURE(power(rational(2),1) == rational(2)); + ENSURE(power(rational(2),3) == rational(8)); } static void tst2() { @@ -116,90 +116,90 @@ static void tst2() { TRACE("rational", tout << r2 << std::endl;); TRACE("rational", tout << r3 << std::endl;); - SASSERT(r2 == r3); - SASSERT(r1 != r2); - SASSERT(rational(2)*r2 + r3 == r1); - SASSERT(r1.is_pos()); - SASSERT((r2 - r1).is_neg()); - SASSERT((r2 - r3).is_zero()); + ENSURE(r2 == r3); + ENSURE(r1 != r2); + ENSURE(rational(2)*r2 + r3 == r1); + ENSURE(r1.is_pos()); + ENSURE((r2 - r1).is_neg()); + ENSURE((r2 - r3).is_zero()); // std::cout << "===> " << floor(r2) << "\n"; { rational r0("1/3000000000000000000000000"); - SASSERT(ceil(r0).is_one()); - SASSERT(floor(-r0).is_minus_one()); - SASSERT(ceil(-r0).is_zero()); + ENSURE(ceil(r0).is_one()); + ENSURE(floor(-r0).is_minus_one()); + ENSURE(ceil(-r0).is_zero()); } - SASSERT(floor(r1) == r1); - SASSERT(ceil(r1) == r1); + ENSURE(floor(r1) == r1); + ENSURE(ceil(r1) == r1); rational r4("300000000/5"); - SASSERT(rational(1,2) * r4 == rational("300000000/10")); - SASSERT(rational(1,2) / r4 == rational("5/600000000")); + ENSURE(rational(1,2) * r4 == rational("300000000/10")); + ENSURE(rational(1,2) / r4 == rational("5/600000000")); rational r5(2,3); - SASSERT(r4 * r5 == rational("200000000/5")); + ENSURE(r4 * r5 == rational("200000000/5")); rational r6("10000000000000000000000000000000003/3"); --r6; - SASSERT(r6 == r2); + ENSURE(r6 == r2); r6.neg(); - SASSERT(r6 != r2); - SASSERT(abs(r6) == r2); + ENSURE(r6 != r2); + ENSURE(abs(r6) == r2); --r2; ++r2; r2.neg(); - SASSERT(r2 == r6); - SASSERT(r6 * rational(1) == r6); - SASSERT((r6 * rational(0)).is_zero()); - SASSERT(r6 * rational(-1) == -r6); - SASSERT(rational(1) * r6 == r6); - SASSERT((rational(0) * r6).is_zero()); - SASSERT(rational(-1) * r6 == -r6); - SASSERT(r6 + rational(0) == r6); + ENSURE(r2 == r6); + ENSURE(r6 * rational(1) == r6); + ENSURE((r6 * rational(0)).is_zero()); + ENSURE(r6 * rational(-1) == -r6); + ENSURE(rational(1) * r6 == r6); + ENSURE((rational(0) * r6).is_zero()); + ENSURE(rational(-1) * r6 == -r6); + ENSURE(r6 + rational(0) == r6); - SASSERT(rational("300000000000000").is_pos()); - SASSERT(rational("0000000000000000000").is_nonneg()); - SASSERT(rational("0000000000000000000").is_nonpos()); - SASSERT(rational("3000000000000000000/2").is_pos()); - SASSERT(rational("3000000000000000000/2").is_nonneg()); - SASSERT((-rational("3000000000000000000/2")).is_neg()); - SASSERT(!rational("3000000000000000000/2").is_neg()); - SASSERT(!rational("3000000000000000000/2").is_zero()); - SASSERT(!rational("3000000000000000000/2").is_one()); - SASSERT(rational("99999999999/2") >= rational("23/2")); - SASSERT(rational("99999999999/2") > rational("23/2")); - SASSERT(rational("23/2") <= rational("99999999999/2")); - SASSERT(rational("23/2") < rational("99999999999/2")); - SASSERT(!(rational("99999999999/2") < rational("23/2"))); + ENSURE(rational("300000000000000").is_pos()); + ENSURE(rational("0000000000000000000").is_nonneg()); + ENSURE(rational("0000000000000000000").is_nonpos()); + ENSURE(rational("3000000000000000000/2").is_pos()); + ENSURE(rational("3000000000000000000/2").is_nonneg()); + ENSURE((-rational("3000000000000000000/2")).is_neg()); + ENSURE(!rational("3000000000000000000/2").is_neg()); + ENSURE(!rational("3000000000000000000/2").is_zero()); + ENSURE(!rational("3000000000000000000/2").is_one()); + ENSURE(rational("99999999999/2") >= rational("23/2")); + ENSURE(rational("99999999999/2") > rational("23/2")); + ENSURE(rational("23/2") <= rational("99999999999/2")); + ENSURE(rational("23/2") < rational("99999999999/2")); + ENSURE(!(rational("99999999999/2") < rational("23/2"))); rational int64_max("9223372036854775807"); rational int64_min((-int64_max) - rational(1)); // is_int64 - SASSERT(int64_max.is_int64()); - SASSERT(int64_min.is_int64()); - SASSERT(rational(0).is_int64()); - SASSERT(rational(1).is_int64()); - SASSERT(rational(-1).is_int64()); - SASSERT(!(int64_max + rational(1)).is_int64()); - SASSERT(!(int64_min - rational(1)).is_int64()); + ENSURE(int64_max.is_int64()); + ENSURE(int64_min.is_int64()); + ENSURE(rational(0).is_int64()); + ENSURE(rational(1).is_int64()); + ENSURE(rational(-1).is_int64()); + ENSURE(!(int64_max + rational(1)).is_int64()); + ENSURE(!(int64_min - rational(1)).is_int64()); // is_uint64 - SASSERT(int64_max.is_uint64()); - SASSERT(!int64_min.is_uint64()); - SASSERT(rational(0).is_uint64()); - SASSERT(rational(1).is_uint64()); - SASSERT(!rational(-1).is_uint64()); - SASSERT((int64_max + rational(1)).is_uint64()); - SASSERT(!(int64_min - rational(1)).is_uint64()); + ENSURE(int64_max.is_uint64()); + ENSURE(!int64_min.is_uint64()); + ENSURE(rational(0).is_uint64()); + ENSURE(rational(1).is_uint64()); + ENSURE(!rational(-1).is_uint64()); + ENSURE((int64_max + rational(1)).is_uint64()); + ENSURE(!(int64_min - rational(1)).is_uint64()); rational uint64_max(rational(1) + (rational(2) * int64_max)); - SASSERT(uint64_max.is_uint64()); + ENSURE(uint64_max.is_uint64()); // get_int64, get_uint64 uint64 u1 = uint64_max.get_uint64(); uint64 u2 = UINT64_MAX; - SASSERT(u1 == u2); + VERIFY(u1 == u2); std::cout << "int64_max: " << int64_max << ", INT64_MAX: " << INT64_MAX << ", int64_max.get_int64(): " << int64_max.get_int64() << ", int64_max.get_uint64(): " << int64_max.get_uint64() << "\n"; - SASSERT(int64_max.get_int64() == INT64_MAX); - SASSERT(int64_min.get_int64() == INT64_MIN); + ENSURE(int64_max.get_int64() == INT64_MAX); + ENSURE(int64_min.get_int64() == INT64_MIN); // extended Euclid: @@ -219,7 +219,7 @@ void tst3() { TRACE("rational", tout << "n4: " << n4 << "\n"; tout << "n5: " << n5 << "\n";); - SASSERT(n5 == rational("2147483646")); + ENSURE(n5 == rational("2147483646")); } void tst4() { @@ -236,7 +236,7 @@ void tst5() { TRACE("rational", tout << n1 << " " << n2 << " " << n1.is_big() << " " << n2.is_big() << "\n";); n1 *= n2; TRACE("rational", tout << "after: " << n1 << " " << n2 << "\n";); - SASSERT(n1.is_minus_one()); + ENSURE(n1.is_minus_one()); } void tst6() { @@ -274,8 +274,8 @@ public: static void tst1() { rational n1(-1); rational n2(8); - SASSERT((n1 % n2).is_minus_one()); - SASSERT(mod(n1, n2) == rational(7)); + ENSURE((n1 % n2).is_minus_one()); + ENSURE(mod(n1, n2) == rational(7)); } static void tst_hash(int val) { @@ -283,7 +283,7 @@ public: rational n2("10203939394995449949494394932929"); rational n3(val); n2 = n3; - SASSERT(n1.hash() == n2.hash()); + ENSURE(n1.hash() == n2.hash()); } static void tst2() { @@ -306,47 +306,47 @@ static void tst7() { rational gcd; extended_gcd(n, p, gcd, x, y); TRACE("gcd", tout << n << " " << p << ": " << gcd << " " << x << " " << y << "\n";); - SASSERT(!mod(n, rational(2)).is_one() || mod(n * x, p).is_one()); + ENSURE(!mod(n, rational(2)).is_one() || mod(n * x, p).is_one()); } } static void tst8() { rational r; - SASSERT(!rational(-4).is_int_perfect_square(r) && r.is_zero()); - SASSERT(!rational(-3).is_int_perfect_square(r) && r.is_zero()); - SASSERT(!rational(-2).is_int_perfect_square(r) && r.is_zero()); - SASSERT(!rational(-1).is_int_perfect_square(r) && r.is_zero()); - SASSERT(rational(0).is_int_perfect_square(r) && r.is_zero()); - SASSERT(rational(1).is_int_perfect_square(r) && r.is_one()); - SASSERT(!rational(2).is_int_perfect_square(r) && r == rational(2)); - SASSERT(!rational(3).is_int_perfect_square(r) && r == rational(2)); - SASSERT(rational(4).is_int_perfect_square(r) && r == rational(2)); - SASSERT(!rational(5).is_int_perfect_square(r) && r == rational(3)); - SASSERT(!rational(6).is_int_perfect_square(r) && r == rational(3)); - SASSERT(!rational(7).is_int_perfect_square(r) && r == rational(3)); - SASSERT(!rational(8).is_int_perfect_square(r) && r == rational(3)); - SASSERT(rational(9).is_int_perfect_square(r) && r == rational(3)); - SASSERT(!rational(10).is_int_perfect_square(r) && r == rational(4)); - SASSERT(!rational(11).is_int_perfect_square(r) && r == rational(4)); - SASSERT(!rational(12).is_int_perfect_square(r) && r == rational(4)); - SASSERT(!rational(13).is_int_perfect_square(r) && r == rational(4)); - SASSERT(!rational(14).is_int_perfect_square(r) && r == rational(4)); - SASSERT(!rational(15).is_int_perfect_square(r) && r == rational(4)); - SASSERT(rational(16).is_int_perfect_square(r) && r == rational(4)); - SASSERT(!rational(17).is_int_perfect_square(r) && r == rational(5)); - SASSERT(!rational(18).is_int_perfect_square(r) && r == rational(5)); - SASSERT(!rational(19).is_int_perfect_square(r) && r == rational(5)); - SASSERT(!rational(20).is_int_perfect_square(r) && r == rational(5)); - SASSERT(!rational(21).is_int_perfect_square(r) && r == rational(5)); - SASSERT(!rational(22).is_int_perfect_square(r) && r == rational(5)); - SASSERT(!rational(23).is_int_perfect_square(r) && r == rational(5)); - SASSERT(!rational(24).is_int_perfect_square(r) && r == rational(5)); - SASSERT(rational(25).is_int_perfect_square(r) && r == rational(5)); - SASSERT(!rational(26).is_int_perfect_square(r) && r == rational(6)); - SASSERT(rational(36).is_int_perfect_square(r) && r == rational(6)); + ENSURE(!rational(-4).is_int_perfect_square(r) && r.is_zero()); + ENSURE(!rational(-3).is_int_perfect_square(r) && r.is_zero()); + ENSURE(!rational(-2).is_int_perfect_square(r) && r.is_zero()); + ENSURE(!rational(-1).is_int_perfect_square(r) && r.is_zero()); + ENSURE(rational(0).is_int_perfect_square(r) && r.is_zero()); + ENSURE(rational(1).is_int_perfect_square(r) && r.is_one()); + ENSURE(!rational(2).is_int_perfect_square(r) && r == rational(2)); + ENSURE(!rational(3).is_int_perfect_square(r) && r == rational(2)); + ENSURE(rational(4).is_int_perfect_square(r) && r == rational(2)); + ENSURE(!rational(5).is_int_perfect_square(r) && r == rational(3)); + ENSURE(!rational(6).is_int_perfect_square(r) && r == rational(3)); + ENSURE(!rational(7).is_int_perfect_square(r) && r == rational(3)); + ENSURE(!rational(8).is_int_perfect_square(r) && r == rational(3)); + ENSURE(rational(9).is_int_perfect_square(r) && r == rational(3)); + ENSURE(!rational(10).is_int_perfect_square(r) && r == rational(4)); + ENSURE(!rational(11).is_int_perfect_square(r) && r == rational(4)); + ENSURE(!rational(12).is_int_perfect_square(r) && r == rational(4)); + ENSURE(!rational(13).is_int_perfect_square(r) && r == rational(4)); + ENSURE(!rational(14).is_int_perfect_square(r) && r == rational(4)); + ENSURE(!rational(15).is_int_perfect_square(r) && r == rational(4)); + ENSURE(rational(16).is_int_perfect_square(r) && r == rational(4)); + ENSURE(!rational(17).is_int_perfect_square(r) && r == rational(5)); + ENSURE(!rational(18).is_int_perfect_square(r) && r == rational(5)); + ENSURE(!rational(19).is_int_perfect_square(r) && r == rational(5)); + ENSURE(!rational(20).is_int_perfect_square(r) && r == rational(5)); + ENSURE(!rational(21).is_int_perfect_square(r) && r == rational(5)); + ENSURE(!rational(22).is_int_perfect_square(r) && r == rational(5)); + ENSURE(!rational(23).is_int_perfect_square(r) && r == rational(5)); + ENSURE(!rational(24).is_int_perfect_square(r) && r == rational(5)); + ENSURE(rational(25).is_int_perfect_square(r) && r == rational(5)); + ENSURE(!rational(26).is_int_perfect_square(r) && r == rational(6)); + ENSURE(rational(36).is_int_perfect_square(r) && r == rational(6)); - SASSERT(rational(1,9).is_perfect_square(r) && r == rational(1,3)); - SASSERT(rational(4,9).is_perfect_square(r) && r == rational(2,3)); + ENSURE(rational(1,9).is_perfect_square(r) && r == rational(1,3)); + ENSURE(rational(4,9).is_perfect_square(r) && r == rational(2,3)); } @@ -363,9 +363,9 @@ static void tstmod(rational const& m, rational const& n) { std::cout << m << " " << n << " " << q << " " << r << "\n"; std::cout << m << " == " << n*q+r << "\n"; - SASSERT(m == (n * q) + r); - SASSERT(rational::zero() <= r); - SASSERT(r < abs(n)); + ENSURE(m == (n * q) + r); + ENSURE(rational::zero() <= r); + ENSURE(r < abs(n)); } diff --git a/src/test/rcf.cpp b/src/test/rcf.cpp index 170c053f1..082147190 100644 --- a/src/test/rcf.cpp +++ b/src/test/rcf.cpp @@ -116,13 +116,13 @@ static void tst_solve(unsigned n, int _A[], int _b[], int _c[], bool solved) { svector b; b.resize(n, 0); if (mm.solve(A, b.c_ptr(), _c)) { - SASSERT(solved); + ENSURE(solved); for (unsigned i = 0; i < n; i++) { - SASSERT(b[i] == _b[i]); + ENSURE(b[i] == _b[i]); } } else { - SASSERT(!solved); + ENSURE(!solved); } } @@ -140,7 +140,7 @@ static void tst_lin_indep(unsigned m, unsigned n, int _A[], unsigned ex_sz, unsi scoped_mpz_matrix B(mm); mm.linear_independent_rows(A, r.c_ptr(), B); for (unsigned i = 0; i < ex_sz; i++) { - SASSERT(r[i] == ex_r[i]); + ENSURE(r[i] == ex_r[i]); } } diff --git a/src/test/sat_user_scope.cpp b/src/test/sat_user_scope.cpp index ebda383f9..d06a55c4c 100644 --- a/src/test/sat_user_scope.cpp +++ b/src/test/sat_user_scope.cpp @@ -34,10 +34,6 @@ static void add_clause(sat::solver& s, random_gen& r, trail_t& t) { s.mk_clause(cls.size(), cls.c_ptr()); } -static void display_state(std::ostream& out, sat::solver& s, trail_t& t) { - s.display(out); -} - static void pop_user_scope(sat::solver& s, trail_t& t) { std::cout << "pop\n"; s.user_pop(1); @@ -77,7 +73,7 @@ static void check_coherence(sat::solver& s1, trail_t& t) { s2.display(std::cout); } std::cout << is_sat1 << "\n"; - SASSERT(is_sat1 == is_sat2); + ENSURE(is_sat1 == is_sat2); } void tst_sat_user_scope() { diff --git a/src/test/simple_parser.cpp b/src/test/simple_parser.cpp index a5d4d8def..934552711 100644 --- a/src/test/simple_parser.cpp +++ b/src/test/simple_parser.cpp @@ -38,6 +38,7 @@ void tst_simple_parser() { TRACE("simple_parser", tout << mk_pp(r, m) << "\n";); p.parse_string("(+ x (* y x) x)", r); float vals[2] = { 2.0f, 3.0f }; + (void)vals; TRACE("simple_parser", tout << mk_pp(r, m) << "\n"; tout << "val: " << eval(r, 2, vals) << "\n";); diff --git a/src/test/simplex.cpp b/src/test/simplex.cpp index 6f08bd04d..8e57f6110 100644 --- a/src/test/simplex.cpp +++ b/src/test/simplex.cpp @@ -84,7 +84,7 @@ void add_row(Simplex& S, vector const& _v, R const& _b, bool is_eq = false) { coeffs.push_back(b.to_mpq().numerator()); mpq_inf one(mpq(1),mpq(0)); mpq_inf zero(mpq(0),mpq(0)); - SASSERT(vars.size() == coeffs.size()); + ENSURE(vars.size() == coeffs.size()); S.set_lower(nv, zero); if (is_eq) S.set_upper(nv, zero); S.set_lower(nv+1, one); diff --git a/src/test/simplifier.cpp b/src/test/simplifier.cpp index 2e8f434e1..5a05ab30f 100644 --- a/src/test/simplifier.cpp +++ b/src/test/simplifier.cpp @@ -18,7 +18,7 @@ static void ev_const(Z3_context ctx, Z3_ast e) { tout << Z3_ast_to_string(ctx, e) << " -> "; tout << Z3_ast_to_string(ctx, r) << "\n";); Z3_ast_kind k = Z3_get_ast_kind(ctx, r); - SASSERT(k == Z3_NUMERAL_AST || + ENSURE(k == Z3_NUMERAL_AST || (k == Z3_APP_AST && (Z3_OP_TRUE == Z3_get_decl_kind(ctx,Z3_get_app_decl(ctx, Z3_to_app(ctx, r))) || Z3_OP_FALSE == Z3_get_decl_kind(ctx,Z3_get_app_decl(ctx, Z3_to_app(ctx, r)))))); @@ -34,7 +34,7 @@ static void test_bv() { Z3_ast bit3_2 = Z3_mk_numeral(ctx, "3", bv2); Z3_ast e = Z3_mk_eq(ctx, bit3_2, Z3_mk_sign_ext(ctx, 1, bit1_1)); - SASSERT(Z3_simplify(ctx, e) == Z3_mk_true(ctx)); + ENSURE(Z3_simplify(ctx, e) == Z3_mk_true(ctx)); TRACE("simplifier", tout << Z3_ast_to_string(ctx, e) << "\n";); Z3_ast b12 = Z3_mk_numeral(ctx, "12", bv72); @@ -97,18 +97,18 @@ static void test_datatypes() { nil = Z3_mk_app(ctx, nil_decl, 0, 0); Z3_ast a = Z3_simplify(ctx, Z3_mk_app(ctx, is_nil_decl, 1, &nil)); - SASSERT(a == Z3_mk_true(ctx)); + ENSURE(a == Z3_mk_true(ctx)); a = Z3_simplify(ctx, Z3_mk_app(ctx, is_cons_decl, 1, &nil)); - SASSERT(a == Z3_mk_false(ctx)); + ENSURE(a == Z3_mk_false(ctx)); Z3_ast one = Z3_mk_numeral(ctx, "1", int_ty); Z3_ast args[2] = { one, nil }; l1 = Z3_mk_app(ctx, cons_decl, 2, args); - SASSERT(nil == Z3_simplify(ctx, Z3_mk_app(ctx, tail_decl, 1, &l1))); - SASSERT(one == Z3_simplify(ctx, Z3_mk_app(ctx, head_decl, 1, &l1))); + ENSURE(nil == Z3_simplify(ctx, Z3_mk_app(ctx, tail_decl, 1, &l1))); + ENSURE(one == Z3_simplify(ctx, Z3_mk_app(ctx, head_decl, 1, &l1))); - SASSERT(Z3_mk_false(ctx) == Z3_simplify(ctx, Z3_mk_eq(ctx, nil, l1))); + ENSURE(Z3_mk_false(ctx) == Z3_simplify(ctx, Z3_mk_eq(ctx, nil, l1))); Z3_del_config(cfg); Z3_del_context(ctx); @@ -147,8 +147,8 @@ static void test_bool() { Z3_ast a = Z3_simplify(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, Z3_mk_false(ctx), Z3_mk_true(ctx)))); Z3_ast b = Z3_simplify(ctx, Z3_mk_not(ctx, Z3_mk_iff(ctx, Z3_mk_false(ctx), Z3_mk_true(ctx)))); - SASSERT(Z3_mk_true(ctx) == a); - SASSERT(Z3_mk_true(ctx) == b); + ENSURE(Z3_mk_true(ctx) == a); + ENSURE(Z3_mk_true(ctx) == b); TRACE("simplifier", tout << Z3_ast_to_string(ctx, a) << "\n";); TRACE("simplifier", tout << Z3_ast_to_string(ctx, b) << "\n";); @@ -179,8 +179,8 @@ static void test_array() { TRACE("simplifier", tout << Z3_ast_to_string(ctx, rxy) << "\n";); TRACE("simplifier", tout << Z3_ast_to_string(ctx, Z3_simplify(ctx, Z3_mk_eq(ctx, x2, x3))) << "\n";); - // SASSERT(rxy == Z3_mk_true(ctx)); - // SASSERT(Z3_simplify(ctx, Z3_mk_eq(ctx, x2, x3)) == Z3_mk_false(ctx)); + // ENSURE(rxy == Z3_mk_true(ctx)); + // ENSURE(Z3_simplify(ctx, Z3_mk_eq(ctx, x2, x3)) == Z3_mk_false(ctx)); for (unsigned i = 0; i < 4; ++i) { for (unsigned j = 0; j < 4; ++j) { diff --git a/src/test/small_object_allocator.cpp b/src/test/small_object_allocator.cpp index 1ecf865dd..5ae2836d0 100644 --- a/src/test/small_object_allocator.cpp +++ b/src/test/small_object_allocator.cpp @@ -36,5 +36,14 @@ void tst_small_object_allocator() { r3 = new (soa) char[1]; TRACE("small_object_allocator", tout << "r1: " << (void*)r1 << " r2: " << (void*)r2 << " r3: " << (void*)r3 << " r4: " << (void*)r4 << "\n";); + (void)r1; + (void)r2; + (void)r3; + (void)r4; + (void)q1; + + (void)p1; + (void)p2; + (void)p3; } diff --git a/src/test/sorting_network.cpp b/src/test/sorting_network.cpp index 81340651a..9836bc04d 100644 --- a/src/test/sorting_network.cpp +++ b/src/test/sorting_network.cpp @@ -57,7 +57,7 @@ struct unsigned_ext { static void is_sorted(svector const& v) { for (unsigned i = 0; i + 1 < v.size(); ++i) { - SASSERT(v[i] <= v[i+1]); + ENSURE(v[i] <= v[i+1]); } } @@ -184,7 +184,7 @@ struct ast_ext2 { static void test_sorting_eq(unsigned n, unsigned k) { - SASSERT(k < n); + ENSURE(k < n); ast_manager m; reg_decl_plugins(m); ast_ext2 ext(m); @@ -206,14 +206,14 @@ static void test_sorting_eq(unsigned n, unsigned k) { solver.assert_expr(ext.m_clauses[i].get()); } lbool res = solver.check(); - SASSERT(res == l_true); + ENSURE(res == l_true); solver.push(); for (unsigned i = 0; i < k; ++i) { solver.assert_expr(in[i].get()); } res = solver.check(); - SASSERT(res == l_true); + ENSURE(res == l_true); solver.assert_expr(in[k].get()); res = solver.check(); if (res == l_true) { @@ -227,7 +227,7 @@ static void test_sorting_eq(unsigned n, unsigned k) { model_smt2_pp(std::cout, m, *model, 0); TRACE("pb", model_smt2_pp(tout, m, *model, 0);); } - SASSERT(res == l_false); + ENSURE(res == l_false); solver.pop(1); ext.m_clauses.reset(); } @@ -253,13 +253,13 @@ static void test_sorting_le(unsigned n, unsigned k) { solver.assert_expr(ext.m_clauses[i].get()); } lbool res = solver.check(); - SASSERT(res == l_true); + ENSURE(res == l_true); for (unsigned i = 0; i < k; ++i) { solver.assert_expr(in[i].get()); } res = solver.check(); - SASSERT(res == l_true); + ENSURE(res == l_true); solver.assert_expr(in[k].get()); res = solver.check(); if (res == l_true) { @@ -273,7 +273,7 @@ static void test_sorting_le(unsigned n, unsigned k) { model_smt2_pp(std::cout, m, *model, 0); TRACE("pb", model_smt2_pp(tout, m, *model, 0);); } - SASSERT(res == l_false); + ENSURE(res == l_false); solver.pop(1); ext.m_clauses.reset(); } @@ -300,14 +300,14 @@ void test_sorting_ge(unsigned n, unsigned k) { solver.assert_expr(ext.m_clauses[i].get()); } lbool res = solver.check(); - SASSERT(res == l_true); + ENSURE(res == l_true); solver.push(); for (unsigned i = 0; i < n - k; ++i) { solver.assert_expr(m.mk_not(in[i].get())); } res = solver.check(); - SASSERT(res == l_true); + ENSURE(res == l_true); solver.assert_expr(m.mk_not(in[n - k].get())); res = solver.check(); if (res == l_true) { @@ -321,7 +321,7 @@ void test_sorting_ge(unsigned n, unsigned k) { model_smt2_pp(std::cout, m, *model, 0); TRACE("pb", model_smt2_pp(tout, m, *model, 0);); } - SASSERT(res == l_false); + ENSURE(res == l_false); solver.pop(1); } @@ -364,15 +364,13 @@ void test_at_most_1(unsigned n, bool full) { for (unsigned i = 0; i < ext.m_clauses.size(); ++i) { solver.assert_expr(ext.m_clauses[i].get()); } - lbool res; if (full) { solver.push(); solver.assert_expr(m.mk_not(m.mk_eq(result1, result2))); std::cout << result1 << "\n"; - res = solver.check(); - SASSERT(res == l_false); + VERIFY(l_false == solver.check()); solver.pop(1); } @@ -390,8 +388,7 @@ void test_at_most_1(unsigned n, bool full) { std::cout << atom << "\n"; if (is_true) ++k; } - res = solver.check(); - SASSERT(res == l_true); + VERIFY(l_false == solver.check()); if (k > 1) { solver.assert_expr(result1); } @@ -402,8 +399,7 @@ void test_at_most_1(unsigned n, bool full) { else { solver.assert_expr(m.mk_not(result1)); } - res = solver.check(); - SASSERT(res == l_false); + VERIFY(l_false == solver.check()); solver.pop(1); } } diff --git a/src/test/stack.cpp b/src/test/stack.cpp index 6a4dd3cd8..c8f3d88a6 100644 --- a/src/test/stack.cpp +++ b/src/test/stack.cpp @@ -27,8 +27,8 @@ static void tst1() { point * p1 = new (s) point(10, 20); point * p2 = new (s) point(30, 40); void * ptr = s.allocate(16000); - SASSERT(p2->first == 30 && p2->second == 40); - SASSERT(p1->first == 10 && p1->second == 20); + ENSURE(p2->first == 30 && p2->second == 40); + ENSURE(p1->first == 10 && p1->second == 20); s.deallocate(static_cast(ptr)); s.deallocate(p2); s.deallocate(p1); @@ -38,8 +38,8 @@ static void tst2(unsigned num, unsigned del_rate) { ptr_vector ptrs; stack s; for (unsigned i = 0; i < num; i++) { - SASSERT(ptrs.empty() == s.empty()); - SASSERT(s.empty() || ptrs.back() == s.top()); + ENSURE(ptrs.empty() == s.empty()); + ENSURE(s.empty() || ptrs.back() == s.top()); if (!ptrs.empty() && rand() % del_rate == 0) { s.deallocate(); ptrs.pop_back(); @@ -57,8 +57,8 @@ static void tst2(unsigned num, unsigned del_rate) { } } while (s.empty()) { - SASSERT(ptrs.empty() == s.empty()); - SASSERT(s.empty() || ptrs.back() == s.top()); + ENSURE(ptrs.empty() == s.empty()); + ENSURE(s.empty() || ptrs.back() == s.top()); s.deallocate(); ptrs.pop_back(); } diff --git a/src/test/string_buffer.cpp b/src/test/string_buffer.cpp index 67d60528c..7d7854a9c 100644 --- a/src/test/string_buffer.cpp +++ b/src/test/string_buffer.cpp @@ -24,7 +24,7 @@ Revision History: static void tst1() { string_buffer<> b; b << "Testing" << 10 << true; - SASSERT(strcmp(b.c_str(), "Testing10true") == 0); + ENSURE(strcmp(b.c_str(), "Testing10true") == 0); } static void tst2() { @@ -34,7 +34,7 @@ static void tst2() { b << r; } TRACE("string_buffer", tout << b.c_str() << "\n";); - SASSERT(strlen(b.c_str()) == 10000); + ENSURE(strlen(b.c_str()) == 10000); } static void tst3() { @@ -42,7 +42,7 @@ static void tst3() { string_buffer<128> b2; b2 << "World"; b << "Hello" << " " << b2; - SASSERT(strcmp(b.c_str(), "Hello World") == 0); + ENSURE(strcmp(b.c_str(), "Hello World") == 0); } void tst_string_buffer() { diff --git a/src/test/substitution.cpp b/src/test/substitution.cpp index cdc7f2080..5609225c6 100644 --- a/src/test/substitution.cpp +++ b/src/test/substitution.cpp @@ -35,6 +35,8 @@ void tst_substitution() bool ok1 = unif(v1.get(), v2.get(), subst, false); bool ok2 = unif(v2.get(), v1.get(), subst, false); + (void)ok1; + (void)ok2; expr_ref res(m); diff --git a/src/test/symbol.cpp b/src/test/symbol.cpp index c87955116..e91332285 100644 --- a/src/test/symbol.cpp +++ b/src/test/symbol.cpp @@ -24,31 +24,31 @@ static void tst1() { symbol s1("foo"); symbol s2("boo"); symbol s3("foo"); - SASSERT(s1 != s2); - SASSERT(s1 == s3); + ENSURE(s1 != s2); + ENSURE(s1 == s3); std::cout << s1 << " " << s2 << " " << s3 << "\n"; - SASSERT(s1 == "foo"); - SASSERT(s1 != "boo"); - SASSERT(s2 != "foo"); - SASSERT(s3 == "foo"); - SASSERT(s2 == "boo"); + ENSURE(s1 == "foo"); + ENSURE(s1 != "boo"); + ENSURE(s2 != "foo"); + ENSURE(s3 == "foo"); + ENSURE(s2 == "boo"); - SASSERT(lt(s2, s1)); - SASSERT(!lt(s1, s2)); - SASSERT(!lt(s1, s3)); - SASSERT(lt(symbol("abcc"), symbol("abcd"))); - SASSERT(!lt(symbol("abcd"), symbol("abcc"))); - SASSERT(lt(symbol("abc"), symbol("abcc"))); - SASSERT(!lt(symbol("abcd"), symbol("abc"))); - SASSERT(lt(symbol(10), s1)); - SASSERT(!lt(s1, symbol(10))); - SASSERT(lt(symbol(10), symbol(20))); - SASSERT(!lt(symbol(20), symbol(10))); - SASSERT(!lt(symbol(10), symbol(10))); - SASSERT(lt(symbol("a"), symbol("b"))); - SASSERT(!lt(symbol("z"), symbol("b"))); - SASSERT(!lt(symbol("zzz"), symbol("b"))); - SASSERT(lt(symbol("zzz"), symbol("zzzb"))); + ENSURE(lt(s2, s1)); + ENSURE(!lt(s1, s2)); + ENSURE(!lt(s1, s3)); + ENSURE(lt(symbol("abcc"), symbol("abcd"))); + ENSURE(!lt(symbol("abcd"), symbol("abcc"))); + ENSURE(lt(symbol("abc"), symbol("abcc"))); + ENSURE(!lt(symbol("abcd"), symbol("abc"))); + ENSURE(lt(symbol(10), s1)); + ENSURE(!lt(s1, symbol(10))); + ENSURE(lt(symbol(10), symbol(20))); + ENSURE(!lt(symbol(20), symbol(10))); + ENSURE(!lt(symbol(10), symbol(10))); + ENSURE(lt(symbol("a"), symbol("b"))); + ENSURE(!lt(symbol("z"), symbol("b"))); + ENSURE(!lt(symbol("zzz"), symbol("b"))); + ENSURE(lt(symbol("zzz"), symbol("zzzb"))); } void tst_symbol() { diff --git a/src/test/symbol_table.cpp b/src/test/symbol_table.cpp index f67ef6f66..626e2a72f 100644 --- a/src/test/symbol_table.cpp +++ b/src/test/symbol_table.cpp @@ -21,24 +21,22 @@ Revision History: static void tst1() { symbol_table t; t.insert(symbol("foo"), 35); - SASSERT(t.contains(symbol("foo"))); - SASSERT(!t.contains(symbol("boo"))); + ENSURE(t.contains(symbol("foo"))); + ENSURE(!t.contains(symbol("boo"))); t.begin_scope(); t.insert(symbol("boo"), 20); - SASSERT(t.contains(symbol("boo"))); -#ifdef Z3DEBUG + ENSURE(t.contains(symbol("boo"))); int tmp; -#endif - SASSERT(t.find(symbol("boo"), tmp) && tmp == 20); - SASSERT(t.find(symbol("foo"), tmp) && tmp == 35); + ENSURE(t.find(symbol("boo"), tmp) && tmp == 20); + ENSURE(t.find(symbol("foo"), tmp) && tmp == 35); t.insert(symbol("foo"), 100); - SASSERT(t.find(symbol("foo"), tmp) && tmp == 100); + ENSURE(t.find(symbol("foo"), tmp) && tmp == 100); t.end_scope(); - SASSERT(t.find(symbol("foo"), tmp) && tmp == 35); - SASSERT(!t.contains(symbol("boo"))); + ENSURE(t.find(symbol("foo"), tmp) && tmp == 35); + ENSURE(!t.contains(symbol("boo"))); t.reset(); - SASSERT(!t.contains(symbol("boo"))); - SASSERT(!t.contains(symbol("foo"))); + ENSURE(!t.contains(symbol("boo"))); + ENSURE(!t.contains(symbol("foo"))); } void tst_symbol_table() { diff --git a/src/test/tbv.cpp b/src/test/tbv.cpp index 7637c7e83..00f7e0960 100644 --- a/src/test/tbv.cpp +++ b/src/test/tbv.cpp @@ -17,18 +17,18 @@ static void tst1(unsigned num_bits) { m.display(std::cout, *b1) << "\n"; m.display(std::cout, *bX) << "\n"; m.display(std::cout, *bN) << "\n"; - SASSERT(!m.equals(*b1,*b0)); - SASSERT(!m.equals(*b1,*bX)); - SASSERT(!m.equals(*b0,*bX)); + ENSURE(!m.equals(*b1,*b0)); + ENSURE(!m.equals(*b1,*bX)); + ENSURE(!m.equals(*b0,*bX)); m.set_and(*bX,*b0); - SASSERT(m.equals(*b0,*bX)); - SASSERT(!m.equals(*b1,*bX)); + ENSURE(m.equals(*b0,*bX)); + ENSURE(!m.equals(*b1,*bX)); m.copy(*bX,*b1); - SASSERT(m.equals(*b1,*bX)); - SASSERT(!m.equals(*b0,*bX)); + ENSURE(m.equals(*b1,*bX)); + ENSURE(!m.equals(*b0,*bX)); m.fillX(*bX); VERIFY(m.intersect(*bX,*b0,*bN)); - SASSERT(m.equals(*b0, *bN)); + ENSURE(m.equals(*b0, *bN)); VERIFY(!m.intersect(*b0,*b1,*bN)); m.fill1(*b1); bit_vector to_delete; @@ -58,8 +58,8 @@ static void tst0() { m.display(std::cout, *t1) << "\n"; m.display(std::cout, *t2) << "\n"; m.display(std::cout, *t3) << "\n"; - SASSERT(m.equals(*t1, *t2)); - SASSERT(m.equals(*t1, *t3)); + ENSURE(m.equals(*t1, *t2)); + ENSURE(m.equals(*t1, *t3)); } static void tst2(unsigned num_bits) { @@ -67,10 +67,10 @@ static void tst2(unsigned num_bits) { tbv_ref t(m), t2(m); for (unsigned i = 0; i < 55; ++i) { t = m.allocate(i); - SASSERT(m.is_well_formed(*t)); + ENSURE(m.is_well_formed(*t)); t2 = m.allocate(i+1); VERIFY(!m.set_and(*t2, *t)); - SASSERT(!m.is_well_formed(*t2)); + ENSURE(!m.is_well_formed(*t2)); } } diff --git a/src/test/theory_pb.cpp b/src/test/theory_pb.cpp index 3a229d951..42a03f619 100644 --- a/src/test/theory_pb.cpp +++ b/src/test/theory_pb.cpp @@ -12,7 +12,7 @@ Copyright (c) 2015 Microsoft Corporation #include "th_rewriter.h" unsigned populate_literals(unsigned k, smt::literal_vector& lits) { - SASSERT(k < (1u << lits.size())); + ENSURE(k < (1u << lits.size())); unsigned t = 0; for (unsigned i = 0; i < lits.size(); ++i) { if (k & (1 << i)) { @@ -159,7 +159,7 @@ void tst_theory_pb() { smt::context ctx(m, params); ctx.push(); smt::literal l = smt::theory_pb::assert_ge(ctx, k, lits.size(), lits.c_ptr()); - SASSERT(l != smt::false_literal); + ENSURE(l != smt::false_literal); ctx.assign(l, 0, false); TRACE("pb", ctx.display(tout);); VERIFY(l_true == ctx.check()); diff --git a/src/test/total_order.cpp b/src/test/total_order.cpp index 2fa22065f..12bb4d977 100644 --- a/src/test/total_order.cpp +++ b/src/test/total_order.cpp @@ -25,12 +25,12 @@ static void tst1() { to.insert(1); to.insert_after(1, 2); to.insert_after(1, 3); - SASSERT(to.lt(1, 2)); - SASSERT(to.lt(3, 2)); - SASSERT(to.lt(1, 3)); - SASSERT(!to.lt(2, 3)); - SASSERT(!to.lt(3, 1)); - SASSERT(!to.lt(2, 2)); + ENSURE(to.lt(1, 2)); + ENSURE(to.lt(3, 2)); + ENSURE(to.lt(1, 3)); + ENSURE(!to.lt(2, 3)); + ENSURE(!to.lt(3, 1)); + ENSURE(!to.lt(2, 2)); std::cout << to << "\n"; } @@ -43,8 +43,8 @@ static void tst2() { to.move_after(3, 1); to.move_after(1, 2); to.move_after(2, 3); - SASSERT(to.lt(1,2)); - SASSERT(to.lt(2,3)); + ENSURE(to.lt(1,2)); + ENSURE(to.lt(2,3)); } } @@ -75,7 +75,7 @@ void move_after(unsigned_vector & v, unsigned_vector & inv_v, unsigned a, unsign // std::cout << "move_after(" << a << ", " << b << ")\n"; unsigned pos_a = inv_v[a]; unsigned pos_b = inv_v[b]; - SASSERT(pos_a != pos_b); + ENSURE(pos_a != pos_b); if (pos_b < pos_a) { for (unsigned i = pos_b; i < pos_a; i++) { v[i] = v[i+1]; @@ -83,17 +83,17 @@ void move_after(unsigned_vector & v, unsigned_vector & inv_v, unsigned a, unsign } v[pos_a] = b; inv_v[b] = pos_a; - SASSERT(inv_v[b] == inv_v[a] + 1); + ENSURE(inv_v[b] == inv_v[a] + 1); } else { - SASSERT(pos_b > pos_a); + ENSURE(pos_b > pos_a); for (unsigned i = pos_b; i > pos_a + 1; i--) { v[i] = v[i-1]; inv_v[v[i-1]] = i; } v[pos_a+1] = b; inv_v[b] = pos_a+1; - SASSERT(inv_v[b] == inv_v[a] + 1); + ENSURE(inv_v[b] == inv_v[a] + 1); } // display(std::cout, v.begin(), v.end()); std::cout << std::endl; } @@ -118,8 +118,8 @@ static void tst4(unsigned sz, unsigned num_rounds) { move_after(v, inv_v, v1, v2); } for (unsigned k = 0; k < sz - 1; k++) { - SASSERT(inv_v[v[k]] == k); - SASSERT(to.lt(v[k], v[k+1])); + ENSURE(inv_v[v[k]] == k); + ENSURE(to.lt(v[k], v[k+1])); } if (i % 1000 == 0) { std::cout << "*"; diff --git a/src/test/udoc_relation.cpp b/src/test/udoc_relation.cpp index dc88e20af..57866c3ac 100644 --- a/src/test/udoc_relation.cpp +++ b/src/test/udoc_relation.cpp @@ -85,7 +85,7 @@ class udoc_tester { doc_ref result(dm); t = mk_rand_tbv(dm); result = dm.allocate(*t); - SASSERT(dm.tbvm().equals(*t, result->pos())); + ENSURE(dm.tbvm().equals(*t, result->pos())); for (unsigned i = 0; i < num_diff; ++i) { t = mk_rand_tbv(dm, result->pos()); if (dm.tbvm().equals(*t, result->pos())) { @@ -97,7 +97,7 @@ class udoc_tester { } result->neg().push_back(t.detach()); } - SASSERT(dm.well_formed(*result)); + ENSURE(dm.well_formed(*result)); return result.detach(); } @@ -121,7 +121,7 @@ public: } udoc_relation* mk_empty(relation_signature const& sig) { - SASSERT(p.can_handle_signature(sig)); + ENSURE(p.can_handle_signature(sig)); relation_base* empty = p.mk_empty(sig); return dynamic_cast(empty); } @@ -210,7 +210,7 @@ public: jc1.push_back(1); jc2.push_back(1); datalog::relation_join_fn* join_fn = p.mk_join_fn(*t1, *t2, jc1.size(), jc1.c_ptr(), jc2.c_ptr()); - SASSERT(join_fn); + ENSURE(join_fn); t = (*join_fn)(*t1, *t2); cr.verify_join(*t1, *t2, *t, jc1, jc2); t->display(std::cout); std::cout << "\n"; @@ -218,13 +218,13 @@ public: t = (*join_fn)(*t1, *t3); cr.verify_join(*t1, *t3, *t, jc1, jc2); - SASSERT(t->empty()); + ENSURE(t->empty()); t->display(std::cout); std::cout << "\n"; t->deallocate(); t = (*join_fn)(*t3, *t3); cr.verify_join(*t3, *t3, *t, jc1, jc2); - SASSERT(t->empty()); + ENSURE(t->empty()); t->display(std::cout); std::cout << "\n"; t->deallocate(); @@ -843,9 +843,9 @@ public: rel_union union_fn = p.mk_union_fn(r, r, 0); (*union_fn)(r, *full); doc_manager& dm = r.get_dm(); - SASSERT(r.get_udoc().size() == 1); + ENSURE(r.get_udoc().size() == 1); doc& d0 = r.get_udoc()[0]; - SASSERT(dm.is_full(d0)); + ENSURE(dm.is_full(d0)); for (unsigned i = 0; i < num_vals; ++i) { unsigned idx = m_rand(num_bits); unsigned val = m_rand(2); diff --git a/src/test/uint_set.cpp b/src/test/uint_set.cpp index fcbbd5c48..3134ada7b 100644 --- a/src/test/uint_set.cpp +++ b/src/test/uint_set.cpp @@ -44,91 +44,91 @@ static void tst1(unsigned n) { s2[idx] = false; s1.remove(idx); } - SASSERT(s1.num_elems() == size); - SASSERT((size == 0) == s1.empty()); + ENSURE(s1.num_elems() == size); + ENSURE((size == 0) == s1.empty()); for (unsigned idx = 0; idx < n; idx++) { - SASSERT(s2[idx] == s1.contains(idx)); + ENSURE(s2[idx] == s1.contains(idx)); } } } static void tst2(unsigned n) { uint_set s; - SASSERT(s.empty()); + ENSURE(s.empty()); unsigned val = rand()%n; s.insert(val); - SASSERT(!s.empty()); - SASSERT(s.num_elems() == 1); + ENSURE(!s.empty()); + ENSURE(s.num_elems() == 1); for (unsigned i = 0; i < 100; i++) { unsigned val2 = rand()%n; if (val != val2) { - SASSERT(!s.contains(val2)); + ENSURE(!s.contains(val2)); } } s.remove(val); - SASSERT(s.num_elems() == 0); - SASSERT(s.empty()); + ENSURE(s.num_elems() == 0); + ENSURE(s.empty()); } static void tst3(unsigned n) { - SASSERT(n > 10); + ENSURE(n > 10); uint_set s1; uint_set s2; - SASSERT(s1 == s2); + ENSURE(s1 == s2); s1.insert(3); - SASSERT(s1.num_elems() == 1); - SASSERT(s2.num_elems() == 0); - SASSERT(s1 != s2); + ENSURE(s1.num_elems() == 1); + ENSURE(s2.num_elems() == 0); + ENSURE(s1 != s2); s2.insert(5); - SASSERT(s2.num_elems() == 1); - SASSERT(s1 != s2); - SASSERT(!s1.subset_of(s2)); + ENSURE(s2.num_elems() == 1); + ENSURE(s1 != s2); + ENSURE(!s1.subset_of(s2)); s2 |= s1; - SASSERT(s1.subset_of(s2)); - SASSERT(s2.num_elems() == 2); - SASSERT(s1 != s2); + ENSURE(s1.subset_of(s2)); + ENSURE(s2.num_elems() == 2); + ENSURE(s1 != s2); s1 |= s2; - SASSERT(s1.subset_of(s2)); - SASSERT(s2.subset_of(s1)); - SASSERT(s1.num_elems() == 2); - SASSERT(s2.num_elems() == 2); - SASSERT(s1 == s2); + ENSURE(s1.subset_of(s2)); + ENSURE(s2.subset_of(s1)); + ENSURE(s1.num_elems() == 2); + ENSURE(s2.num_elems() == 2); + ENSURE(s1 == s2); s1.insert(9); - SASSERT(s1.num_elems() == 3); - SASSERT(s2.num_elems() == 2); + ENSURE(s1.num_elems() == 3); + ENSURE(s2.num_elems() == 2); s1.insert(9); - SASSERT(s1.num_elems() == 3); - SASSERT(s2.num_elems() == 2); - SASSERT(s2.subset_of(s1)); - SASSERT(!s1.subset_of(s2)); - SASSERT(s1 != s2); + ENSURE(s1.num_elems() == 3); + ENSURE(s2.num_elems() == 2); + ENSURE(s2.subset_of(s1)); + ENSURE(!s1.subset_of(s2)); + ENSURE(s1 != s2); uint_set s3(s1); - SASSERT(s1 == s3); - SASSERT(s1.subset_of(s3)); - SASSERT(s3.subset_of(s1)); - SASSERT(s2 != s3); + ENSURE(s1 == s3); + ENSURE(s1.subset_of(s3)); + ENSURE(s3.subset_of(s1)); + ENSURE(s2 != s3); uint_set s4(s2); - SASSERT(s2 == s4); - SASSERT(s2.subset_of(s4)); - SASSERT(s4.subset_of(s2)); - SASSERT(s2 != s3); + ENSURE(s2 == s4); + ENSURE(s2.subset_of(s4)); + ENSURE(s4.subset_of(s2)); + ENSURE(s2 != s3); for (unsigned i = 0; i < n; i++) { uint_set s5; s5.insert(i); - SASSERT(s1.contains(i) == s5.subset_of(s1)); + ENSURE(s1.contains(i) == s5.subset_of(s1)); } } static void tst4() { uint_set s; s.insert(32); - SASSERT(s.contains(32)); - SASSERT(!s.contains(31)); - SASSERT(!s.contains(0)); + ENSURE(s.contains(32)); + ENSURE(!s.contains(31)); + ENSURE(!s.contains(0)); s.remove(32); - SASSERT(!s.contains(32)); - SASSERT(!s.contains(31)); - SASSERT(!s.contains(0)); + ENSURE(!s.contains(32)); + ENSURE(!s.contains(31)); + ENSURE(!s.contains(0)); } #include "map.h" diff --git a/src/test/upolynomial.cpp b/src/test/upolynomial.cpp index e7dcf2719..4c8358b3a 100644 --- a/src/test/upolynomial.cpp +++ b/src/test/upolynomial.cpp @@ -101,10 +101,10 @@ static void tst_isolate_roots(polynomial_ref const & p, unsigned prec, mpbq_mana std::cout << "num. roots: " << roots.size() + lowers.size() << "\n"; std::cout << "sign var(-oo): " << um.sign_variations_at_minus_inf(sseq) << "\n"; std::cout << "sign var(+oo): " << um.sign_variations_at_plus_inf(sseq) << "\n"; - SASSERT(roots.size() + lowers.size() == um.sign_variations_at_minus_inf(sseq) - um.sign_variations_at_plus_inf(sseq)); + ENSURE(roots.size() + lowers.size() == um.sign_variations_at_minus_inf(sseq) - um.sign_variations_at_plus_inf(sseq)); std::cout << "roots:"; for (unsigned i = 0; i < roots.size(); i++) { - SASSERT(um.eval_sign_at(q.size(), q.c_ptr(), roots[i]) == 0); + ENSURE(um.eval_sign_at(q.size(), q.c_ptr(), roots[i]) == 0); std::cout << " "; bqm.display_decimal(std::cout, roots[i], prec); } { @@ -118,7 +118,7 @@ static void tst_isolate_roots(polynomial_ref const & p, unsigned prec, mpbq_mana bqm.display_decimal(std::cout, uppers[i], prec); std::cout << ")"; // Check interval with Sturm sequence. Small detail: Sturm sequence is for close intervals. - SASSERT(um.eval_sign_at(q.size(), q.c_ptr(), lowers[i]) == 0 || + ENSURE(um.eval_sign_at(q.size(), q.c_ptr(), lowers[i]) == 0 || um.eval_sign_at(q.size(), q.c_ptr(), uppers[i]) == 0 || um.sign_variations_at(sseq, lowers[i]) - um.sign_variations_at(sseq, uppers[i]) == 1); // Fourier sequence may also be used to check if the interval is isolating @@ -129,18 +129,18 @@ static void tst_isolate_roots(polynomial_ref const & p, unsigned prec, mpbq_mana tout << "fourier upper: " << um.sign_variations_at(fseq, uppers[i]) << "\n";); unsigned fsv_lower = um.sign_variations_at(fseq, lowers[i]); unsigned fsv_upper = um.sign_variations_at(fseq, uppers[i]); - SASSERT(um.eval_sign_at(q.size(), q.c_ptr(), lowers[i]) == 0 || - um.eval_sign_at(q.size(), q.c_ptr(), uppers[i]) == 0 || + VERIFY(um.eval_sign_at(q.size(), q.c_ptr(), lowers[i]) == 0 || + um.eval_sign_at(q.size(), q.c_ptr(), uppers[i]) == 0 || // fsv_lower - fsv_upper is an upper bound for the number of roots in the interval // fsv_upper - fsv_upper - num_roots is even // Recall that num_roots == 1 in the interval. - (fsv_lower - fsv_upper >= 1 && (fsv_lower - fsv_upper - 1) % 2 == 0)); - + (fsv_lower - fsv_upper >= 1 && (fsv_lower - fsv_upper - 1) % 2 == 0)); + // Double checking using Descartes bounds for the interval // Must use square free component. unsigned dab = um.descartes_bound_a_b(q_sqf.size(), q_sqf.c_ptr(), bqm, lowers[i], uppers[i]); TRACE("upolynomial", tout << "Descartes bound: " << dab << "\n";); - SASSERT(dab == 1); + VERIFY(dab == 1); } } std::cout << "\n"; @@ -155,7 +155,7 @@ static void tst_isolate_roots(polynomial_ref const & p, unsigned prec = 5) { } static void check_roots(mpbq_vector const & roots, mpbq_vector const & lowers, mpbq_vector const & uppers, unsigned expected_sz, rational const * expected_roots) { - SASSERT(expected_sz == roots.size() + lowers.size()); + ENSURE(expected_sz == roots.size() + lowers.size()); svector visited; visited.resize(expected_sz, false); for (unsigned i = 0; i < expected_sz; i++) { @@ -163,8 +163,8 @@ static void check_roots(mpbq_vector const & roots, mpbq_vector const & lowers, m bool found = false; for (unsigned j = 0; j < roots.size(); j++) { if (to_rational(roots[j]) == r) { - SASSERT(!visited[j]); - SASSERT(!found); + ENSURE(!visited[j]); + VERIFY(!found); found = true; visited[j] = true; } @@ -172,13 +172,13 @@ static void check_roots(mpbq_vector const & roots, mpbq_vector const & lowers, m for (unsigned j = 0; j < lowers.size(); j++) { unsigned j_prime = j + roots.size(); if (to_rational(lowers[j]) < r && r < to_rational(uppers[j])) { - SASSERT(!found); - SASSERT(!visited[j_prime]); + VERIFY(!found); + ENSURE(!visited[j_prime]); found = true; visited[j_prime] = true; } } - SASSERT(found); + ENSURE(found); } } @@ -292,21 +292,21 @@ static void tst_remove_one_half() { upolynomial::scoped_numeral_vector _p(um), _q(um), _r(um); um.to_numeral_vector(p, _p); um.to_numeral_vector(r, _r); - SASSERT(um.has_one_half_root(_p.size(), _p.c_ptr())); + ENSURE(um.has_one_half_root(_p.size(), _p.c_ptr())); um.remove_one_half_root(_p.size(), _p.c_ptr(), _q); - SASSERT(!um.has_one_half_root(_q.size(), _q.c_ptr())); + ENSURE(!um.has_one_half_root(_q.size(), _q.c_ptr())); std::cout << "_p: "; um.display(std::cout, _p); std::cout << "\n"; std::cout << "_r: "; um.display(std::cout, _r); std::cout << "\n"; std::cout << "_q: "; um.display(std::cout, _q); std::cout << "\n"; - SASSERT(um.eq(_q, _r)); + ENSURE(um.eq(_q, _r)); p = (((x^5) - 1000000000)^3)*((3*x - 10000000)^2)*((10*x - 632)^2); um.to_numeral_vector(p, _p); - SASSERT(!um.has_one_half_root(_p.size(), _p.c_ptr())); + ENSURE(!um.has_one_half_root(_p.size(), _p.c_ptr())); p = (x - 2)*(x - 4)*(x - 8)*(x - 16)*(x - 32)*(x - 64)*(2*x - 1)*(4*x - 1)*(8*x - 1)*(16*x - 1)*(32*x - 1); um.to_numeral_vector(p, _p); - SASSERT(um.has_one_half_root(_p.size(), _p.c_ptr())); + ENSURE(um.has_one_half_root(_p.size(), _p.c_ptr())); } template @@ -499,11 +499,11 @@ static void tst_refinable(polynomial_ref const & p, mpbq_manager & bqm, mpbq & a std::cout << "new (" << bqm.to_string(a) << ", " << bqm.to_string(b) << ")\n"; int sign_a = um.eval_sign_at(_p.size(), _p.c_ptr(), a); int sign_b = um.eval_sign_at(_p.size(), _p.c_ptr(), b); - SASSERT(sign_a != 0 && sign_b != 0 && sign_a == -sign_b); + VERIFY(sign_a != 0 && sign_b != 0 && sign_a == -sign_b); } else { std::cout << "new root: " << bqm.to_string(a) << "\n"; - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), a) == 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), a) == 0); } } @@ -608,13 +608,13 @@ static void tst_translate_q() { upolynomial::manager um(rl, nm); upolynomial::scoped_numeral_vector _p(um), _q(um); um.to_numeral_vector(p, _p); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(1)) == 0); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(2)) == 0); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(3)) == 0); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(4)) == 0); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(-1)) != 0); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(5)) != 0); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(-2)) != 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(1)) == 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(2)) == 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(3)) == 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(4)) == 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(-1)) != 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(5)) != 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(-2)) != 0); scoped_mpq c(nm); nm.set(c, 1, 3); scoped_mpq r1(nm); @@ -623,32 +623,32 @@ static void tst_translate_q() { scoped_mpq r2(nm); r2 = 3; r2 -= c; - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), r1) != 0); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), r2) != 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), r1) != 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), r2) != 0); std::cout << "p: "; um.display(std::cout, _p); std::cout << "\n"; um.translate_q(_p.size(), _p.c_ptr(), c, _q); std::cout << "q: "; um.display(std::cout, _q); std::cout << "\n"; - SASSERT(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(1)) != 0); - SASSERT(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(2)) != 0); - SASSERT(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(3)) != 0); - SASSERT(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(4)) != 0); - SASSERT(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(-1)) != 0); - SASSERT(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(5)) != 0); - SASSERT(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(-2)) != 0); - SASSERT(um.eval_sign_at(_q.size(), _q.c_ptr(), r1) == 0); - SASSERT(um.eval_sign_at(_q.size(), _q.c_ptr(), r2) == 0); + ENSURE(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(1)) != 0); + ENSURE(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(2)) != 0); + ENSURE(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(3)) != 0); + ENSURE(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(4)) != 0); + ENSURE(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(-1)) != 0); + ENSURE(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(5)) != 0); + ENSURE(um.eval_sign_at(_q.size(), _q.c_ptr(), mpq(-2)) != 0); + ENSURE(um.eval_sign_at(_q.size(), _q.c_ptr(), r1) == 0); + ENSURE(um.eval_sign_at(_q.size(), _q.c_ptr(), r2) == 0); um.p_1_div_x(_p.size(), _p.c_ptr()); std::cout << "p: "; um.display(std::cout, _p); std::cout << "\n"; - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(1)) == 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(1)) == 0); nm.set(c, 1, 2); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), c) == 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), c) == 0); nm.set(c, 1, 3); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), c) == 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), c) == 0); nm.set(c, 1, 4); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), c) == 0); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(2)) != 0); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(3)) != 0); - SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(4)) != 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), c) == 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(2)) != 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(3)) != 0); + ENSURE(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(4)) != 0); } static void tst_convert_q2bq(unsynch_mpq_manager & m, polynomial_ref const & p, mpq const & a, mpq const & b) { @@ -848,9 +848,9 @@ static void tst_exact_div(polynomial_ref const & p1, polynomial_ref const & p2, std::cout << "expected: "; um.display(std::cout, _q); std::cout << "\n"; } std::cout.flush(); - SASSERT(res == expected); - SASSERT(expected == um.divides(_p1.size(), _p1.c_ptr(), _p2.size(), _p2.c_ptr())); - SASSERT(!expected || um.eq(_r, _q)); + ENSURE(res == expected); + ENSURE(expected == um.divides(_p1.size(), _p1.c_ptr(), _p2.size(), _p2.c_ptr())); + ENSURE(!expected || um.eq(_r, _q)); } static void tst_exact_div() { @@ -878,7 +878,7 @@ static void tst_exact_div() { } static void tst_fact(polynomial_ref const & p, unsigned num_distinct_factors, upolynomial::factor_params const & params = upolynomial::factor_params()) { - SASSERT(is_univariate(p)); + ENSURE(is_univariate(p)); std::cout << "---------------\n"; std::cout << "p: " << p << std::endl; reslimit rl; upolynomial::manager um(rl, p.m().m()); @@ -891,11 +891,11 @@ static void tst_fact(polynomial_ref const & p, unsigned num_distinct_factors, up for (unsigned i = 0; i < fs.distinct_factors(); i++) { std::cout << "*("; um.display(std::cout, fs[i]); std::cout << ")^" << fs.get_degree(i) << std::endl; } - SASSERT(fs.distinct_factors() == num_distinct_factors); + ENSURE(fs.distinct_factors() == num_distinct_factors); upolynomial::scoped_numeral_vector _r(um); fs.multiply(_r); TRACE("upolynomial", tout << "_r: "; um.display(tout, _r); tout << "\n_p: "; um.display(tout, _p); tout << "\n";); - SASSERT(um.eq(_p, _r)); + ENSURE(um.eq(_p, _r)); } static void tst_fact() { @@ -992,8 +992,8 @@ static void tst_fact() { } static void tst_rem(polynomial_ref const & p, polynomial_ref const & q, polynomial_ref const & expected) { - SASSERT(is_univariate(p)); - SASSERT(is_univariate(q)); + ENSURE(is_univariate(p)); + ENSURE(is_univariate(q)); std::cout << "---------------\n"; std::cout << "p: " << p << std::endl; std::cout << "q: " << q << std::endl; @@ -1005,7 +1005,7 @@ static void tst_rem(polynomial_ref const & p, polynomial_ref const & q, polynomi polynomial_ref r(p.m()); r = p.m().to_polynomial(_r.size(), _r.c_ptr(), 0); std::cout << "r: " << r << std::endl; - SASSERT(eq(expected, r)); + ENSURE(eq(expected, r)); } static void tst_rem() { @@ -1022,7 +1022,7 @@ static void tst_rem() { } static void tst_lower_bound(polynomial_ref const & p) { - SASSERT(is_univariate(p)); + ENSURE(is_univariate(p)); std::cout << "---------------\n"; std::cout << "p: " << p << std::endl; reslimit rl; upolynomial::manager um(rl, p.m().m()); diff --git a/src/test/var_subst.cpp b/src/test/var_subst.cpp index e82c09218..f90292d11 100644 --- a/src/test/var_subst.cpp +++ b/src/test/var_subst.cpp @@ -87,7 +87,7 @@ void tst_subst(ast_manager& m) { std::cout << mk_pp(e2, m) << "\n"; std::cout << mk_pp(e3, m) << "\n"; std::cout << mk_pp(t1, m) << "\n"; - SASSERT(e3.get() == t1.get()); + ENSURE(e3.get() == t1.get()); // replace #2 -> #3, #3 -> #2 e2 = m.mk_forall(2, ss, names, e1); @@ -95,7 +95,7 @@ void tst_subst(ast_manager& m) { std::cout << mk_pp(e2, m) << "\n"; std::cout << mk_pp(e3, m) << "\n"; std::cout << mk_pp(t2, m) << "\n"; - SASSERT(e3.get() == t2.get()); + ENSURE(e3.get() == t2.get()); } diff --git a/src/test/vector.cpp b/src/test/vector.cpp index 86ae997ca..f7d70a87b 100644 --- a/src/test/vector.cpp +++ b/src/test/vector.cpp @@ -20,28 +20,28 @@ Revision History: static void tst1() { svector v1; - SASSERT(v1.empty()); + ENSURE(v1.empty()); for (unsigned i = 0; i < 1000; i++) { v1.push_back(i + 3); - SASSERT(static_cast(v1[i]) == i + 3); - SASSERT(v1.capacity() >= v1.size()); - SASSERT(!v1.empty()); + ENSURE(static_cast(v1[i]) == i + 3); + ENSURE(v1.capacity() >= v1.size()); + ENSURE(!v1.empty()); } for (unsigned i = 0; i < 1000; i++) { - SASSERT(static_cast(v1[i]) == i + 3); + ENSURE(static_cast(v1[i]) == i + 3); } svector::iterator it = v1.begin(); svector::iterator end = v1.end(); for (int i = 0; it != end; ++it, ++i) { - SASSERT(*it == i + 3); + ENSURE(*it == i + 3); } for (unsigned i = 0; i < 1000; i++) { - SASSERT(static_cast(v1.back()) == 1000 - i - 1 + 3); - SASSERT(v1.size() == 1000 - i); + ENSURE(static_cast(v1.back()) == 1000 - i - 1 + 3); + ENSURE(v1.size() == 1000 - i); v1.pop_back(); } - SASSERT(v1.empty()); - SASSERT(v1.size() == 0); + ENSURE(v1.empty()); + ENSURE(v1.size() == 0); unsigned i = 1000000000; while (true) { std::cout << "resize " << i << "\n"; diff --git a/contrib/cmake/src/util/CMakeLists.txt b/src/util/CMakeLists.txt similarity index 87% rename from contrib/cmake/src/util/CMakeLists.txt rename to src/util/CMakeLists.txt index b76f909d0..7ed68c89f 100644 --- a/contrib/cmake/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -59,4 +59,13 @@ z3_add_component(util util.cpp warning.cpp z3_exception.cpp + EXTRA_REGISTER_MODULE_HEADERS + env_params.h + MEMORY_INIT_FINALIZER_HEADERS + debug.h + gparams.h + prime_generator.h + rational.h + symbol.h + trace.h ) diff --git a/src/util/debug.h b/src/util/debug.h index 6e295dcaa..ec0f600b5 100644 --- a/src/util/debug.h +++ b/src/util/debug.h @@ -79,14 +79,10 @@ bool is_debug_enabled(const char * tag); #define NOT_IMPLEMENTED_YET() { std::cerr << "NOT IMPLEMENTED YET!\n"; UNREACHABLE(); exit(ERR_NOT_IMPLEMENTED_YET); } ((void) 0) -#ifdef Z3DEBUG #define VERIFY(_x_) if (!(_x_)) { \ std::cerr << "Failed to verify: " << #_x_ << "\n"; \ UNREACHABLE(); \ } -#else -#define VERIFY(_x_) (void)(_x_) -#endif #define ENSURE(_x_) \ if (!(_x_)) { \ diff --git a/src/util/heap.h b/src/util/heap.h index e8964a4f0..14e902648 100644 --- a/src/util/heap.h +++ b/src/util/heap.h @@ -43,7 +43,15 @@ class heap : private LT { return i >> 1; } -#ifdef Z3DEBUG + void display(std::ostream& out, unsigned indent, int idx) const { + if (idx < static_cast(m_values.size())) { + for (unsigned i = 0; i < indent; ++i) out << " "; + out << m_values[idx] << "\n"; + display(out, indent + 1, left(idx)); + display(out, indent + 1, right(idx)); + } + } + // Return true if the value can be inserted in the heap. That is, the vector m_value2indices is big enough to store this value. bool is_valid_value(int v) const { SASSERT(v >= 0 && v < static_cast(m_value2indices.size())); @@ -59,11 +67,13 @@ class heap : private LT { } return true; } + + public: bool check_invariant() const { return check_invariant_core(1); } -#endif + private: void move_up(int idx) { @@ -219,6 +229,7 @@ public: void insert(int val) { CASSERT("heap", check_invariant()); + CASSERT("heap", !contains(val)); SASSERT(is_valid_value(val)); int idx = static_cast(m_values.size()); m_value2indices[val] = idx; @@ -272,6 +283,11 @@ public: } } } + + void display(std::ostream& out) const { + display(out, 0, 1); + } + }; diff --git a/contrib/cmake/src/util/lp/CMakeLists.txt b/src/util/lp/CMakeLists.txt similarity index 98% rename from contrib/cmake/src/util/lp/CMakeLists.txt rename to src/util/lp/CMakeLists.txt index e33764f69..72c2482bb 100644 --- a/contrib/cmake/src/util/lp/CMakeLists.txt +++ b/src/util/lp/CMakeLists.txt @@ -8,6 +8,7 @@ z3_add_component(lp dense_matrix_instances.cpp eta_matrix_instances.cpp indexed_vector_instances.cpp + int_solver.cpp lar_solver_instances.cpp lar_core_solver_instances.cpp lp_core_solver_base_instances.cpp diff --git a/src/util/lp/binary_heap_priority_queue.h b/src/util/lp/binary_heap_priority_queue.h index a6206948c..04faefd5b 100644 --- a/src/util/lp/binary_heap_priority_queue.h +++ b/src/util/lp/binary_heap_priority_queue.h @@ -7,7 +7,7 @@ #include "util/vector.h" #include "util/debug.h" #include "util/lp/lp_utils.h" -namespace lean { +namespace lp { // the elements with the smallest priority are dequeued first template class binary_heap_priority_queue { @@ -60,7 +60,7 @@ public: /// return the first element of the queue and removes it from the queue unsigned dequeue(); unsigned peek() const { - lean_assert(m_heap_size > 0); + lp_assert(m_heap_size > 0); return m_heap[1]; } #ifdef LEAN_DEBUG diff --git a/src/util/lp/binary_heap_priority_queue.hpp b/src/util/lp/binary_heap_priority_queue.hpp index 440b45b02..d6d9a5358 100644 --- a/src/util/lp/binary_heap_priority_queue.hpp +++ b/src/util/lp/binary_heap_priority_queue.hpp @@ -4,7 +4,7 @@ */ #include "util/vector.h" #include "util/lp/binary_heap_priority_queue.h" -namespace lean { +namespace lp { // is is the child place in heap template void binary_heap_priority_queue::swap_with_parent(unsigned i) { unsigned parent = m_heap[i >> 1]; @@ -33,8 +33,8 @@ template void binary_heap_priority_queue::decrease_priority(unsi template bool binary_heap_priority_queue::is_consistent() const { for (int i = 0; i < m_heap_inverse.size(); i++) { int i_index = m_heap_inverse[i]; - lean_assert(i_index <= static_cast(m_heap_size)); - lean_assert(i_index == -1 || m_heap[i_index] == i); + lp_assert(i_index <= static_cast(m_heap_size)); + lp_assert(i_index == -1 || m_heap[i_index] == i); } for (unsigned i = 1; i < m_heap_size; i++) { unsigned ch = i << 1; @@ -55,7 +55,7 @@ template void binary_heap_priority_queue::remove(unsigned o) { if (o_in_heap == -1) { return; // nothing to do } - lean_assert(static_cast(o_in_heap) <= m_heap_size); + lp_assert(static_cast(o_in_heap) <= m_heap_size); if (static_cast(o_in_heap) < m_heap_size) { put_at(o_in_heap, m_heap[m_heap_size--]); if (m_priorities[m_heap[o_in_heap]] > priority_of_o) { @@ -72,11 +72,11 @@ template void binary_heap_priority_queue::remove(unsigned o) { } } } else { - lean_assert(static_cast(o_in_heap) == m_heap_size); + lp_assert(static_cast(o_in_heap) == m_heap_size); m_heap_size--; } m_heap_inverse[o] = -1; - // lean_assert(is_consistent()); + // lp_assert(is_consistent()); } // n is the initial queue capacity. // The capacity will be enlarged two times automatically if needed @@ -102,7 +102,7 @@ template void binary_heap_priority_queue::put_to_heap(unsigned i template void binary_heap_priority_queue::enqueue_new(unsigned o, const T& priority) { m_heap_size++; int i = m_heap_size; - lean_assert(o < m_priorities.size()); + lp_assert(o < m_priorities.size()); m_priorities[o] = priority; put_at(i, o); while (i > 1 && m_priorities[m_heap[i >> 1]] > priority) { @@ -134,7 +134,7 @@ template void binary_heap_priority_queue::change_priority_for_ex /// return the first element of the queue and removes it from the queue template unsigned binary_heap_priority_queue::dequeue_and_get_priority(T & priority) { - lean_assert(m_heap_size != 0); + lp_assert(m_heap_size != 0); int ret = m_heap[1]; priority = m_priorities[ret]; put_the_last_at_the_top_and_fix_the_heap(); @@ -168,7 +168,7 @@ template void binary_heap_priority_queue::put_the_last_at_the_to } /// return the first element of the queue and removes it from the queue template unsigned binary_heap_priority_queue::dequeue() { - lean_assert(m_heap_size > 0); + lp_assert(m_heap_size > 0); int ret = m_heap[1]; put_the_last_at_the_top_and_fix_the_heap(); m_heap_inverse[ret] = -1; diff --git a/src/util/lp/binary_heap_priority_queue_instances.cpp b/src/util/lp/binary_heap_priority_queue_instances.cpp index 567494d6f..12b853fc8 100644 --- a/src/util/lp/binary_heap_priority_queue_instances.cpp +++ b/src/util/lp/binary_heap_priority_queue_instances.cpp @@ -4,7 +4,7 @@ */ #include "util/lp/numeric_pair.h" #include "util/lp/binary_heap_priority_queue.hpp" -namespace lean { +namespace lp { template binary_heap_priority_queue::binary_heap_priority_queue(unsigned int); template unsigned binary_heap_priority_queue::dequeue(); template void binary_heap_priority_queue::enqueue(unsigned int, int const&); @@ -16,11 +16,11 @@ template unsigned binary_heap_priority_queue::dequeue(); template unsigned binary_heap_priority_queue::dequeue(); template void binary_heap_priority_queue >::enqueue(unsigned int, numeric_pair const&); template void binary_heap_priority_queue >::resize(unsigned int); -template void lean::binary_heap_priority_queue::resize(unsigned int); +template void lp::binary_heap_priority_queue::resize(unsigned int); template binary_heap_priority_queue::binary_heap_priority_queue(unsigned int); template void binary_heap_priority_queue::resize(unsigned int); template unsigned binary_heap_priority_queue::dequeue(); template void binary_heap_priority_queue::enqueue(unsigned int, unsigned int const&); template void binary_heap_priority_queue::remove(unsigned int); -template void lean::binary_heap_priority_queue::resize(unsigned int); +template void lp::binary_heap_priority_queue::resize(unsigned int); } diff --git a/src/util/lp/binary_heap_upair_queue.h b/src/util/lp/binary_heap_upair_queue.h index 26cfd5532..ec7f4e85f 100644 --- a/src/util/lp/binary_heap_upair_queue.h +++ b/src/util/lp/binary_heap_upair_queue.h @@ -15,7 +15,7 @@ typedef std::pair upair; -namespace lean { +namespace lp { template class binary_heap_upair_queue { binary_heap_priority_queue m_q; diff --git a/src/util/lp/binary_heap_upair_queue.hpp b/src/util/lp/binary_heap_upair_queue.hpp index a48bdb5b7..2a162fa06 100644 --- a/src/util/lp/binary_heap_upair_queue.hpp +++ b/src/util/lp/binary_heap_upair_queue.hpp @@ -6,7 +6,7 @@ #include #include "util/lp/lp_utils.h" #include "util/lp/binary_heap_upair_queue.h" -namespace lean { +namespace lp { template binary_heap_upair_queue::binary_heap_upair_queue(unsigned size) : m_q(size), m_pairs(size) { for (unsigned i = 0; i < size; i++) m_available_spots.push_back(i); @@ -14,7 +14,7 @@ template binary_heap_upair_queue::binary_heap_upair_queue(unsign template unsigned binary_heap_upair_queue::dequeue_available_spot() { - lean_assert(m_available_spots.empty() == false); + lp_assert(m_available_spots.empty() == false); unsigned ret = m_available_spots.back(); m_available_spots.pop_back(); return ret; @@ -54,7 +54,7 @@ template void binary_heap_upair_queue::enqueue(unsigned i, unsig m_pairs.resize(new_size); } ij_index = dequeue_available_spot(); - // lean_assert(ij_index void binary_heap_upair_queue::enqueue(unsigned i, unsig } template void binary_heap_upair_queue::dequeue(unsigned & i, unsigned &j) { - lean_assert(!m_q.is_empty()); + lp_assert(!m_q.is_empty()); unsigned ij_index = m_q.dequeue(); upair & p = m_pairs[ij_index]; i = p.first; diff --git a/src/util/lp/binary_heap_upair_queue_instances.cpp b/src/util/lp/binary_heap_upair_queue_instances.cpp index 4c4603110..d315e9bda 100644 --- a/src/util/lp/binary_heap_upair_queue_instances.cpp +++ b/src/util/lp/binary_heap_upair_queue_instances.cpp @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #include "util/lp/binary_heap_upair_queue.hpp" -namespace lean { +namespace lp { template binary_heap_upair_queue::binary_heap_upair_queue(unsigned int); template binary_heap_upair_queue::binary_heap_upair_queue(unsigned int); template unsigned binary_heap_upair_queue::dequeue_available_spot(); diff --git a/src/util/lp/bound_analyzer_on_row.h b/src/util/lp/bound_analyzer_on_row.h index 508692e5a..45f5288b1 100644 --- a/src/util/lp/bound_analyzer_on_row.h +++ b/src/util/lp/bound_analyzer_on_row.h @@ -13,7 +13,7 @@ // We try to pin a var by pushing the total by using the variable bounds // In a loop we drive the partial sum down, denoting the variables of this process by _u. // In the same loop trying to pin variables by pushing the partial sum up, denoting the variable related to it by _l -namespace lean { +namespace lp { class bound_analyzer_on_row { @@ -91,11 +91,11 @@ public : } const impq & ub(unsigned j) const { - lean_assert(upper_bound_is_available(j)); + lp_assert(upper_bound_is_available(j)); return m_bp.get_upper_bound(j); } const impq & lb(unsigned j) const { - lean_assert(low_bound_is_available(j)); + lp_assert(low_bound_is_available(j)); return m_bp.get_low_bound(j); } @@ -153,7 +153,7 @@ public : void limit_all_monoids_from_above() { int strict = 0; mpq total; - lean_assert(is_zero(total)); + lp_assert(is_zero(total)); m_it.reset(); mpq a; unsigned j; while (m_it.next(a, j)) { @@ -180,7 +180,7 @@ public : void limit_all_monoids_from_below() { int strict = 0; mpq total; - lean_assert(is_zero(total)); + lp_assert(is_zero(total)); m_it.reset(); mpq a; unsigned j; while (m_it.next(a, j)) { @@ -272,7 +272,7 @@ public : // mpq a; unsigned j; // while (it->next(a, j)) { // if (be.m_j == j) continue; - // lean_assert(bound_is_available(j, is_neg(a) ? low_bound : !low_bound)); + // lp_assert(bound_is_available(j, is_neg(a) ? low_bound : !low_bound)); // be.m_vector_of_bound_signatures.emplace_back(a, j, numeric_traits:: // is_neg(a)? low_bound: !low_bound); // } diff --git a/src/util/lp/bound_propagator.cpp b/src/util/lp/bound_propagator.cpp index 0d58ec2be..cfb3aa68f 100644 --- a/src/util/lp/bound_propagator.cpp +++ b/src/util/lp/bound_propagator.cpp @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #include "util/lp/lar_solver.h" -namespace lean { +namespace lp { bound_propagator::bound_propagator(lar_solver & ls): m_lar_solver(ls) {} column_type bound_propagator::get_column_type(unsigned j) const { diff --git a/src/util/lp/bound_propagator.h b/src/util/lp/bound_propagator.h index 92523d75f..2ef0856fd 100644 --- a/src/util/lp/bound_propagator.h +++ b/src/util/lp/bound_propagator.h @@ -4,7 +4,7 @@ */ #pragma once #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { class lar_solver; class bound_propagator { std::unordered_map m_improved_low_bounds; // these maps map a column index to the corresponding index in ibounds @@ -19,7 +19,7 @@ public: const impq & get_upper_bound(unsigned) const; void try_add_bound(const mpq & v, unsigned j, bool is_low, bool coeff_before_j_is_pos, unsigned row_or_term_index, bool strict); virtual bool bound_is_interesting(unsigned vi, - lean::lconstraint_kind kind, + lp::lconstraint_kind kind, const rational & bval) {return true;} unsigned number_of_found_bounds() const { return m_ibounds.size(); } virtual void consume(mpq const& v, unsigned j) { std::cout << "doh\n"; } diff --git a/src/util/lp/breakpoint.h b/src/util/lp/breakpoint.h index e5454db0e..ff3a03e94 100644 --- a/src/util/lp/breakpoint.h +++ b/src/util/lp/breakpoint.h @@ -5,7 +5,7 @@ #pragma once -namespace lean { +namespace lp { enum breakpoint_type { low_break, upper_break, fixed_break }; diff --git a/src/util/lp/column_info.h b/src/util/lp/column_info.h index 56e75a1fb..02c2f638b 100644 --- a/src/util/lp/column_info.h +++ b/src/util/lp/column_info.h @@ -9,7 +9,7 @@ #include #include #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { inline bool is_valid(unsigned j) { return static_cast(j) >= 0;} template @@ -100,11 +100,11 @@ public: } T get_low_bound() const { - lean_assert(m_low_bound_is_set); + lp_assert(m_low_bound_is_set); return m_low_bound; } T get_upper_bound() const { - lean_assert(m_upper_bound_is_set); + lp_assert(m_upper_bound_is_set); return m_upper_bound; } @@ -156,7 +156,7 @@ public: } T get_fixed_value() const { - lean_assert(m_is_fixed); + lp_assert(m_is_fixed); return m_fixed_value; } diff --git a/src/util/lp/column_namer.h b/src/util/lp/column_namer.h index 1a10a5a23..66b6a55db 100644 --- a/src/util/lp/column_namer.h +++ b/src/util/lp/column_namer.h @@ -5,7 +5,7 @@ */ #include #include "util/lp/linear_combination_iterator.h" -namespace lean { +namespace lp { class column_namer { public: virtual std::string get_column_name(unsigned j) const = 0; @@ -15,7 +15,7 @@ public: T a; unsigned i; while (it->next(a, i)) { - coeff.emplace_back(a, i); + coeff.push_back(std::make_pair(a, i)); } print_linear_combination_of_column_indices(coeff, out); } diff --git a/src/util/lp/conversion_helper.h b/src/util/lp/conversion_helper.h index bff2ad563..cd8577483 100644 --- a/src/util/lp/conversion_helper.h +++ b/src/util/lp/conversion_helper.h @@ -4,7 +4,7 @@ Author: Lev Nachmanson */ #pragma once -namespace lean { +namespace lp { template struct conversion_helper { static V get_low_bound(const column_info & ci) { diff --git a/src/util/lp/core_solver_pretty_printer.h b/src/util/lp/core_solver_pretty_printer.h index 2a3a14b31..cf4caf19d 100644 --- a/src/util/lp/core_solver_pretty_printer.h +++ b/src/util/lp/core_solver_pretty_printer.h @@ -10,7 +10,7 @@ #include #include "util/lp/lp_settings.h" #include "util/lp/indexed_vector.h" -namespace lean { +namespace lp { template class lp_core_solver_base; // forward definition template diff --git a/src/util/lp/core_solver_pretty_printer.hpp b/src/util/lp/core_solver_pretty_printer.hpp index 786b8b3a1..8890f8c20 100644 --- a/src/util/lp/core_solver_pretty_printer.hpp +++ b/src/util/lp/core_solver_pretty_printer.hpp @@ -9,7 +9,7 @@ #include "util/lp/lp_core_solver_base.h" #include "util/lp/core_solver_pretty_printer.h" #include "util/lp/numeric_pair.h" -namespace lean { +namespace lp { template @@ -148,7 +148,7 @@ template void core_solver_pretty_printer::adjust_ case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); break; } } @@ -357,7 +357,7 @@ template void core_solver_pretty_printer::print_g unsigned width = m_column_widths[col]; string s = row[col]; int number_of_blanks = width - static_cast(s.size()); - lean_assert(number_of_blanks >= 0); + lp_assert(number_of_blanks >= 0); print_blanks(number_of_blanks, m_out); m_out << s << ' '; if (col < row.size() - 1) { @@ -368,7 +368,7 @@ template void core_solver_pretty_printer::print_g string rs = T_to_string(rst); int nb = m_rs_width - static_cast(rs.size()); - lean_assert(nb >= 0); + lp_assert(nb >= 0); print_blanks(nb + 1, m_out); m_out << rs << std::endl; } diff --git a/src/util/lp/core_solver_pretty_printer_instances.cpp b/src/util/lp/core_solver_pretty_printer_instances.cpp index cfa72f725..e3801228c 100644 --- a/src/util/lp/core_solver_pretty_printer_instances.cpp +++ b/src/util/lp/core_solver_pretty_printer_instances.cpp @@ -4,12 +4,12 @@ */ #include "util/lp/numeric_pair.h" #include "util/lp/core_solver_pretty_printer.hpp" -template lean::core_solver_pretty_printer::core_solver_pretty_printer(lean::lp_core_solver_base &, std::ostream & out); -template void lean::core_solver_pretty_printer::print(); -template lean::core_solver_pretty_printer::~core_solver_pretty_printer(); -template lean::core_solver_pretty_printer::core_solver_pretty_printer(lean::lp_core_solver_base &, std::ostream & out); -template void lean::core_solver_pretty_printer::print(); -template lean::core_solver_pretty_printer::~core_solver_pretty_printer(); -template lean::core_solver_pretty_printer >::core_solver_pretty_printer(lean::lp_core_solver_base > &, std::ostream & out); -template lean::core_solver_pretty_printer >::~core_solver_pretty_printer(); -template void lean::core_solver_pretty_printer >::print(); +template lp::core_solver_pretty_printer::core_solver_pretty_printer(lp::lp_core_solver_base &, std::ostream & out); +template void lp::core_solver_pretty_printer::print(); +template lp::core_solver_pretty_printer::~core_solver_pretty_printer(); +template lp::core_solver_pretty_printer::core_solver_pretty_printer(lp::lp_core_solver_base &, std::ostream & out); +template void lp::core_solver_pretty_printer::print(); +template lp::core_solver_pretty_printer::~core_solver_pretty_printer(); +template lp::core_solver_pretty_printer >::core_solver_pretty_printer(lp::lp_core_solver_base > &, std::ostream & out); +template lp::core_solver_pretty_printer >::~core_solver_pretty_printer(); +template void lp::core_solver_pretty_printer >::print(); diff --git a/src/util/lp/dense_matrix.h b/src/util/lp/dense_matrix.h index 233f74016..6f2f54338 100644 --- a/src/util/lp/dense_matrix.h +++ b/src/util/lp/dense_matrix.h @@ -6,7 +6,7 @@ #ifdef LEAN_DEBUG #include "util/vector.h" #include "util/lp/matrix.h" -namespace lean { +namespace lp { // used for debugging purposes only template class dense_matrix: public matrix { @@ -31,7 +31,7 @@ public: dense_matrix(unsigned m, unsigned n); dense_matrix operator*=(matrix const & a) { - lean_assert(column_count() == a.row_count()); + lp_assert(column_count() == a.row_count()); dense_matrix c(row_count(), a.column_count()); for (unsigned i = 0; i < row_count(); i++) { for (unsigned j = 0; j < a.column_count(); j++) { diff --git a/src/util/lp/dense_matrix.hpp b/src/util/lp/dense_matrix.hpp index e42d9e3a4..8850d4f74 100644 --- a/src/util/lp/dense_matrix.hpp +++ b/src/util/lp/dense_matrix.hpp @@ -7,7 +7,7 @@ #include "util/vector.h" #include "util/lp/numeric_pair.h" #include "util/lp/dense_matrix.h" -namespace lean { +namespace lp { template void print_vector(const vector & t, std::ostream & out); template dense_matrix::dense_matrix(unsigned m, unsigned n) : m_m(m), m_n(n), m_values(m * n, numeric_traits::zero()) { } @@ -170,7 +170,7 @@ template void dense_matrix::multiply_row_by_const template dense_matrix operator* (matrix & a, matrix & b){ - lean_assert(a.column_count() == b.row_count()); + lp_assert(a.column_count() == b.row_count()); dense_matrix ret(a.row_count(), b.column_count()); for (unsigned i = 0; i < ret.m_m; i++) for (unsigned j = 0; j< ret.m_n; j++) { diff --git a/src/util/lp/dense_matrix_instances.cpp b/src/util/lp/dense_matrix_instances.cpp index 1e931211d..418e2f2e0 100644 --- a/src/util/lp/dense_matrix_instances.cpp +++ b/src/util/lp/dense_matrix_instances.cpp @@ -6,19 +6,20 @@ #include "util/lp/dense_matrix.hpp" #ifdef LEAN_DEBUG #include "util/vector.h" -template lean::dense_matrix lean::operator*(lean::matrix&, lean::matrix&); -template void lean::dense_matrix::apply_from_left(vector &); -template lean::dense_matrix::dense_matrix(lean::matrix const*); -template lean::dense_matrix::dense_matrix(unsigned int, unsigned int); -template lean::dense_matrix& lean::dense_matrix::operator=(lean::dense_matrix const&); -template lean::dense_matrix >::dense_matrix(lean::matrix > const*); -template void lean::dense_matrix >::apply_from_left(vector&); -template lean::dense_matrix lean::operator*(lean::matrix&, lean::matrix&); -template lean::dense_matrix & lean::dense_matrix::operator=(lean::dense_matrix const&); -template lean::dense_matrix >::dense_matrix(unsigned int, unsigned int); -template lean::dense_matrix >& lean::dense_matrix >::operator=(lean::dense_matrix > const&); -template lean::dense_matrix > lean::operator* >(lean::matrix >&, lean::matrix >&); -template void lean::dense_matrix >::apply_from_right( vector< lean::mpq> &); -template void lean::dense_matrix::apply_from_right(class vector &); -template void lean::dense_matrix::apply_from_left(vector&); +template lp::dense_matrix lp::operator*(lp::matrix&, lp::matrix&); +template void lp::dense_matrix::apply_from_left(vector &); +template lp::dense_matrix::dense_matrix(lp::matrix const*); +template lp::dense_matrix::dense_matrix(unsigned int, unsigned int); +template lp::dense_matrix& lp::dense_matrix::operator=(lp::dense_matrix const&); +template lp::dense_matrix::dense_matrix(unsigned int, unsigned int); +template lp::dense_matrix >::dense_matrix(lp::matrix > const*); +template void lp::dense_matrix >::apply_from_left(vector&); +template lp::dense_matrix lp::operator*(lp::matrix&, lp::matrix&); +template lp::dense_matrix & lp::dense_matrix::operator=(lp::dense_matrix const&); +template lp::dense_matrix >::dense_matrix(unsigned int, unsigned int); +template lp::dense_matrix >& lp::dense_matrix >::operator=(lp::dense_matrix > const&); +template lp::dense_matrix > lp::operator* >(lp::matrix >&, lp::matrix >&); +template void lp::dense_matrix >::apply_from_right( vector< lp::mpq> &); +template void lp::dense_matrix::apply_from_right(class vector &); +template void lp::dense_matrix::apply_from_left(vector&); #endif diff --git a/src/util/lp/eta_matrix.h b/src/util/lp/eta_matrix.h index 51b015066..cfcd11256 100644 --- a/src/util/lp/eta_matrix.h +++ b/src/util/lp/eta_matrix.h @@ -7,7 +7,7 @@ #include "util/vector.h" #include "util/lp/tail_matrix.h" #include "util/lp/permutation_matrix.h" -namespace lean { +namespace lp { // This is the sum of a unit matrix and a one-column matrix template @@ -61,7 +61,7 @@ public: void push_back(unsigned row_index, T val ) { - lean_assert(row_index != m_column_index); + lp_assert(row_index != m_column_index); m_column_vector.push_back(row_index, val); } diff --git a/src/util/lp/eta_matrix.hpp b/src/util/lp/eta_matrix.hpp index 142a408d1..dc1ba9ce5 100644 --- a/src/util/lp/eta_matrix.hpp +++ b/src/util/lp/eta_matrix.hpp @@ -6,7 +6,7 @@ #pragma once #include "util/vector.h" #include "util/lp/eta_matrix.h" -namespace lean { +namespace lp { // This is the sum of a unit matrix and a one-column matrix template @@ -60,7 +60,7 @@ void eta_matrix::apply_from_right(vector & w) { } w[m_column_index] = t; #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(clone_w, w, get_number_of_rows())); + // lp_assert(vectors_are_equal(clone_w, w, get_number_of_rows())); // delete clone_w; #endif } @@ -100,8 +100,8 @@ void eta_matrix::apply_from_right(indexed_vector & w) { } #ifdef LEAN_DEBUG - // lean_assert(w.is_OK()); - // lean_assert(vectors_are_equal(wcopy, w.m_data)); + // lp_assert(w.is_OK()); + // lp_assert(vectors_are_equal(wcopy, w.m_data)); #endif } #ifdef LEAN_DEBUG @@ -130,7 +130,7 @@ void eta_matrix::conjugate_by_permutation(permutation_matrix & p) { pair.first = p.get_rev(pair.first); } #ifdef LEAN_DEBUG - // lean_assert(deb == *this); + // lp_assert(deb == *this); #endif } } diff --git a/src/util/lp/eta_matrix_instances.cpp b/src/util/lp/eta_matrix_instances.cpp index d57d43fed..470a16800 100644 --- a/src/util/lp/eta_matrix_instances.cpp +++ b/src/util/lp/eta_matrix_instances.cpp @@ -7,22 +7,22 @@ #include "util/lp/numeric_pair.h" #include "util/lp/eta_matrix.hpp" #ifdef LEAN_DEBUG -template double lean::eta_matrix::get_elem(unsigned int, unsigned int) const; -template lean::mpq lean::eta_matrix::get_elem(unsigned int, unsigned int) const; -template lean::mpq lean::eta_matrix >::get_elem(unsigned int, unsigned int) const; +template double lp::eta_matrix::get_elem(unsigned int, unsigned int) const; +template lp::mpq lp::eta_matrix::get_elem(unsigned int, unsigned int) const; +template lp::mpq lp::eta_matrix >::get_elem(unsigned int, unsigned int) const; #endif -template void lean::eta_matrix::apply_from_left(vector&, lean::lp_settings&); -template void lean::eta_matrix::apply_from_right(vector&); -template void lean::eta_matrix::conjugate_by_permutation(lean::permutation_matrix&); -template void lean::eta_matrix::apply_from_left(vector&, lean::lp_settings&); -template void lean::eta_matrix::apply_from_right(vector&); -template void lean::eta_matrix::conjugate_by_permutation(lean::permutation_matrix&); -template void lean::eta_matrix >::apply_from_left(vector >&, lean::lp_settings&); -template void lean::eta_matrix >::apply_from_right(vector&); -template void lean::eta_matrix >::conjugate_by_permutation(lean::permutation_matrix >&); -template void lean::eta_matrix::apply_from_left_local(lean::indexed_vector&, lean::lp_settings&); -template void lean::eta_matrix::apply_from_left_local(lean::indexed_vector&, lean::lp_settings&); -template void lean::eta_matrix >::apply_from_left_local(lean::indexed_vector&, lean::lp_settings&); -template void lean::eta_matrix >::apply_from_right(lean::indexed_vector&); -template void lean::eta_matrix::apply_from_right(lean::indexed_vector&); -template void lean::eta_matrix::apply_from_right(lean::indexed_vector&); +template void lp::eta_matrix::apply_from_left(vector&, lp::lp_settings&); +template void lp::eta_matrix::apply_from_right(vector&); +template void lp::eta_matrix::conjugate_by_permutation(lp::permutation_matrix&); +template void lp::eta_matrix::apply_from_left(vector&, lp::lp_settings&); +template void lp::eta_matrix::apply_from_right(vector&); +template void lp::eta_matrix::conjugate_by_permutation(lp::permutation_matrix&); +template void lp::eta_matrix >::apply_from_left(vector >&, lp::lp_settings&); +template void lp::eta_matrix >::apply_from_right(vector&); +template void lp::eta_matrix >::conjugate_by_permutation(lp::permutation_matrix >&); +template void lp::eta_matrix::apply_from_left_local(lp::indexed_vector&, lp::lp_settings&); +template void lp::eta_matrix::apply_from_left_local(lp::indexed_vector&, lp::lp_settings&); +template void lp::eta_matrix >::apply_from_left_local(lp::indexed_vector&, lp::lp_settings&); +template void lp::eta_matrix >::apply_from_right(lp::indexed_vector&); +template void lp::eta_matrix::apply_from_right(lp::indexed_vector&); +template void lp::eta_matrix::apply_from_right(lp::indexed_vector&); diff --git a/src/util/lp/hash_helper.h b/src/util/lp/hash_helper.h index 6fe31d5cd..3d2457a5c 100644 --- a/src/util/lp/hash_helper.h +++ b/src/util/lp/hash_helper.h @@ -12,8 +12,8 @@ #endif namespace std { template<> -struct hash { - inline size_t operator()(const lean::mpq & v) const { +struct hash { + inline size_t operator()(const lp::mpq & v) const { return v.hash(); } }; diff --git a/src/util/lp/implied_bound.h b/src/util/lp/implied_bound.h index 9583e3cd8..45911476f 100644 --- a/src/util/lp/implied_bound.h +++ b/src/util/lp/implied_bound.h @@ -5,7 +5,7 @@ #pragma once #include "util/lp/lp_settings.h" #include "util/lp/lar_constraints.h" -namespace lean { +namespace lp { struct implied_bound { mpq m_bound; unsigned m_j; // the column for which the bound has been found diff --git a/src/util/lp/indexed_value.h b/src/util/lp/indexed_value.h index 7963dfdf9..08a821d10 100644 --- a/src/util/lp/indexed_value.h +++ b/src/util/lp/indexed_value.h @@ -4,7 +4,7 @@ */ #pragma once -namespace lean { +namespace lp { template class indexed_value { public: diff --git a/src/util/lp/indexed_vector.h b/src/util/lp/indexed_vector.h index 6e6a6009b..6c0c32414 100644 --- a/src/util/lp/indexed_vector.h +++ b/src/util/lp/indexed_vector.h @@ -11,7 +11,7 @@ #include "util/lp/lp_utils.h" #include "util/lp/lp_settings.h" #include -namespace lean { +namespace lp { template void print_vector(const vector & t, std::ostream & out); template void print_vector(const buffer & t, std::ostream & out); @@ -75,16 +75,7 @@ public: } void set_value(const T& value, unsigned index); - void set_value_as_in_dictionary(unsigned index) { - lean_assert(index < m_data.size()); - T & loc = m_data[index]; - if (is_zero(loc)) { - m_index.push_back(index); - loc = one_of_type(); // use as a characteristic function - } - } - void clear(); void clear_all(); const T& operator[] (unsigned i) const { diff --git a/src/util/lp/indexed_vector.hpp b/src/util/lp/indexed_vector.hpp index 64e329adc..ff3effeb5 100644 --- a/src/util/lp/indexed_vector.hpp +++ b/src/util/lp/indexed_vector.hpp @@ -5,7 +5,7 @@ #include "util/vector.h" #include "util/lp/indexed_vector.h" #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { template void print_vector(const vector & t, std::ostream & out) { @@ -41,13 +41,13 @@ template void indexed_vector::resize(unsigned data_size) { clear(); m_data.resize(data_size, numeric_traits::zero()); - lean_assert(is_OK()); + lp_assert(is_OK()); } template void indexed_vector::set_value(const T& value, unsigned index) { m_data[index] = value; - lean_assert(std::find(m_index.begin(), m_index.end(), index) == m_index.end()); + lp_assert(std::find(m_index.begin(), m_index.end(), index) == m_index.end()); m_index.push_back(index); } diff --git a/src/util/lp/indexed_vector_instances.cpp b/src/util/lp/indexed_vector_instances.cpp index 6f17a894f..0d6f8c5d2 100644 --- a/src/util/lp/indexed_vector_instances.cpp +++ b/src/util/lp/indexed_vector_instances.cpp @@ -4,7 +4,7 @@ */ #include "util/vector.h" #include "util/lp/indexed_vector.hpp" -namespace lean { +namespace lp { template void indexed_vector::clear(); template void indexed_vector::clear_all(); template void indexed_vector::erase_from_index(unsigned int); @@ -20,17 +20,17 @@ template void indexed_vector::set_value(const unsigned&, unsigned int) #ifdef LEAN_DEBUG template bool indexed_vector::is_OK() const; template bool indexed_vector::is_OK() const; -template bool indexed_vector >::is_OK() const; -template void lean::indexed_vector< lean::mpq>::print(std::basic_ostream > &); -template void lean::indexed_vector::print(std::basic_ostream > &); -template void lean::indexed_vector >::print(std::ostream&); +template bool indexed_vector >::is_OK() const; +template void lp::indexed_vector< lp::mpq>::print(std::basic_ostream > &); +template void lp::indexed_vector::print(std::basic_ostream > &); +template void lp::indexed_vector >::print(std::ostream&); #endif } -template void lean::print_vector(vector const&, std::ostream&); -template void lean::print_vector(vector const&, std::ostream&); -template void lean::print_vector(vector const&, std::ostream&); -template void lean::print_vector >(vector> const&, std::ostream&); -template void lean::indexed_vector::resize(unsigned int); -template void lean::print_vector< lean::mpq>(vector< lean::mpq> const &, std::basic_ostream > &); -template void lean::print_vector >(vector> const&, std::ostream&); -template void lean::indexed_vector >::erase_from_index(unsigned int); +template void lp::print_vector(vector const&, std::ostream&); +template void lp::print_vector(vector const&, std::ostream&); +template void lp::print_vector(vector const&, std::ostream&); +template void lp::print_vector >(vector> const&, std::ostream&); +template void lp::indexed_vector::resize(unsigned int); +template void lp::print_vector< lp::mpq>(vector< lp::mpq> const &, std::basic_ostream > &); +template void lp::print_vector >(vector> const&, std::ostream&); +template void lp::indexed_vector >::erase_from_index(unsigned int); diff --git a/src/util/lp/int_set.h b/src/util/lp/int_set.h index 0619facd8..931125ab5 100644 --- a/src/util/lp/int_set.h +++ b/src/util/lp/int_set.h @@ -6,7 +6,7 @@ #include "util/vector.h" #include "util/lp/indexed_vector.h" #include -namespace lean { +namespace lp { // serves at a set of non-negative integers smaller than the set size class int_set { vector m_data; @@ -20,7 +20,7 @@ public: return m_data[j] >= 0; } void insert(unsigned j) { - lean_assert(j < m_data.size()); + lp_assert(j < m_data.size()); if (contains(j)) return; m_data[j] = m_index.size(); m_index.push_back(j); diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index e7ea24a6f..90dfef767 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -4,3 +4,963 @@ */ #include "util/lp/int_solver.h" +#include "util/lp/lar_solver.h" +namespace lp { + +void int_solver::fix_non_base_columns() { + lp_assert(is_feasible() && inf_int_set_is_correct()); + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + bool change = false; + for (unsigned j : lcs.m_r_nbasis) { + if (column_is_int_inf(j)) { + change = true; + set_value_for_nbasic_column(j, floor(lcs.m_r_x[j].x)); + } + } + if (!change) + return; + if (m_lar_solver->find_feasible_solution() == lp_status::INFEASIBLE) + failed(); + lp_assert(is_feasible() && inf_int_set_is_correct()); +} + +void int_solver::failed() { + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + + for (unsigned j : m_old_values_set.m_index) { + lcs.m_r_x[j] = m_old_values_data[j]; + lp_assert(lcs.m_r_solver.column_is_feasible(j)); + lcs.m_r_solver.remove_column_from_inf_set(j); + } + lp_assert(lcs.m_r_solver.calc_current_x_is_feasible_include_non_basis()); + lp_assert(lcs.m_r_solver.current_x_is_feasible()); + m_old_values_set.clear(); +} + +void int_solver::trace_inf_rows() const { + TRACE("arith_int_rows", + unsigned num = m_lar_solver->A_r().column_count(); + for (unsigned v = 0; v < num; v++) { + if (is_int(v) && !get_value(v).is_int()) { + display_column(tout, v); + } + } + + num = 0; + for (unsigned i = 0; i < m_lar_solver->A_r().row_count(); i++) { + unsigned j = m_lar_solver->m_mpq_lar_core_solver.m_r_basis[i]; + if (column_is_int_inf(j)) { + num++; + iterator_on_row it(m_lar_solver->A_r().m_rows[i]); + m_lar_solver->print_linear_iterator(&it, tout); + tout << "\n"; + } + } + tout << "num of int infeasible: " << num << "\n"; + ); +} + +int_set& int_solver::inf_int_set() { + return m_lar_solver->m_inf_int_set; +} + +const int_set& int_solver::inf_int_set() const { + return m_lar_solver->m_inf_int_set; +} + +int int_solver::find_inf_int_base_column() { + if (inf_int_set().is_empty()) + return -1; + int j = find_inf_int_boxed_base_column_with_smallest_range(); + if (j != -1) + return j; + unsigned k = settings().random_next() % inf_int_set().m_index.size(); + return inf_int_set().m_index[k]; +} + +int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { + int result = -1; + mpq range; + mpq new_range; + mpq small_range_thresold(1024); + unsigned n = 0; + lar_core_solver & lcs = m_lar_solver->m_mpq_lar_core_solver; + + for (int j : inf_int_set().m_index) { + lp_assert(is_base(j) && column_is_int_inf(j)); + if (!is_boxed(j)) + continue; + new_range = lcs.m_r_upper_bounds()[j].x - lcs.m_r_low_bounds()[j].x; + if (new_range > small_range_thresold) + continue; + if (result == -1) { + result = j; + range = new_range; + n = 1; + continue; + } + if (new_range < range) { + n = 1; + result = j; + range = new_range; + continue; + } + if (new_range == range) { + n++; + if (settings().random_next() % n == 0) { + result = j; + continue; + } + } + } + return result; + +} + +bool int_solver::is_gomory_cut_target() { + m_iter_on_gomory_row->reset(); + unsigned j; + TRACE("gomory_cut", m_lar_solver->print_linear_iterator(m_iter_on_gomory_row, tout); + m_iter_on_gomory_row->reset(); + ); + + while (m_iter_on_gomory_row->next(j)) { + // All non base variables must be at their bounds and assigned to rationals (that is, infinitesimals are not allowed). + if (j != m_gomory_cut_inf_column && (!at_bound(j) || !is_zero(get_value(j).y))) { + TRACE("gomory_cut", tout << "row is not gomory cut target:\n"; + display_column(tout, j); + tout << "at_bound: " << at_bound(j) << "\n"; + tout << "infinitesimal: " << !is_zero(get_value(j).y) << "\n";); + return false; + } + } + m_iter_on_gomory_row->reset(); + return true; +} + + +void int_solver::real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& pol, explanation & expl) { + mpq f_0 = fractional_part(get_value(m_gomory_cut_inf_column)); + mpq new_a; + if (at_lower(x_j)) { + if (a.is_pos()) { + new_a = a / (1 - f_0); + } + else { + new_a = a / f_0; + new_a.neg(); + } + k += lower_bound(x_j).x * k; // k.addmul(new_a, lower_bound(x_j).x); // is it a faster operation + + expl.push_justification(column_low_bound_constraint(x_j), new_a); + } + else { + lp_assert(at_upper(x_j)); + if (a.is_pos()) { + new_a = a / f_0; + new_a.neg(); // the upper terms are inverted. + } + else { + new_a = a / (mpq(1) - f_0); + } + k += upper_bound(x_j).x * k; // k.addmul(new_a, upper_bound(x_j).get_rational()); + expl.push_justification(column_upper_bound_constraint(x_j), new_a); + } + TRACE("gomory_cut_detail", tout << a << "*v" << x_j << " k: " << k << "\n";); + pol.add_monoid(new_a, x_j); +} + +constraint_index int_solver::column_upper_bound_constraint(unsigned j) const { + return m_lar_solver->get_column_upper_bound_witness(j); +} + +constraint_index int_solver::column_low_bound_constraint(unsigned j) const { + return m_lar_solver->get_column_low_bound_witness(j); +} + + +void int_solver::int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term & pol, explanation& expl, mpq & lcm_den) { + mpq f_0 = fractional_part(get_value(m_gomory_cut_inf_column)); + lp_assert(is_int(x_j)); + mpq f_j = fractional_part(a); + TRACE("gomory_cut_detail", + tout << a << "*v" << x_j << "\n"; + tout << "fractional_part: " << fractional_part(a) << "\n"; + tout << "f_j: " << f_j << "\n"; + tout << "f_0: " << f_0 << "\n"; + tout << "one_minus_f_0: " << 1 - f_0 << "\n";); + if (!f_j.is_zero()) { + mpq new_a; + if (at_lower(x_j)) { + auto one_minus_f_0 = 1 - f_0; + if (f_j <= one_minus_f_0) { + new_a = f_j / one_minus_f_0; + } + else { + new_a = (1 - f_j) / f_0; + } + k.addmul(new_a, lower_bound(x_j).x); + expl.push_justification(column_low_bound_constraint(x_j), new_a); + } + else { + SASSERT(at_upper(x_j)); + if (f_j <= f_0) { + new_a = f_j / f_0; + } + else { + new_a = (mpq(1) - f_j) / 1 - f_0; + } + new_a.neg(); // the upper terms are inverted + k.addmul(new_a, upper_bound(x_j).x); + expl.push_justification(column_upper_bound_constraint(x_j), new_a); + } + TRACE("gomory_cut_detail", tout << "new_a: " << new_a << " k: " << k << "\n";); + pol.add_monoid(new_a, x_j); + lcm_den = lcm(lcm_den, denominator(new_a)); + } +} + +lia_move int_solver::report_conflict_from_gomory_cut(mpq & k) { + TRACE("empty_pol", + display_row_info(tout, + m_lar_solver->m_mpq_lar_core_solver.m_r_heading[m_gomory_cut_inf_column]);); + lp_assert(k.is_pos()); + // conflict 0 >= k where k is positive + k.neg(); // returning 0 <= -k + return lia_move::conflict; +} + +void int_solver::gomory_cut_adjust_t_and_k_for_size_gt_1( + vector> & pol, + lar_term & t, + mpq &k, + unsigned num_ints, + mpq & lcm_den) { + if (num_ints > 0) { + lcm_den = lcm(lcm_den, denominator(k)); + TRACE("gomory_cut_detail", tout << "k: " << k << " lcm_den: " << lcm_den << "\n"; + linear_combination_iterator_on_vector pi(pol); + m_lar_solver->print_linear_iterator(&pi, tout); + tout << "\nk: " << k << "\n";); + lp_assert(lcm_den.is_pos()); + if (!lcm_den.is_one()) { + // normalize coefficients of integer parameters to be integers. + for (auto & pi: pol) { + pi.first *= lcm_den; + SASSERT(!is_int(pi.second) || pi.first.is_int()); + } + k *= lcm_den; + } + TRACE("gomory_cut_detail", tout << "after *lcm_den\n"; + for (unsigned i = 0; i < pol.size(); i++) { + tout << pol[i].first << " * v" << pol[i].second << "\n"; + } + tout << "k: " << k << "\n";); + } + t.clear(); + // negate everything to return -pol <= -k + for (const auto & pi: pol) + t.add_monoid(-pi.first, pi.second); + k.neg(); +} + + +void int_solver::gomory_cut_adjust_t_and_k_for_size_1(const vector> & pol, lar_term& t, mpq &k) { + lp_assert(pol.size() == 1); + unsigned j = pol[0].second; + k /= pol[0].first; + bool is_lower = pol[0].first.is_pos(); + if (is_int(j) && !k.is_int()) { + k = is_lower?ceil(k):floor(k); + } + if (is_lower) { // returning -t <= -k which is equivalent to t >= k + k.neg(); + t.negate(); + } +} + + +bool int_solver::current_solution_is_inf_on_cut(const lar_term& t, const mpq& k) const { + const auto & x = m_lar_solver->m_mpq_lar_core_solver.m_r_x; + impq v = t.apply(x); + TRACE("gomory_cut", tout << "v = " << v << " k = " << k << std::endl;); + return v > k; +} + +lia_move int_solver::report_gomory_cut(lar_term& t, mpq& k, mpq &lcm_den, unsigned num_ints) { + lp_assert(!t.is_empty()); + auto pol = t.coeffs_as_vector(); + if (pol.size() == 1) + gomory_cut_adjust_t_and_k_for_size_1(pol, t, k); + else + gomory_cut_adjust_t_and_k_for_size_gt_1(pol, t, k, num_ints, lcm_den); + return lia_move::cut; +} + + + + +lia_move int_solver::mk_gomory_cut(lar_term& t, mpq& k, explanation & expl) { + + lp_assert(column_is_int_inf(m_gomory_cut_inf_column)); + + TRACE("gomory_cut", tout << "applying cut at:\n"; m_lar_solver->print_linear_iterator(m_iter_on_gomory_row, tout); tout << std::endl; m_iter_on_gomory_row->reset();); + + // gomory will be t >= k + k = 1; + mpq lcm_den(1); + unsigned num_ints = 0; + unsigned x_j; + mpq a; + while (m_iter_on_gomory_row->next(a, x_j)) { + if (x_j == m_gomory_cut_inf_column) + continue; + // make the format compatible with the format used in: Integrating Simplex with DPLL(T) + a.neg(); + if (is_real(x_j)) + real_case_in_gomory_cut(a, x_j, k, t, expl); + else { + num_ints++; + int_case_in_gomory_cut(a, x_j, k, t, expl, lcm_den); + } + } + + if (t.is_empty()) + return report_conflict_from_gomory_cut(k); + + auto ret = report_gomory_cut(t, k, lcm_den, num_ints); + + // remove this call later :todo + m_lar_solver->subs_term_columns(t); + lp_assert(current_solution_is_inf_on_cut(t, k)); + return ret; + +} + +void int_solver::init_check_data() { + unsigned n = m_lar_solver->A_r().column_count(); + m_old_values_set.resize(n); + m_old_values_data.resize(n); +} + +int int_solver::find_next_free_var_in_gomory_row() { + lp_assert(m_iter_on_gomory_row != nullptr); + unsigned j; + while(m_iter_on_gomory_row->next(j)) { + if (j != m_gomory_cut_inf_column && is_free(j)) + return static_cast(j); + } + return -1; +} + +lia_move int_solver::proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex) { + int j = find_next_free_var_in_gomory_row(); + if (j != -1) { + m_found_free_var_in_gomory_row = true; + lp_assert(t.is_empty()); + t.add_monoid(mpq(1), j); + k = zero_of_type(); + return lia_move::branch; // branch on a free column + } + if (m_found_free_var_in_gomory_row || !is_gomory_cut_target()) { + m_found_free_var_in_gomory_row = false; + delete m_iter_on_gomory_row; + m_iter_on_gomory_row = nullptr; + return lia_move::continue_with_check; + } + + lia_move ret = mk_gomory_cut(t, k, ex); + delete m_iter_on_gomory_row; + m_iter_on_gomory_row = nullptr; + return ret; + } + + +lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { + if (m_iter_on_gomory_row != nullptr) { + auto ret = proceed_with_gomory_cut(t, k, ex); + TRACE("gomory_cut", tout << "term t = "; m_lar_solver->print_term_as_indices(t, tout);); + if (ret != lia_move::continue_with_check) + return ret; + } + + init_check_data(); + lp_assert(inf_int_set_is_correct()); + // currently it is a reimplementation of + // final_check_status theory_arith::check_int_feasibility() + // from theory_arith_int.h + if (m_lar_solver->model_is_int_feasible()) + return lia_move::ok; + if (!gcd_test(ex)) + return lia_move::conflict; + /* + if (m_params.m_arith_euclidean_solver) + apply_euclidean_solver(); + + */ + m_lar_solver->pivot_fixed_vars_from_basis(); + patch_int_infeasible_columns(); + fix_non_base_columns(); + TRACE("arith_int_rows", trace_inf_rows();); + + if (find_inf_int_base_column() == -1) + return lia_move::ok; + + + if ((++m_branch_cut_counter) % settings().m_int_branch_cut_threshold == 0) { + move_non_base_vars_to_bounds(); // todo track changed variables + lp_status st = m_lar_solver->find_feasible_solution(); + if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) { + return lia_move::give_up; + } + lp_assert(inf_int_set_is_correct()); + // init_inf_int_set(); // todo - can we avoid this call? + int j = find_inf_int_base_column(); + if (j != -1) { + // setup the call for gomory cut + TRACE("arith_int", tout << "j = " << j << " does not have an integer assignment: " << get_value(j) << "\n";); + unsigned row_index = m_lar_solver->m_mpq_lar_core_solver.m_r_heading[j]; + m_iter_on_gomory_row = m_lar_solver->get_iterator_on_row(row_index); + m_gomory_cut_inf_column = j; + return check(t, k, ex); + } + } + else { + int j = find_inf_int_base_column(); + if (j != -1) { + TRACE("arith_int", tout << "j" << j << " does not have an integer assignment: " << get_value(j) << "\n";); + + lp_assert(t.is_empty()); + t.add_monoid(mpq(1), j); + k = floor(get_value(j)); + TRACE("arith_int", tout << "branching v" << j << " = " << get_value(j) << "\n"; + display_column(tout, j); + tout << "k = " << k << std::endl; + ); + // todo: remove this call later when theory_lra handles term indices + m_lar_solver->subs_term_columns(t); + lp_assert(current_solution_is_inf_on_cut(t, k)); + return lia_move::branch; + } + } + + lp_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); + // return true; + return lia_move::give_up; +} + +void int_solver::move_non_base_vars_to_bounds() { + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + for (unsigned j : lcs.m_r_nbasis) { + auto & val = lcs.m_r_x[j]; + switch (lcs.m_column_types()[j]) { + case column_type::boxed: + if (val != lcs.m_r_low_bounds()[j] && val != lcs.m_r_upper_bounds()[j]) + set_value_for_nbasic_column(j, lcs.m_r_low_bounds()[j]); + break; + case column_type::low_bound: + if (val != lcs.m_r_low_bounds()[j]) + set_value_for_nbasic_column(j, lcs.m_r_low_bounds()[j]); + break; + case column_type::upper_bound: + if (val != lcs.m_r_upper_bounds()[j]) + set_value_for_nbasic_column(j, lcs.m_r_upper_bounds()[j]); + break; + default: + if (is_int(j) && !val.is_int()) { + set_value_for_nbasic_column(j, impq(floor(val))); + } + } + } +} + + + +void int_solver::set_value_for_nbasic_column(unsigned j, const impq & new_val) { + lp_assert(!is_base(j)); + auto & x = m_lar_solver->m_mpq_lar_core_solver.m_r_x[j]; + if (!m_old_values_set.contains(j)) { + m_old_values_set.insert(j); + m_old_values_data[j] = x; + } + auto delta = new_val - x; + x = new_val; + m_lar_solver->change_basic_x_by_delta_on_column(j, delta); + + auto * it = get_column_iterator(j); + update_column_in_int_inf_set(j); + unsigned i; + while (it->next(i)) + update_column_in_int_inf_set(m_lar_solver->m_mpq_lar_core_solver.m_r_basis[i]); + delete it; +} + +void int_solver::patch_int_infeasible_columns() { + bool inf_l, inf_u; + impq l, u; + mpq m; + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + for (unsigned j : lcs.m_r_nbasis) { + if (!is_int(j)) + continue; + get_freedom_interval_for_column(j, inf_l, l, inf_u, u, m); + impq & val = lcs.m_r_x[j]; + bool val_is_int = val.is_int(); + bool m_is_one = m.is_one(); + if (m.is_one() && val_is_int) + continue; + // check whether value of j is already a multiple of m. + if (val_is_int && (val.x / m).is_int()) + continue; + TRACE("patch_int", + tout << "TARGET j" << j << " -> ["; + if (inf_l) tout << "-oo"; else tout << l; + tout << ", "; + if (inf_u) tout << "oo"; else tout << u; + tout << "]"; + tout << ", m: " << m << ", val: " << val << ", is_int: " << m_lar_solver->column_is_int(j) << "\n";); + if (!inf_l) { + l = m_is_one? ceil(l) : m * ceil(l / m); + if (inf_u || l <= u) { + TRACE("patch_int", + tout << "patching with l: " << l << '\n';); + + set_value_for_nbasic_column(j, l); + } else { + TRACE("patch_int", + tout << "not patching " << l << "\n";); + } + } else if (!inf_u) { + u = m_is_one? floor(u) : m * floor(u / m); + set_value_for_nbasic_column(j, u); + TRACE("patch_int", + tout << "patching with u: " << u << '\n';); + } else { + set_value_for_nbasic_column(j, impq(0)); + TRACE("patch_int", + tout << "patching with 0\n";); + } + lp_assert(is_feasible() && inf_int_set_is_correct()); + } +} + +mpq get_denominators_lcm(iterator_on_row &it) { + mpq r(1); + mpq a; + unsigned j; + while (it.next(a, j)) { + r = lcm(r, denominator(a)); + } + return r; +} + +bool int_solver::gcd_test_for_row(static_matrix> & A, unsigned i, explanation & ex) { + iterator_on_row it(A.m_rows[i]); + mpq lcm_den = get_denominators_lcm(it); + mpq consts(0); + mpq gcds(0); + mpq least_coeff(0); + bool least_coeff_is_bounded = false; + mpq a; + unsigned j; + while (it.next(a, j)) { + if (m_lar_solver->column_is_fixed(j)) { + mpq aux = lcm_den * a; + consts += aux * m_lar_solver->column_low_bound(j).x; + } + else if (m_lar_solver->column_is_real(j)) { + return true; + } + else if (gcds.is_zero()) { + gcds = abs(lcm_den * a); + least_coeff = gcds; + least_coeff_is_bounded = m_lar_solver->column_is_bounded(j); + } + else { + mpq aux = abs(lcm_den * a); + gcds = gcd(gcds, aux); + if (aux < least_coeff) { + least_coeff = aux; + least_coeff_is_bounded = m_lar_solver->column_is_bounded(j); + } + else if (least_coeff_is_bounded && aux == least_coeff) { + least_coeff_is_bounded = m_lar_solver->column_is_bounded(j); + } + } + SASSERT(gcds.is_int()); + SASSERT(least_coeff.is_int()); + TRACE("gcd_test_bug", tout << "coeff: " << a << ", gcds: " << gcds + << " least_coeff: " << least_coeff << " consts: " << consts << "\n";); + + } + + if (gcds.is_zero()) { + // All variables are fixed. + // This theory guarantees that the assignment satisfies each row, and + // fixed integer variables are assigned to integer values. + return true; + } + + if (!(consts / gcds).is_int()) + fill_explanation_from_fixed_columns(it, ex); + + if (least_coeff.is_one() && !least_coeff_is_bounded) { + SASSERT(gcds.is_one()); + return true; + } + + if (least_coeff_is_bounded) { + return ext_gcd_test(it, least_coeff, lcm_den, consts, ex); + } + return true; +} + +void int_solver::add_to_explanation_from_fixed_or_boxed_column(unsigned j, explanation & ex) { + constraint_index lc, uc; + m_lar_solver->get_bound_constraint_witnesses_for_column(j, lc, uc); + ex.m_explanation.push_back(std::make_pair(mpq(1), lc)); + ex.m_explanation.push_back(std::make_pair(mpq(1), uc)); +} +void int_solver::fill_explanation_from_fixed_columns(iterator_on_row & it, explanation & ex) { + it.reset(); + unsigned j; + while (it.next(j)) { + if (!m_lar_solver->column_is_fixed(j)) + continue; + add_to_explanation_from_fixed_or_boxed_column(j, ex); + } +} + +bool int_solver::gcd_test(explanation & ex) { + auto & A = m_lar_solver->A_r(); // getting the matrix + for (unsigned i = 0; i < A.row_count(); i++) + if (!gcd_test_for_row(A, i, ex)) { + std::cout << "false from gcd_test\n" ; + return false; + } + + return true; +} + +bool int_solver::ext_gcd_test(iterator_on_row & it, + mpq const & least_coeff, + mpq const & lcm_den, + mpq const & consts, explanation& ex) { + mpq gcds(0); + mpq l(consts); + mpq u(consts); + + it.reset(); + mpq a; + unsigned j; + while (it.next(a, j)) { + if (m_lar_solver->column_is_fixed(j)) + continue; + SASSERT(!m_lar_solver->column_is_real(j)); + mpq ncoeff = lcm_den * a; + SASSERT(ncoeff.is_int()); + mpq abs_ncoeff = abs(ncoeff); + if (abs_ncoeff == least_coeff) { + SASSERT(m_lar_solver->column_is_bounded(j)); + if (ncoeff.is_pos()) { + // l += ncoeff * m_lar_solver->column_low_bound(j).x; + l.addmul(ncoeff, m_lar_solver->column_low_bound(j).x); + // u += ncoeff * m_lar_solver->column_upper_bound(j).x; + u.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x); + } + else { + // l += ncoeff * upper_bound(j).get_rational(); + l.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x); + // u += ncoeff * lower_bound(j).get_rational(); + u.addmul(ncoeff, m_lar_solver->column_low_bound(j).x); + } + add_to_explanation_from_fixed_or_boxed_column(j, ex); + } + else if (gcds.is_zero()) { + gcds = abs_ncoeff; + } + else { + gcds = gcd(gcds, abs_ncoeff); + } + SASSERT(gcds.is_int()); + } + + if (gcds.is_zero()) { + return true; + } + + mpq l1 = ceil(l/gcds); + mpq u1 = floor(u/gcds); + + if (u1 < l1) { + fill_explanation_from_fixed_columns(it, ex); + return false; + } + + return true; + +} + +linear_combination_iterator * int_solver::get_column_iterator(unsigned j) { + if (m_lar_solver->use_tableau()) + return new iterator_on_column(m_lar_solver->A_r().m_columns[j], m_lar_solver->A_r()); + return new iterator_on_indexed_vector(m_lar_solver->get_column_in_lu_mode(j)); +} + + +int_solver::int_solver(lar_solver* lar_slv) : + m_lar_solver(lar_slv), + m_branch_cut_counter(0), + m_iter_on_gomory_row(nullptr), + m_found_free_var_in_gomory_row(false) { + lp_assert(m_old_values_set.size() == 0); + m_old_values_set.resize(lar_slv->A_r().column_count()); + m_old_values_data.resize(lar_slv->A_r().column_count(), zero_of_type()); +} + +bool int_solver::lower(unsigned j) const { + switch (m_lar_solver->m_mpq_lar_core_solver.m_column_types()[j]) { + case column_type::fixed: + case column_type::boxed: + case column_type::low_bound: + return true; + default: + return false; + } +} + +bool int_solver::upper(unsigned j) const { + switch (m_lar_solver->m_mpq_lar_core_solver.m_column_types()[j]) { + case column_type::fixed: + case column_type::boxed: + case column_type::upper_bound: + return true; + default: + return false; + } +} + +const impq& int_solver::lower_bound(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_r_low_bounds()[j]; +} + +const impq& int_solver::upper_bound(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_r_upper_bounds()[j]; +} + + +void set_lower(impq & l, + bool & inf_l, + impq const & v ) { + if (inf_l || v > l) { + l = v; + inf_l = false; + } +} + +void set_upper(impq & u, + bool & inf_u, + impq const & v) { + if (inf_u || v < u) { + u = v; + inf_u = false; + } +} + +bool int_solver::get_freedom_interval_for_column(unsigned x_j, bool & inf_l, impq & l, bool & inf_u, impq & u, mpq & m) { + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + if (lcs.m_r_heading[x_j] >= 0) // the basic var + return false; + + impq const & x_j_val = lcs.m_r_x[x_j]; + linear_combination_iterator *it = get_column_iterator(x_j); + + inf_l = true; + inf_u = true; + l = u = zero_of_type(); + m = mpq(1); + + if (lower(x_j)) { + set_lower(l, inf_l, lower_bound(x_j)); + } + if (upper(x_j)) { + set_upper(u, inf_u, upper_bound(x_j)); + } + + mpq a_ij; unsigned i; + while (it->next(a_ij, i)) { + unsigned x_i = lcs.m_r_basis[i]; + impq const & x_i_val = lcs.m_r_x[x_i]; + if (is_int(x_i) && is_int(x_j) && !a_ij.is_int()) + m = lcm(m, denominator(a_ij)); + bool x_i_lower = lower(x_i); + bool x_i_upper = upper(x_i); + if (a_ij.is_neg()) { + if (x_i_lower) { + impq new_l = x_j_val + ((x_i_val - lcs.m_r_low_bounds()[x_i]) / a_ij); + set_lower(l, inf_l, new_l); + if (!inf_l && !inf_u && l == u) break;; + } + if (x_i_upper) { + impq new_u = x_j_val + ((x_i_val - lcs.m_r_upper_bounds()[x_i]) / a_ij); + set_upper(u, inf_u, new_u); + if (!inf_l && !inf_u && l == u) break;; + } + } + else { + if (x_i_upper) { + impq new_l = x_j_val + ((x_i_val - lcs.m_r_upper_bounds()[x_i]) / a_ij); + set_lower(l, inf_l, new_l); + if (!inf_l && !inf_u && l == u) break;; + } + if (x_i_lower) { + impq new_u = x_j_val + ((x_i_val - lcs.m_r_low_bounds()[x_i]) / a_ij); + set_upper(u, inf_u, new_u); + if (!inf_l && !inf_u && l == u) break;; + } + } + } + + delete it; + TRACE("freedom_interval", + tout << "freedom variable for:\n"; + tout << m_lar_solver->get_column_name(x_j); + tout << "["; + if (inf_l) tout << "-oo"; else tout << l; + tout << "; "; + if (inf_u) tout << "oo"; else tout << u; + tout << "]\n"; + tout << "val = " << get_value(x_j) << "\n"; + ); + lp_assert(inf_l || l <= get_value(x_j)); + lp_assert(inf_u || u >= get_value(x_j)); + return true; + +} + +bool int_solver::is_int(unsigned j) const { + return m_lar_solver->column_is_int(j); +} + +bool int_solver::is_real(unsigned j) const { + return !is_int(j); +} + +bool int_solver::value_is_int(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_r_x[j].is_int(); +} + + + +bool int_solver::is_feasible() const { + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + lp_assert( + lcs.m_r_solver.calc_current_x_is_feasible_include_non_basis() == + lcs.m_r_solver.current_x_is_feasible()); + return lcs.m_r_solver.current_x_is_feasible(); +} +const impq & int_solver::get_value(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_r_x[j]; +} + +void int_solver::display_column(std::ostream & out, unsigned j) const { + m_lar_solver->m_mpq_lar_core_solver.m_r_solver.print_column_info(j, out); +} + +bool int_solver::inf_int_set_is_correct() const { + for (unsigned j = 0; j < m_lar_solver->A_r().column_count(); j++) { + if (inf_int_set().contains(j) != (is_int(j) && (!value_is_int(j)))) + return false; + } + return true; +} + +bool int_solver::column_is_int_inf(unsigned j) const { + return is_int(j) && (!value_is_int(j)); +} + +void int_solver::update_column_in_int_inf_set(unsigned j) { + if (is_int(j) && (!value_is_int(j))) + inf_int_set().insert(j); + else + inf_int_set().erase(j); +} + +bool int_solver::is_base(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_r_heading[j] >= 0; +} + +bool int_solver::is_boxed(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_column_types[j] == column_type::boxed; +} + +bool int_solver::is_free(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_column_types[j] == column_type::free_column; +} + +bool int_solver::at_bound(unsigned j) const { + auto & mpq_solver = m_lar_solver->m_mpq_lar_core_solver.m_r_solver; + switch (mpq_solver.m_column_types[j] ) { + case column_type::fixed: + case column_type::boxed: + return + mpq_solver.m_low_bounds[j] == get_value(j) || + mpq_solver.m_upper_bounds[j] == get_value(j); + case column_type::low_bound: + return mpq_solver.m_low_bounds[j] == get_value(j); + case column_type::upper_bound: + return mpq_solver.m_upper_bounds[j] == get_value(j); + default: + return false; + } +} + +bool int_solver::at_lower(unsigned j) const { + auto & mpq_solver = m_lar_solver->m_mpq_lar_core_solver.m_r_solver; + switch (mpq_solver.m_column_types[j] ) { + case column_type::fixed: + case column_type::boxed: + case column_type::low_bound: + return mpq_solver.m_low_bounds[j] == get_value(j); + default: + return false; + } +} + +bool int_solver::at_upper(unsigned j) const { + auto & mpq_solver = m_lar_solver->m_mpq_lar_core_solver.m_r_solver; + switch (mpq_solver.m_column_types[j] ) { + case column_type::fixed: + case column_type::boxed: + case column_type::upper_bound: + return mpq_solver.m_upper_bounds[j] == get_value(j); + default: + return false; + } +} + + + +lp_settings& int_solver::settings() { + return m_lar_solver->settings(); +} + +void int_solver::display_row_info(std::ostream & out, unsigned row_index) const { + auto & rslv = m_lar_solver->m_mpq_lar_core_solver.m_r_solver; + auto it = m_lar_solver->get_iterator_on_row(row_index); + mpq a; + unsigned j; + while (it->next(a, j)) { + if (numeric_traits::is_pos(a)) + out << "+"; + out << a << rslv.column_name(j) << " "; + } + + it->reset(); + while(it->next(j)) { + rslv.print_column_bound_info(j, out); + } + rslv.print_column_bound_info(rslv.m_basis[row_index], out); + delete it; +} +} diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index b74a25855..104e9b321 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -4,22 +4,53 @@ */ #pragma once #include "util/lp/lp_settings.h" -class lemma; // forward definition -namespace lean { +#include "util/lp/static_matrix.h" +#include "util/lp/iterator_on_row.h" +#include "util/lp/int_set.h" +#include "util/lp/lar_term.h" +namespace lp { class lar_solver; template struct lp_constraint; +enum class lia_move { + ok, + branch, + cut, + conflict, + continue_with_check, + give_up +}; + +struct explanation { + vector> m_explanation; + void push_justification(constraint_index j, const mpq& v) { + m_explanation.push_back(std::make_pair(v, j)); + } +}; class int_solver { public: - lar_solver *m_solver; + // fields + lar_solver *m_lar_solver; + int_set m_old_values_set; + vector m_old_values_data; + unsigned m_branch_cut_counter; + linear_combination_iterator* m_iter_on_gomory_row; + unsigned m_gomory_cut_inf_column; + bool m_found_free_var_in_gomory_row; + // methods int_solver(lar_solver* lp); - bool check();// main function to check that solution provided by lar_solver is valid for integral values or can be adjusted. + int_set& inf_int_set(); + const int_set& inf_int_set() const; + // main function to check that solution provided by lar_solver is valid for integral values, + // or provide a way of how it can be adjusted. + lia_move check(lar_term& t, mpq& k, explanation& ex); private: // how to tighten bounds for integer variables. - + + bool gcd_test_for_row(static_matrix> & A, unsigned i, explanation &); // gcd test // 5*x + 3*y + 6*z = 5 @@ -29,7 +60,7 @@ private: // this is unsolvable because 5/3 is not an integer. // so we create a lemma that rules out this condition. // - bool gcd_test(lemma& lemma); // returns false in case of failure. Creates a theory lemma in case of failure. + bool gcd_test(explanation & ); // returns false in case of failure. Creates a theory lemma in case of failure. // create goromy cuts // either creates a conflict or a bound. @@ -39,6 +70,70 @@ private: // creates a fresh inequality. bool branch(const lp_constraint & new_inequality); - + bool ext_gcd_test(iterator_on_row & it, + mpq const & least_coeff, + mpq const & lcm_den, + mpq const & consts, + explanation & ex); + void fill_explanation_from_fixed_columns(iterator_on_row & it, explanation &); + void add_to_explanation_from_fixed_or_boxed_column(unsigned j, explanation &); + void remove_fixed_vars_from_base(); + void patch_int_infeasible_columns(); + bool get_freedom_interval_for_column(unsigned j, bool & inf_l, impq & l, bool & inf_u, impq & u, mpq & m); + linear_combination_iterator * get_column_iterator(unsigned j); + bool lower(unsigned j) const; + bool upper(unsigned j) const; + const impq & lower_bound(unsigned j) const; + const impq & upper_bound(unsigned j) const; + bool is_int(unsigned j) const; + bool is_real(unsigned j) const; + bool is_base(unsigned j) const; + bool is_boxed(unsigned j) const; + bool is_free(unsigned j) const; + bool value_is_int(unsigned j) const; + void set_value_for_nbasic_column(unsigned j, const impq & new_val); + void fix_non_base_columns(); + void failed(); + bool is_feasible() const; + const impq & get_value(unsigned j) const; + void display_column(std::ostream & out, unsigned j) const; + bool inf_int_set_is_correct() const; + void update_column_in_int_inf_set(unsigned j); + bool column_is_int_inf(unsigned j) const; + void trace_inf_rows() const; + int find_inf_int_base_column(); + int find_inf_int_boxed_base_column_with_smallest_range(); + lp_settings& settings(); + void move_non_base_vars_to_bounds(); + void branch_infeasible_int_var(unsigned); + lia_move mk_gomory_cut(lar_term& t, mpq& k,explanation & ex); + lia_move report_conflict_from_gomory_cut(mpq & k); + lia_move report_gomory_cut(lar_term& t, mpq& k, mpq& lcm_den, unsigned num_ints); + void init_check_data(); + bool constrain_free_vars(linear_combination_iterator * r); + lia_move proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex); + int find_next_free_var_in_gomory_row(); + bool is_gomory_cut_target(); + bool at_bound(unsigned j) const; + bool at_lower(unsigned j) const; + bool at_upper(unsigned j) const; + + inline static bool is_rational(const impq & n) { + return is_zero(n.y); + } + + inline static + mpq fractional_part(const impq & n) { + lp_assert(is_rational); + return n.x - floor(n.x); + } + void real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& t, explanation & ex); + void int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& t, explanation& ex, mpq & lcm_den); + constraint_index column_upper_bound_constraint(unsigned j) const; + constraint_index column_low_bound_constraint(unsigned j) const; + void display_row_info(std::ostream & out, unsigned row_index) const; + void gomory_cut_adjust_t_and_k_for_size_1(const vector> & pol, lar_term & t, mpq &k); + void gomory_cut_adjust_t_and_k_for_size_gt_1(vector> & pol, lar_term & t, mpq &k, unsigned num_ints, mpq &lcm_den); + bool current_solution_is_inf_on_cut(const lar_term& t, const mpq& k) const; }; } diff --git a/src/util/lp/iterator_on_column.h b/src/util/lp/iterator_on_column.h index 215514b39..a3875deef 100644 --- a/src/util/lp/iterator_on_column.h +++ b/src/util/lp/iterator_on_column.h @@ -6,7 +6,7 @@ #include "util/lp/linear_combination_iterator.h" #include "util/lp/static_matrix.h" #include "util/lp/lar_term.h" -namespace lean { +namespace lp { template struct iterator_on_column:linear_combination_iterator { const vector& m_column; // the offset in term coeffs diff --git a/src/util/lp/iterator_on_indexed_vector.h b/src/util/lp/iterator_on_indexed_vector.h index 532b62617..253661c38 100644 --- a/src/util/lp/iterator_on_indexed_vector.h +++ b/src/util/lp/iterator_on_indexed_vector.h @@ -4,7 +4,7 @@ */ #pragma once #include "util/lp/linear_combination_iterator.h" -namespace lean { +namespace lp { template struct iterator_on_indexed_vector:linear_combination_iterator { const indexed_vector & m_v; diff --git a/src/util/lp/iterator_on_pivot_row.h b/src/util/lp/iterator_on_pivot_row.h index 1a9381a70..cfd0feba4 100644 --- a/src/util/lp/iterator_on_pivot_row.h +++ b/src/util/lp/iterator_on_pivot_row.h @@ -4,7 +4,7 @@ */ #pragma once #include "util/lp/iterator_on_indexed_vector.h" -namespace lean { +namespace lp { template struct iterator_on_pivot_row:linear_combination_iterator { bool m_basis_returned; diff --git a/src/util/lp/iterator_on_row.h b/src/util/lp/iterator_on_row.h index 96a1a8cf3..d5f42340b 100644 --- a/src/util/lp/iterator_on_row.h +++ b/src/util/lp/iterator_on_row.h @@ -4,7 +4,7 @@ */ #pragma once #include "util/lp/linear_combination_iterator.h" -namespace lean { +namespace lp { template struct iterator_on_row:linear_combination_iterator { const vector> & m_row; diff --git a/src/util/lp/iterator_on_term_with_basis_var.h b/src/util/lp/iterator_on_term_with_basis_var.h index 3dd217103..3210b1c27 100644 --- a/src/util/lp/iterator_on_term_with_basis_var.h +++ b/src/util/lp/iterator_on_term_with_basis_var.h @@ -6,7 +6,7 @@ #include "util/lp/linear_combination_iterator.h" #include "util/lp/numeric_pair.h" #include "util/lp/lar_term.h" -namespace lean { +namespace lp { struct iterator_on_term_with_basis_var:linear_combination_iterator { const lar_term & m_term; std::unordered_map::const_iterator m_i; // the offset in term coeffs diff --git a/src/util/lp/lar_constraints.h b/src/util/lp/lar_constraints.h index ee0864a4e..bd11896fb 100644 --- a/src/util/lp/lar_constraints.h +++ b/src/util/lp/lar_constraints.h @@ -12,7 +12,7 @@ #include "util/lp/lp_utils.h" #include "util/lp/ul_pair.h" #include "util/lp/lar_term.h" -namespace lean { +namespace lp { inline lconstraint_kind flip_kind(lconstraint_kind t) { return static_cast( - static_cast(t)); } @@ -25,7 +25,7 @@ inline std::string lconstraint_kind_string(lconstraint_kind t) { case GT: return std::string(">"); case EQ: return std::string("="); } - lean_unreachable(); + lp_unreachable(); return std::string(); // it is unreachable } @@ -74,7 +74,7 @@ public: : lar_base_constraint(kind, right_side), m_coeffs(left_side) {} lar_constraint(const lar_base_constraint & c) { - lean_assert(false); // should not be called : todo! + lp_assert(false); // should not be called : todo! } unsigned size() const { diff --git a/src/util/lp/lar_core_solver.h b/src/util/lp/lar_core_solver.h index 71d69c3a4..01afc866c 100644 --- a/src/util/lp/lar_core_solver.h +++ b/src/util/lp/lar_core_solver.h @@ -18,7 +18,7 @@ #include "util/lp/iterator_on_column.h" #include "util/lp/iterator_on_indexed_vector.h" #include "util/lp/stacked_value.h" -namespace lean { +namespace lp { class lar_core_solver { // m_sign_of_entering is set to 1 if the entering variable needs @@ -168,9 +168,9 @@ public: } void push() { - lean_assert(m_r_solver.basis_heading_is_correct()); - lean_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct()); - lean_assert(m_column_types.size() == m_r_A.column_count()); + lp_assert(m_r_solver.basis_heading_is_correct()); + lp_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct()); + lp_assert(m_column_types.size() == m_r_A.column_count()); m_stacked_simplex_strategy = settings().simplex_strategy(); m_stacked_simplex_strategy.push(); m_column_types.push(); @@ -192,7 +192,7 @@ public: template void push_vector(stacked_vector & pushed_vector, const vector & vector) { - lean_assert(pushed_vector.size() <= vector.size()); + lp_assert(pushed_vector.size() <= vector.size()); for (unsigned i = 0; i < vector.size();i++) { if (i == pushed_vector.size()) { pushed_vector.push_back(vector[i]); @@ -242,8 +242,8 @@ public: pop_basis(k); m_stacked_simplex_strategy.pop(k); settings().simplex_strategy() = m_stacked_simplex_strategy; - lean_assert(m_r_solver.basis_heading_is_correct()); - lean_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct()); + lp_assert(m_r_solver.basis_heading_is_correct()); + lp_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct()); } bool need_to_presolve_with_double_solver() const { @@ -304,11 +304,11 @@ public: break; default: - lean_assert(false); + lp_assert(false); } break; default: - lean_unreachable(); + lp_unreachable(); } m_r_solver.remove_column_from_inf_set(j); return true; @@ -317,7 +317,7 @@ public: void prepare_solver_x_with_signature_tableau(const lar_solution_signature & signature) { - lean_assert(m_r_solver.inf_set_is_correct()); + lp_assert(m_r_solver.inf_set_is_correct()); for (auto &t : signature) { unsigned j = t.first; if (m_r_heading[j] >= 0) @@ -332,9 +332,9 @@ public: m_r_solver.m_x[jb] -= delta * m_r_solver.m_A.get_val(cc); m_r_solver.update_column_in_inf_set(jb); } - lean_assert(m_r_solver.A_mult_x_is_off() == false); + lp_assert(m_r_solver.A_mult_x_is_off() == false); } - lean_assert(m_r_solver.inf_set_is_correct()); + lp_assert(m_r_solver.inf_set_is_correct()); } @@ -342,7 +342,7 @@ public: void prepare_solver_x_with_signature(const lar_solution_signature & signature, lp_primal_core_solver & s) { for (auto &t : signature) { unsigned j = t.first; - lean_assert(m_r_heading[j] < 0); + lp_assert(m_r_heading[j] < 0); auto pos_type = t.second; switch (pos_type) { case at_low_bound: @@ -359,7 +359,7 @@ public: case not_at_bound: switch (m_column_types[j]) { case column_type::free_column: - lean_assert(false); // unreachable + lp_assert(false); // unreachable case column_type::upper_bound: s.m_x[j] = s.m_upper_bounds[j]; break; @@ -377,15 +377,15 @@ public: s.m_x[j] = s.m_low_bounds[j]; break; default: - lean_assert(false); + lp_assert(false); } break; default: - lean_unreachable(); + lp_unreachable(); } } - lean_assert(is_zero_vector(s.m_b)); + lp_assert(is_zero_vector(s.m_b)); s.solve_Ax_eq_b(); } @@ -418,7 +418,7 @@ public: // the queues of delayed indices std::queue entr_q, leav_q; auto * l = cs.m_factorization; - lean_assert(l->get_status() == LU_status::OK); + lp_assert(l->get_status() == LU_status::OK); for (unsigned i = 0; i < trace_of_basis_change.size(); i+= 2) { unsigned entering = trace_of_basis_change[i]; unsigned leaving = trace_of_basis_change[i+1]; @@ -446,8 +446,8 @@ public: continue; } } - lean_assert(cs.m_basis_heading[entering] < 0); - lean_assert(cs.m_basis_heading[leaving] >= 0); + lp_assert(cs.m_basis_heading[entering] < 0); + lp_assert(cs.m_basis_heading[leaving] >= 0); if (l->get_status() == LU_status::OK) { l->prepare_entering(entering, w); // to init vector w l->replace_column(zero_of_type(), w, cs.m_basis_heading[leaving]); @@ -471,7 +471,7 @@ public: void solve_on_signature_tableau(const lar_solution_signature & signature, const vector & changes_of_basis) { r_basis_is_OK(); - lean_assert(settings().use_tableau()); + lp_assert(settings().use_tableau()); bool r = catch_up_in_lu_tableau(changes_of_basis, m_d_solver.m_basis_heading); if (!r) { // it is the case where m_d_solver gives a degenerated basis @@ -490,10 +490,10 @@ public: return; m_r_solver.stop_tracing_basis_changes(); // and now catch up in the double solver - lean_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2); + lp_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2); catch_up_in_lu(m_r_solver.m_trace_of_basis_change_vector, m_r_solver.m_basis_heading, m_d_solver); } - lean_assert(r_basis_is_OK()); + lp_assert(r_basis_is_OK()); } bool adjust_x_of_column(unsigned j) { @@ -507,16 +507,16 @@ public: } m_r_solver.snap_column_to_bound_tableau(j); - lean_assert(m_r_solver.column_is_feasible(j)); + lp_assert(m_r_solver.column_is_feasible(j)); m_r_solver.m_inf_set.erase(j); */ - lean_assert(false); + lp_assert(false); return true; } bool catch_up_in_lu_tableau(const vector & trace_of_basis_change, const vector & basis_heading) { - lean_assert(r_basis_is_OK()); + lp_assert(r_basis_is_OK()); // the queues of delayed indices std::queue entr_q, leav_q; for (unsigned i = 0; i < trace_of_basis_change.size(); i+= 2) { @@ -546,8 +546,8 @@ public: continue; } } - lean_assert(m_r_solver.m_basis_heading[entering] < 0); - lean_assert(m_r_solver.m_basis_heading[leaving] >= 0); + lp_assert(m_r_solver.m_basis_heading[entering] < 0); + lp_assert(m_r_solver.m_basis_heading[leaving] >= 0); m_r_solver.change_basis_unconditionally(entering, leaving); if(!m_r_solver.pivot_column_tableau(entering, m_r_solver.m_basis_heading[entering])) { // unroll the last step @@ -557,12 +557,12 @@ public: #endif m_r_solver.pivot_column_tableau(leaving, m_r_solver.m_basis_heading[leaving]); #ifdef LEAN_DEBUG - lean_assert(t); + lp_assert(t); #endif return false; } } - lean_assert(r_basis_is_OK()); + lp_assert(r_basis_is_OK()); return true; } @@ -572,21 +572,21 @@ public: if (!m_r_solver.m_settings.use_tableau()) return true; for (unsigned j : m_r_solver.m_basis) { - lean_assert(m_r_solver.m_A.m_columns[j].size() == 1); - lean_assert(m_r_solver.m_A.get_val(m_r_solver.m_A.m_columns[j][0]) == one_of_type()); + lp_assert(m_r_solver.m_A.m_columns[j].size() == 1); + lp_assert(m_r_solver.m_A.get_val(m_r_solver.m_A.m_columns[j][0]) == one_of_type()); } for (unsigned j =0; j < m_r_solver.m_basis_heading.size(); j++) { if (m_r_solver.m_basis_heading[j] >= 0) continue; if (m_r_solver.m_column_types[j] == column_type::fixed) continue; - lean_assert(static_cast(- m_r_solver.m_basis_heading[j] - 1) < m_r_solver.m_column_types.size()); - lean_assert( m_r_solver.m_basis_heading[j] <= -1); + lp_assert(static_cast(- m_r_solver.m_basis_heading[j] - 1) < m_r_solver.m_column_types.size()); + lp_assert( m_r_solver.m_basis_heading[j] <= -1); } #endif return true; } void solve_on_signature(const lar_solution_signature & signature, const vector & changes_of_basis) { - lean_assert(!settings().use_tableau()); + lp_assert(!settings().use_tableau()); if (m_r_solver.m_factorization == nullptr) { for (unsigned j = 0; j < changes_of_basis.size(); j+=2) { unsigned entering = changes_of_basis[j]; @@ -615,7 +615,7 @@ public: return; m_r_solver.stop_tracing_basis_changes(); // and now catch up in the double solver - lean_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2); + lp_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2); catch_up_in_lu(m_r_solver.m_trace_of_basis_change_vector, m_r_solver.m_basis_heading, m_d_solver); } } @@ -641,7 +641,7 @@ public: template void extract_signature_from_lp_core_solver(const lp_primal_core_solver & solver, lar_solution_signature & signature) { signature.clear(); - lean_assert(signature.size() == 0); + lp_assert(signature.size() == 0); for (unsigned j = 0; j < solver.m_basis_heading.size(); j++) { if (solver.m_basis_heading[j] < 0) { signature[j] = solver.get_non_basic_column_value_position(j); @@ -664,7 +664,7 @@ public: if (upper_bound_is_set(j)) { const auto & ub = m_r_solver.m_upper_bounds[j]; m_d_upper_bounds[j] = ub.x.get_double() + delta * ub.y.get_double(); - lean_assert(!low_bound_is_set(j) || (m_d_upper_bounds[j] >= m_d_low_bounds[j])); + lp_assert(!low_bound_is_set(j) || (m_d_upper_bounds[j] >= m_d_low_bounds[j])); } } } @@ -729,7 +729,7 @@ public: case column_type::fixed: return true; default: - lean_assert(false); + lp_assert(false); } return false; } @@ -744,20 +744,20 @@ public: case column_type::fixed: return true; default: - lean_assert(false); + lp_assert(false); } return false; } void update_delta(mpq& delta, numeric_pair const& l, numeric_pair const& u) const { - lean_assert(l <= u); + lp_assert(l <= u); if (l.x < u.x && l.y > u.y) { mpq delta1 = (u.x - l.x) / (l.y - u.y); if (delta1 < delta) { delta = delta1; } } - lean_assert(l.x + delta * l.y <= u.x + delta * u.y); + lp_assert(l.x + delta * l.y <= u.x + delta * u.y); } @@ -796,6 +796,37 @@ public: return new iterator_on_indexed_vector(m_r_solver.m_ed); } } + + bool column_is_fixed(unsigned j) const { + return m_column_types()[j] == column_type::fixed || + ( m_column_types()[j] == column_type::boxed && + m_r_solver.m_low_bounds[j] == m_r_solver.m_upper_bounds[j]); + } + + const impq & low_bound(unsigned j) const { + lp_assert(m_column_types()[j] == column_type::fixed || + m_column_types()[j] == column_type::boxed || + m_column_types()[j] == column_type::low_bound); + return m_r_low_bounds[j]; + } + + const impq & upper_bound(unsigned j) const { + lp_assert(m_column_types()[j] == column_type::fixed || + m_column_types()[j] == column_type::boxed || + m_column_types()[j] == column_type::upper_bound); + return m_r_upper_bounds[j]; + } + + const bool column_is_bounded(unsigned j) const { + switch(m_column_types()[j]) { + case column_type::fixed: + case column_type::boxed: + return true; + default: + return false; + } + } + }; } diff --git a/src/util/lp/lar_core_solver.hpp b/src/util/lp/lar_core_solver.hpp index a6dd7e3e0..6f7f7e720 100644 --- a/src/util/lp/lar_core_solver.hpp +++ b/src/util/lp/lar_core_solver.hpp @@ -10,7 +10,7 @@ #include "util/vector.h" #include "util/lp/lar_core_solver.h" #include "util/lp/lar_solution_signature.h" -namespace lean { +namespace lp { lar_core_solver::lar_core_solver( lp_settings & settings, const column_namer & column_names @@ -42,9 +42,9 @@ lar_core_solver::lar_core_solver( column_names){} void lar_core_solver::init_costs(bool first_time) { - lean_assert(false); // should not be called - // lean_assert(this->m_x.size() >= this->m_n()); - // lean_assert(this->m_column_types.size() >= this->m_n()); + lp_assert(false); // should not be called + // lp_assert(this->m_x.size() >= this->m_n()); + // lp_assert(this->m_column_types.size() >= this->m_n()); // if (first_time) // this->m_costs.resize(this->m_n()); // X inf = this->m_infeasibility; @@ -54,7 +54,7 @@ void lar_core_solver::init_costs(bool first_time) { // if (!(first_time || inf >= this->m_infeasibility)) { // LP_OUT(this->m_settings, "iter = " << this->total_iterations() << std::endl); // LP_OUT(this->m_settings, "inf was " << T_to_string(inf) << " and now " << T_to_string(this->m_infeasibility) << std::endl); - // lean_assert(false); + // lp_assert(false); // } // if (inf == this->m_infeasibility) // this->m_iters_with_no_cost_growing++; @@ -105,7 +105,7 @@ void lar_core_solver::init_cost_for_column(unsigned j) { this->m_costs[j] = numeric_traits::zero(); break; default: - lean_assert(false); + lp_assert(false); break; }*/ } @@ -138,30 +138,14 @@ int lar_core_solver::column_is_out_of_bounds(unsigned j) { return 0; break; }*/ - lean_assert(false); + lp_assert(false); return true; } void lar_core_solver::calculate_pivot_row(unsigned i) { - lean_assert(!m_r_solver.use_tableau()); - lean_assert(m_r_solver.m_pivot_row.is_OK()); - m_r_solver.m_pivot_row_of_B_1.clear(); - m_r_solver.m_pivot_row_of_B_1.resize(m_r_solver.m_m()); - m_r_solver.m_pivot_row.clear(); - m_r_solver.m_pivot_row.resize(m_r_solver.m_n()); - if (m_r_solver.m_settings.use_tableau()) { - unsigned basis_j = m_r_solver.m_basis[i]; - for (auto & c : m_r_solver.m_A.m_rows[i]) { - if (c.m_j != basis_j) - m_r_solver.m_pivot_row.set_value(c.get_val(), c.m_j); - } - return; - } - - m_r_solver.calculate_pivot_row_of_B_1(i); - m_r_solver.calculate_pivot_row_when_pivot_row_of_B1_is_ready(i); + m_r_solver.calculate_pivot_row(i); } @@ -208,7 +192,7 @@ void lar_core_solver::calculate_pivot_row(unsigned i) { } void lar_core_solver::fill_not_improvable_zero_sum_from_inf_row() { - lean_assert(m_r_solver.A_mult_x_is_off() == false); + lp_assert(m_r_solver.A_mult_x_is_off() == false); unsigned bj = m_r_basis[m_r_solver.m_inf_row_index_for_tableau]; m_infeasible_sum_sign = m_r_solver.inf_sign_of_column(bj); m_infeasible_linear_combination.clear(); @@ -243,32 +227,32 @@ void lar_core_solver::fill_not_improvable_zero_sum() { void lar_core_solver::solve() { - lean_assert(m_r_solver.non_basic_columns_are_set_correctly()); - lean_assert(m_r_solver.inf_set_is_correct()); + lp_assert(m_r_solver.non_basic_columns_are_set_correctly()); + lp_assert(m_r_solver.inf_set_is_correct()); if (m_r_solver.current_x_is_feasible() && m_r_solver.m_look_for_feasible_solution_only) { - m_r_solver.set_status(OPTIMAL); + m_r_solver.set_status(lp_status::OPTIMAL); return; } ++settings().st().m_need_to_solve_inf; - lean_assert(!m_r_solver.A_mult_x_is_off()); - lean_assert((!settings().use_tableau()) || r_basis_is_OK()); + lp_assert(!m_r_solver.A_mult_x_is_off()); + lp_assert((!settings().use_tableau()) || r_basis_is_OK()); if (need_to_presolve_with_double_solver()) { prefix_d(); lar_solution_signature solution_signature; vector changes_of_basis = find_solution_signature_with_doubles(solution_signature); - if (m_d_solver.get_status() == TIME_EXHAUSTED) { - m_r_solver.set_status(TIME_EXHAUSTED); + if (m_d_solver.get_status() == lp_status::TIME_EXHAUSTED) { + m_r_solver.set_status(lp_status::TIME_EXHAUSTED); return; } if (settings().use_tableau()) solve_on_signature_tableau(solution_signature, changes_of_basis); else solve_on_signature(solution_signature, changes_of_basis); - lean_assert(!settings().use_tableau() || r_basis_is_OK()); + lp_assert(!settings().use_tableau() || r_basis_is_OK()); } else { if (!settings().use_tableau()) { bool snapped = m_r_solver.snap_non_basic_x_to_bound(); - lean_assert(m_r_solver.non_basic_columns_are_set_correctly()); + lp_assert(m_r_solver.non_basic_columns_are_set_correctly()); if (snapped) m_r_solver.solve_Ax_eq_b(); } @@ -276,16 +260,16 @@ void lar_core_solver::solve() { m_r_solver.find_feasible_solution(); else m_r_solver.solve(); - lean_assert(!settings().use_tableau() || r_basis_is_OK()); + lp_assert(!settings().use_tableau() || r_basis_is_OK()); } - if (m_r_solver.get_status() == INFEASIBLE) { + if (m_r_solver.get_status() == lp_status::INFEASIBLE) { fill_not_improvable_zero_sum(); - } else if (m_r_solver.get_status() != UNBOUNDED) { - m_r_solver.set_status(OPTIMAL); + } else if (m_r_solver.get_status() != lp_status::UNBOUNDED) { + m_r_solver.set_status(lp_status::OPTIMAL); } - lean_assert(r_basis_is_OK()); - lean_assert(m_r_solver.non_basic_columns_are_set_correctly()); - lean_assert(m_r_solver.inf_set_is_correct()); + lp_assert(r_basis_is_OK()); + lp_assert(m_r_solver.non_basic_columns_are_set_correctly()); + lp_assert(m_r_solver.inf_set_is_correct()); } diff --git a/src/util/lp/lar_solution_signature.h b/src/util/lp/lar_solution_signature.h index 2c4169c81..6c8598a73 100644 --- a/src/util/lp/lar_solution_signature.h +++ b/src/util/lp/lar_solution_signature.h @@ -8,6 +8,6 @@ #include "util/debug.h" #include "util/lp/lp_settings.h" #include -namespace lean { +namespace lp { typedef std::unordered_map lar_solution_signature; } diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index 882ce229e..e7ef4f748 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -1,10 +1,10 @@ #include "util/lp/lar_solver.h" /* Copyright (c) 2017 Microsoft Corporation - Author: Lev Nachmanson + Author: Nikolaj Bjorner, Lev Nachmanson */ -namespace lean { +namespace lp { unsigned lar_solver::constraint_count() const { return m_constraints.size(); @@ -23,14 +23,24 @@ lp_settings & lar_solver::settings() { return m_settings;} lp_settings const & lar_solver::settings() const { return m_settings;} -void clear() {lean_assert(false); // not implemented +void clear() {lp_assert(false); // not implemented } -lar_solver::lar_solver() : m_status(OPTIMAL), +lar_solver::lar_solver() : m_status(lp_status::OPTIMAL), m_infeasible_column_index(-1), m_terms_start_index(1000000), - m_mpq_lar_core_solver(m_settings, *this) + m_mpq_lar_core_solver(m_settings, *this), + m_tracker_of_x_change([&](unsigned j, const impq & x){ + if (!var_is_int(j)) { + lp_assert(m_inf_int_set.contains(j) == false); + return; + } + if (m_mpq_lar_core_solver.m_r_x[j].is_int()) + m_inf_int_set.erase(j); + else + m_inf_int_set.insert(j); + }) { } @@ -52,7 +62,7 @@ bool lar_solver::is_term(var_index j) const { } unsigned lar_solver::adjust_term_index(unsigned j) const { - lean_assert(is_term(j)); + lp_assert(is_term(j)); return j - m_terms_start_index; } @@ -60,10 +70,10 @@ unsigned lar_solver::adjust_term_index(unsigned j) const { bool lar_solver::use_lu() const { return m_settings.simplex_strategy() == simplex_strategy_enum::lu; } bool lar_solver::sizes_are_correct() const { - lean_assert(strategy_is_undecided() || !m_mpq_lar_core_solver.need_to_presolve_with_double_solver() || A_r().column_count() == A_d().column_count()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_column_types.size()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_x.size()); + lp_assert(strategy_is_undecided() || !m_mpq_lar_core_solver.need_to_presolve_with_double_solver() || A_r().column_count() == A_d().column_count()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_column_types.size()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_x.size()); return true; } @@ -105,7 +115,7 @@ bool lar_solver::implied_bound_is_correctly_explained(implied_bound const & be, else if (kind == LE || kind == LT) n_of_L++; rs_of_evidence += coeff*constr.m_right_side; } - lean_assert(n_of_G == 0 || n_of_L == 0); + lp_assert(n_of_G == 0 || n_of_L == 0); lconstraint_kind kind = n_of_G ? GE : (n_of_L ? LE : EQ); if (strict) kind = static_cast((static_cast(kind) / 2)); @@ -149,7 +159,7 @@ bool lar_solver::implied_bound_is_correctly_explained(implied_bound const & be, void lar_solver::analyze_new_bounds_on_row( unsigned row_index, bound_propagator & bp) { - lean_assert(!use_tableau()); + lp_assert(!use_tableau()); iterator_on_pivot_row it(m_mpq_lar_core_solver.get_pivot_row(), m_mpq_lar_core_solver.m_r_basis[row_index]); bound_analyzer_on_row ra_pos(it, @@ -168,7 +178,7 @@ void lar_solver::analyze_new_bounds_on_row_tableau( if (A_r().m_rows[row_index].size() > settings().max_row_length_for_bound_propagation) return; iterator_on_row it(A_r().m_rows[row_index]); - lean_assert(use_tableau()); + lp_assert(use_tableau()); bound_analyzer_on_row::analyze_row(it, zero_of_type>(), row_index, @@ -201,7 +211,7 @@ void lar_solver::calculate_implied_bounds_for_row(unsigned i, bound_propagator & linear_combination_iterator * lar_solver::create_new_iter_from_term(unsigned term_index) const { - lean_assert(false); // not implemented + lp_assert(false); // not implemented return nullptr; // new linear_combination_iterator_on_vector(m_terms[adjust_term_index(term_index)]->coeffs_as_vector()); } @@ -212,7 +222,7 @@ unsigned lar_solver::adjust_column_index_to_term_index(unsigned j) const { } void lar_solver::propagate_bounds_on_a_term(const lar_term& t, bound_propagator & bp, unsigned term_offset) { - lean_assert(false); // not implemented + lp_assert(false); // not implemented } @@ -223,7 +233,7 @@ void lar_solver::explain_implied_bound(implied_bound & ib, bound_propagator & bp unsigned m_j = ib.m_j; if (is_term(m_j)) { auto it = m_ext_vars_to_columns.find(m_j); - lean_assert(it != m_ext_vars_to_columns.end()); + lp_assert(it != m_ext_vars_to_columns.end()); m_j = it->second.ext_j(); } for (auto const& r : A_r().m_rows[i]) { @@ -232,22 +242,22 @@ void lar_solver::explain_implied_bound(implied_bound & ib, bound_propagator & bp if (j == m_j) continue; if (is_term(j)) { auto it = m_ext_vars_to_columns.find(j); - lean_assert(it != m_ext_vars_to_columns.end()); + lp_assert(it != m_ext_vars_to_columns.end()); j = it->second.ext_j(); } int a_sign = is_pos(a)? 1: -1; int sign = j_sign * a_sign; - const ul_pair & ul = m_vars_to_ul_pairs[j]; + const ul_pair & ul = m_columns_to_ul_pairs[j]; auto witness = sign > 0? ul.upper_bound_witness(): ul.low_bound_witness(); - lean_assert(is_valid(witness)); + lp_assert(is_valid(witness)); bp.consume(a, witness); } - // lean_assert(implied_bound_is_correctly_explained(ib, explanation)); + // lp_assert(implied_bound_is_correctly_explained(ib, explanation)); } bool lar_solver::term_is_used_as_row(unsigned term) const { - lean_assert(is_term(term)); + lp_assert(is_term(term)); return contains(m_ext_vars_to_columns, term); } @@ -279,20 +289,33 @@ lp_status lar_solver::get_status() const { return m_status;} void lar_solver::set_status(lp_status s) {m_status = s;} +bool lar_solver::has_int_var() const { + return m_mpq_lar_core_solver.m_r_solver.m_tracker_of_x_change != nullptr; +} + lp_status lar_solver::find_feasible_solution() { + m_settings.st().m_make_feasible++; + if (A_r().column_count() > m_settings.st().m_max_cols) + m_settings.st().m_max_cols = A_r().column_count(); + if (A_r().row_count() > m_settings.st().m_max_rows) + m_settings.st().m_max_rows = A_r().row_count(); if (strategy_is_undecided()) decide_on_strategy_and_adjust_initial_state(); + if (has_int_var()) { + m_inf_int_set.resize(A_r().column_count()); + } + m_mpq_lar_core_solver.m_r_solver.m_look_for_feasible_solution_only = true; return solve(); } lp_status lar_solver::solve() { - if (m_status == INFEASIBLE) { + if (m_status == lp_status::INFEASIBLE) { return m_status; } solve_with_core_solver(); - if (m_status != INFEASIBLE) { + if (m_status != lp_status::INFEASIBLE) { if (m_settings.bound_propagation()) detect_rows_with_changed_bounds(); } @@ -304,16 +327,13 @@ lp_status lar_solver::solve() { void lar_solver::fill_explanation_from_infeasible_column(vector> & evidence) const{ // this is the case when the lower bound is in conflict with the upper one - const ul_pair & ul = m_vars_to_ul_pairs[m_infeasible_column_index]; + const ul_pair & ul = m_columns_to_ul_pairs[m_infeasible_column_index]; evidence.push_back(std::make_pair(numeric_traits::one(), ul.upper_bound_witness())); evidence.push_back(std::make_pair(-numeric_traits::one(), ul.low_bound_witness())); } unsigned lar_solver::get_total_iterations() const { return m_mpq_lar_core_solver.m_r_solver.total_iterations(); } -// see http://research.microsoft.com/projects/z3/smt07.pdf -// This method searches for a feasible solution with as many different values of variables, reverenced in vars, as it can find -// Attention, after a call to this method the non-basic variables don't necesserarly stick to their bounds anymore vector lar_solver::get_list_of_all_var_indices() const { vector ret; for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_heading.size(); j++) @@ -323,8 +343,7 @@ vector lar_solver::get_list_of_all_var_indices() const { void lar_solver::push() { m_simplex_strategy = m_settings.simplex_strategy(); m_simplex_strategy.push(); - m_status.push(); - m_vars_to_ul_pairs.push(); + m_columns_to_ul_pairs.push(); m_infeasible_column_index.push(); m_mpq_lar_core_solver.push(); m_term_count = m_terms.size(); @@ -333,7 +352,7 @@ void lar_solver::push() { m_constraint_count.push(); } -void lar_solver::clean_large_elements_after_pop(unsigned n, int_set& set) { +void lar_solver::clean_popped_elements(unsigned n, int_set& set) { vector to_remove; for (unsigned j: set.m_index) if (j >= n) @@ -343,35 +362,36 @@ void lar_solver::clean_large_elements_after_pop(unsigned n, int_set& set) { } void lar_solver::shrink_inf_set_after_pop(unsigned n, int_set & set) { - clean_large_elements_after_pop(n, set); + clean_popped_elements(n, set); set.resize(n); } void lar_solver::pop(unsigned k) { + TRACE("lar_solver", tout << "k = " << k << std::endl;); + int n_was = static_cast(m_ext_vars_to_columns.size()); - m_status.pop(k); m_infeasible_column_index.pop(k); - unsigned n = m_vars_to_ul_pairs.peek_size(k); + unsigned n = m_columns_to_ul_pairs.peek_size(k); for (unsigned j = n_was; j-- > n;) m_ext_vars_to_columns.erase(m_columns_to_ext_vars_or_term_indices[j]); m_columns_to_ext_vars_or_term_indices.resize(n); if (m_settings.use_tableau()) { pop_tableau(); } - m_vars_to_ul_pairs.pop(k); + m_columns_to_ul_pairs.pop(k); m_mpq_lar_core_solver.pop(k); - clean_large_elements_after_pop(n, m_columns_with_changed_bound); + clean_popped_elements(n, m_columns_with_changed_bound); unsigned m = A_r().row_count(); - clean_large_elements_after_pop(m, m_rows_with_changed_bounds); + clean_popped_elements(m, m_rows_with_changed_bounds); clean_inf_set_of_r_solver_after_pop(); - lean_assert(m_settings.simplex_strategy() == simplex_strategy_enum::undecided || + lp_assert(m_settings.simplex_strategy() == simplex_strategy_enum::undecided || (!use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); - lean_assert(ax_is_correct()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.inf_set_is_correct()); + lp_assert(ax_is_correct()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.inf_set_is_correct()); m_constraint_count.pop(k); for (unsigned i = m_constraint_count; i < m_constraints.size(); i++) delete m_constraints[i]; @@ -384,8 +404,10 @@ void lar_solver::pop(unsigned k) { m_terms.resize(m_term_count); m_simplex_strategy.pop(k); m_settings.simplex_strategy() = m_simplex_strategy; - lean_assert(sizes_are_correct()); - lean_assert((!m_settings.use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + lp_assert(sizes_are_correct()); + lp_assert((!m_settings.use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + m_status = m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()? lp_status::OPTIMAL: lp_status::UNKNOWN; + } vector lar_solver::get_all_constraint_indices() const { @@ -402,7 +424,7 @@ bool lar_solver::maximize_term_on_tableau(const vector decide_on_strategy_and_adjust_initial_state(); m_mpq_lar_core_solver.solve(); - if (m_mpq_lar_core_solver.m_r_solver.get_status() == UNBOUNDED) + if (m_mpq_lar_core_solver.m_r_solver.get_status() == lp_status::UNBOUNDED) return false; term_max = 0; @@ -414,13 +436,13 @@ bool lar_solver::maximize_term_on_tableau(const vector bool lar_solver::costs_are_zeros_for_r_solver() const { for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_solver.m_costs.size(); j++) { - lean_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_costs[j])); + lp_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_costs[j])); } return true; } bool lar_solver::reduced_costs_are_zeroes_for_r_solver() const { for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_solver.m_d.size(); j++) { - lean_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_d[j])); + lp_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_d[j])); } return true; } @@ -428,7 +450,7 @@ bool lar_solver::reduced_costs_are_zeroes_for_r_solver() const { void lar_solver::set_costs_to_zero(const vector> & term) { auto & rslv = m_mpq_lar_core_solver.m_r_solver; auto & jset = m_mpq_lar_core_solver.m_r_solver.m_inf_set; // hijack this set that should be empty right now - lean_assert(jset.m_index.size()==0); + lp_assert(jset.m_index.size()==0); for (auto & p : term) { unsigned j = p.second; @@ -447,16 +469,16 @@ void lar_solver::set_costs_to_zero(const vector> & ter jset.clear(); - lean_assert(reduced_costs_are_zeroes_for_r_solver()); - lean_assert(costs_are_zeros_for_r_solver()); + lp_assert(reduced_costs_are_zeroes_for_r_solver()); + lp_assert(costs_are_zeros_for_r_solver()); } void lar_solver::prepare_costs_for_r_solver(const vector> & term) { auto & rslv = m_mpq_lar_core_solver.m_r_solver; rslv.m_using_infeas_costs = false; - lean_assert(costs_are_zeros_for_r_solver()); - lean_assert(reduced_costs_are_zeroes_for_r_solver()); + lp_assert(costs_are_zeros_for_r_solver()); + lp_assert(reduced_costs_are_zeroes_for_r_solver()); rslv.m_costs.resize(A_r().column_count(), zero_of_type()); for (auto & p : term) { unsigned j = p.second; @@ -466,7 +488,7 @@ void lar_solver::prepare_costs_for_r_solver(const vector> & term, @@ -480,7 +502,7 @@ bool lar_solver::maximize_term_on_corrected_r_solver(const vector> & term, impq &term_max) { - lean_assert(m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()); m_mpq_lar_core_solver.m_r_solver.m_look_for_feasible_solution_only = false; return maximize_term_on_corrected_r_solver(term, term_max); } @@ -512,7 +534,7 @@ bool lar_solver::maximize_term(const vector> & term, const lar_term & lar_solver::get_term(unsigned j) const { - lean_assert(j >= m_terms_start_index); + lp_assert(j >= m_terms_start_index); return *m_terms[j - m_terms_start_index]; } @@ -527,18 +549,18 @@ void lar_solver::pop_core_solver_params(unsigned k) { void lar_solver::set_upper_bound_witness(var_index j, constraint_index ci) { - ul_pair ul = m_vars_to_ul_pairs[j]; + ul_pair ul = m_columns_to_ul_pairs[j]; ul.upper_bound_witness() = ci; - m_vars_to_ul_pairs[j] = ul; + m_columns_to_ul_pairs[j] = ul; } void lar_solver::set_low_bound_witness(var_index j, constraint_index ci) { - ul_pair ul = m_vars_to_ul_pairs[j]; + ul_pair ul = m_columns_to_ul_pairs[j]; ul.low_bound_witness() = ci; - m_vars_to_ul_pairs[j] = ul; + m_columns_to_ul_pairs[j] = ul; } -void lar_solver::register_one_coeff_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j) { +void lar_solver::register_monoid_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j) { auto it = coeffs.find(j); if (it == coeffs.end()) { coeffs[j] = a; @@ -549,18 +571,18 @@ void lar_solver::register_one_coeff_in_map(std::unordered_map & void lar_solver::substitute_terms_in_linear_expression(const vector>& left_side_with_terms, - vector> &left_side, mpq & right_side) const { + vector> &left_side, mpq & free_coeff) const { std::unordered_map coeffs; for (auto & t : left_side_with_terms) { unsigned j = t.second; if (!is_term(j)) { - register_one_coeff_in_map(coeffs, t.first, j); + register_monoid_in_map(coeffs, t.first, j); } else { const lar_term & term = * m_terms[adjust_term_index(t.second)]; for (auto & p : term.coeffs()){ - register_one_coeff_in_map(coeffs, t.first * p.second , p.first); + register_monoid_in_map(coeffs, t.first * p.second , p.first); } - right_side += t.first * term.m_v; + free_coeff += t.first * term.m_v; } } @@ -574,7 +596,7 @@ void lar_solver::detect_rows_of_bound_change_column_for_nbasic_column(unsigned j m_column_buffer.resize(A_r().row_count()); else m_column_buffer.clear(); - lean_assert(m_column_buffer.size() == 0 && m_column_buffer.is_OK()); + lp_assert(m_column_buffer.size() == 0 && m_column_buffer.is_OK()); m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer); for (unsigned i : m_column_buffer.m_index) @@ -608,7 +630,7 @@ void lar_solver::detect_rows_of_column_with_bound_change(unsigned j) { } void lar_solver::adjust_x_of_column(unsigned j) { - lean_assert(false); + lp_assert(false); } bool lar_solver::row_is_correct(unsigned i) const { @@ -643,6 +665,10 @@ void lar_solver::change_basic_x_by_delta_on_column(unsigned j, const numeric_pai m_basic_columns_with_changed_cost.insert(bj); } m_mpq_lar_core_solver.m_r_solver.update_column_in_inf_set(bj); + TRACE("change_x_del", + tout << "changed basis column " << bj << ", it is " << + ( m_mpq_lar_core_solver.m_r_solver.column_is_feasible(bj)? "feas":"inf") << std::endl;); + } } else { m_column_buffer.clear(); @@ -697,14 +723,14 @@ void lar_solver::update_x_and_inf_costs_for_columns_with_changed_bounds() { } void lar_solver::update_x_and_inf_costs_for_columns_with_changed_bounds_tableau() { - lean_assert(ax_is_correct()); + lp_assert(ax_is_correct()); for (auto j : m_columns_with_changed_bound.m_index) update_x_and_inf_costs_for_column_with_changed_bounds(j); if (tableau_with_costs()) { for (unsigned j : m_basic_columns_with_changed_cost.m_index) m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); - lean_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); } } @@ -726,7 +752,7 @@ void lar_solver::solve_with_core_solver() { update_x_and_inf_costs_for_columns_with_changed_bounds(); m_mpq_lar_core_solver.solve(); set_status(m_mpq_lar_core_solver.m_r_solver.get_status()); - lean_assert(m_status != OPTIMAL || all_constraints_hold()); + lp_assert(m_status != lp_status::OPTIMAL || all_constraints_hold()); } @@ -751,7 +777,7 @@ numeric_pair lar_solver::get_basic_var_value_from_row(unsigned i) { numeric_pair r = zero_of_type>(); m_mpq_lar_core_solver.calculate_pivot_row(i); for (unsigned j : m_mpq_lar_core_solver.m_r_solver.m_pivot_row.m_index) { - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); r -= m_mpq_lar_core_solver.m_r_solver.m_pivot_row.m_data[j] * m_mpq_lar_core_solver.m_r_x[j]; } return r; @@ -815,12 +841,12 @@ unsigned lar_solver::constraint_stack_size() const { } void lar_solver::fill_last_row_of_A_r(static_matrix> & A, const lar_term * ls) { - lean_assert(A.row_count() > 0); - lean_assert(A.column_count() > 0); + lp_assert(A.row_count() > 0); + lp_assert(A.column_count() > 0); unsigned last_row = A.row_count() - 1; - lean_assert(A.m_rows[last_row].size() == 0); + lp_assert(A.m_rows[last_row].size() == 0); for (auto & t : ls->m_coeffs) { - lean_assert(!is_zero(t.second)); + lp_assert(!is_zero(t.second)); var_index j = t.first; A.set(last_row, j, - t.second); } @@ -830,7 +856,7 @@ void lar_solver::fill_last_row_of_A_r(static_matrix> & A, template void lar_solver::create_matrix_A(static_matrix & matr) { - lean_assert(false); // not implemented + lp_assert(false); // not implemented /* unsigned m = number_or_nontrivial_left_sides(); unsigned n = m_vec_of_canonic_left_sides.size(); @@ -891,7 +917,7 @@ bool lar_solver::all_constraints_hold() const { if (m_settings.get_cancel_flag()) return true; std::unordered_map var_map; - get_model(var_map); + get_model_do_not_care_about_diff_vars(var_map); for (unsigned i = 0; i < m_constraints.size(); i++) { if (!constraint_holds(*m_constraints[i], var_map)) { @@ -911,7 +937,7 @@ bool lar_solver::constraint_holds(const lar_base_constraint & constr, std::unord case GT: return left_side_val > constr.m_right_side; case EQ: return left_side_val == constr.m_right_side; default: - lean_unreachable(); + lp_unreachable(); } return false; // it is unreachable } @@ -956,7 +982,7 @@ bool lar_solver::the_left_sides_sum_to_zero(const vector>& explanation) const { #ifdef LEAN_DEBUG lconstraint_kind kind; - lean_assert(the_relations_are_of_same_type(explanation, kind)); - lean_assert(the_left_sides_sum_to_zero(explanation)); + lp_assert(the_relations_are_of_same_type(explanation, kind)); + lp_assert(the_left_sides_sum_to_zero(explanation)); mpq rs = sum_of_right_sides_of_explanation(explanation); switch (kind) { - case LE: lean_assert(rs < zero_of_type()); + case LE: lp_assert(rs < zero_of_type()); break; - case LT: lean_assert(rs <= zero_of_type()); + case LT: lp_assert(rs <= zero_of_type()); break; - case GE: lean_assert(rs > zero_of_type()); + case GE: lp_assert(rs > zero_of_type()); break; - case GT: lean_assert(rs >= zero_of_type()); + case GT: lp_assert(rs >= zero_of_type()); break; - case EQ: lean_assert(rs != zero_of_type()); + case EQ: lp_assert(rs != zero_of_type()); break; default: - lean_assert(false); + lp_assert(false); return false; } #endif @@ -1025,7 +1051,7 @@ mpq lar_solver::sum_of_right_sides_of_explanation(const vectorm_right_side - m_constraints[con_ind]->get_free_coeff_of_left_side()) * coeff; } return ret; @@ -1033,11 +1059,11 @@ mpq lar_solver::sum_of_right_sides_of_explanation(const vector= m_vars_to_ul_pairs.size()) { + if (var >= m_columns_to_ul_pairs.size()) { // TBD: bounds on terms could also be used, caller may have to track these. return false; } - const ul_pair & ul = m_vars_to_ul_pairs[var]; + const ul_pair & ul = m_columns_to_ul_pairs[var]; ci = ul.low_bound_witness(); if (ci != static_cast(-1)) { auto& p = m_mpq_lar_core_solver.m_r_low_bounds()[var]; @@ -1052,11 +1078,11 @@ bool lar_solver::has_lower_bound(var_index var, constraint_index& ci, mpq& value bool lar_solver::has_upper_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) { - if (var >= m_vars_to_ul_pairs.size()) { + if (var >= m_columns_to_ul_pairs.size()) { // TBD: bounds on terms could also be used, caller may have to track these. return false; } - const ul_pair & ul = m_vars_to_ul_pairs[var]; + const ul_pair & ul = m_columns_to_ul_pairs[var]; ci = ul.upper_bound_witness(); if (ci != static_cast(-1)) { auto& p = m_mpq_lar_core_solver.m_r_upper_bounds()[var]; @@ -1082,7 +1108,7 @@ void lar_solver::get_infeasibility_explanation(vector & variable_values) const { mpq delta = mpq(1, 2); // start from 0.5 to have less clashes - lean_assert(m_status == OPTIMAL); + lp_assert(m_status == lp_status::OPTIMAL); unsigned i; do { @@ -1131,6 +1157,16 @@ void lar_solver::get_model(std::unordered_map & variable_values) } while (i != m_mpq_lar_core_solver.m_r_x.size()); } +void lar_solver::get_model_do_not_care_about_diff_vars(std::unordered_map & variable_values) const { + mpq delta = mpq(1); + delta = m_mpq_lar_core_solver.find_delta_for_strict_bounds(delta); + for (unsigned i = 0; i < m_mpq_lar_core_solver.m_r_x.size(); i++ ) { + const impq & rp = m_mpq_lar_core_solver.m_r_x[i]; + variable_values[i] = rp.x + delta * rp.y; + } +} + + std::string lar_solver::get_variable_name(var_index vi) const { return get_column_name(vi); } @@ -1174,12 +1210,19 @@ void lar_solver::print_term(lar_term const& term, std::ostream & out) const { print_linear_combination_of_column_indices(term.coeffs_as_vector(), out); } +void lar_solver::print_term_as_indices(lar_term const& term, std::ostream & out) const { + if (!numeric_traits::is_zero(term.m_v)) { + out << term.m_v << " + "; + } + print_linear_combination_of_column_indices_only(term.coeffs_as_vector(), out); +} + mpq lar_solver::get_left_side_val(const lar_base_constraint & cns, const std::unordered_map & var_map) const { mpq ret = cns.get_free_coeff_of_left_side(); for (auto & it : cns.get_left_side_coefficients()) { var_index j = it.second; auto vi = var_map.find(j); - lean_assert(vi != var_map.end()); + lp_assert(vi != var_map.end()); ret += it.first * vi->second; } return ret; @@ -1211,7 +1254,7 @@ void lar_solver::random_update(unsigned sz, var_index const * vars) { } -void lar_solver::try_pivot_fixed_vars_from_basis() { +void lar_solver::pivot_fixed_vars_from_basis() { m_mpq_lar_core_solver.m_r_solver.pivot_fixed_vars_from_basis(); } @@ -1220,12 +1263,12 @@ void lar_solver::pop() { } bool lar_solver::column_represents_row_in_tableau(unsigned j) { - return m_vars_to_ul_pairs()[j].m_i != static_cast(-1); + return m_columns_to_ul_pairs()[j].m_i != static_cast(-1); } void lar_solver::make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j) { // i, j - is the indices of the bottom-right element of the tableau - lean_assert(A_r().row_count() == i + 1 && A_r().column_count() == j + 1); + lp_assert(A_r().row_count() == i + 1 && A_r().column_count() == j + 1); auto & last_column = A_r().m_columns[j]; int non_zero_column_cell_index = -1; for (unsigned k = last_column.size(); k-- > 0;){ @@ -1235,13 +1278,13 @@ void lar_solver::make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsign non_zero_column_cell_index = k; } - lean_assert(non_zero_column_cell_index != -1); - lean_assert(static_cast(non_zero_column_cell_index) != i); + lp_assert(non_zero_column_cell_index != -1); + lp_assert(static_cast(non_zero_column_cell_index) != i); m_mpq_lar_core_solver.m_r_solver.transpose_rows_tableau(last_column[non_zero_column_cell_index].m_i, i); } void lar_solver::remove_last_row_and_column_from_tableau(unsigned j) { - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); auto & slv = m_mpq_lar_core_solver.m_r_solver; unsigned i = A_r().row_count() - 1; //last row index make_sure_that_the_bottom_right_elem_not_zero_in_tableau(i, j); @@ -1260,17 +1303,17 @@ void lar_solver::remove_last_row_and_column_from_tableau(unsigned j) { A_r().remove_element(last_row, rc); } - lean_assert(last_row.size() == 0); - lean_assert(A_r().m_columns[j].size() == 0); + lp_assert(last_row.size() == 0); + lp_assert(A_r().m_columns[j].size() == 0); A_r().m_rows.pop_back(); A_r().m_columns.pop_back(); slv.m_b.pop_back(); } void lar_solver::remove_last_column_from_tableau(unsigned j) { - lean_assert(j == A_r().column_count() - 1); + lp_assert(j == A_r().column_count() - 1); // the last column has to be empty - lean_assert(A_r().m_columns[j].size() == 0); + lp_assert(A_r().m_columns[j].size() == 0); A_r().m_columns.pop_back(); } @@ -1279,7 +1322,7 @@ void lar_solver::remove_last_column_from_basis_tableau(unsigned j) { int i = rslv.m_basis_heading[j]; if (i >= 0) { // j is a basic var int last_pos = static_cast(rslv.m_basis.size()) - 1; - lean_assert(last_pos >= 0); + lp_assert(last_pos >= 0); if (i != last_pos) { unsigned j_at_last_pos = rslv.m_basis[last_pos]; rslv.m_basis[i] = j_at_last_pos; @@ -1288,7 +1331,7 @@ void lar_solver::remove_last_column_from_basis_tableau(unsigned j) { rslv.m_basis.pop_back(); // remove j from the basis } else { int last_pos = static_cast(rslv.m_nbasis.size()) - 1; - lean_assert(last_pos >= 0); + lp_assert(last_pos >= 0); i = - 1 - i; if (i != last_pos) { unsigned j_at_last_pos = rslv.m_nbasis[last_pos]; @@ -1298,14 +1341,14 @@ void lar_solver::remove_last_column_from_basis_tableau(unsigned j) { rslv.m_nbasis.pop_back(); // remove j from the basis } rslv.m_basis_heading.pop_back(); - lean_assert(rslv.m_basis.size() == A_r().row_count()); - lean_assert(rslv.basis_heading_is_correct()); + lp_assert(rslv.m_basis.size() == A_r().row_count()); + lp_assert(rslv.basis_heading_is_correct()); } void lar_solver::remove_column_from_tableau(unsigned j) { auto& rslv = m_mpq_lar_core_solver.m_r_solver; - lean_assert(j == A_r().column_count() - 1); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + lp_assert(j == A_r().column_count() - 1); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); if (column_represents_row_in_tableau(j)) { remove_last_row_and_column_from_tableau(j); if (rslv.m_basis_heading[j] < 0) @@ -1319,27 +1362,27 @@ void lar_solver::remove_column_from_tableau(unsigned j) { rslv.m_costs.pop_back(); remove_last_column_from_basis_tableau(j); - lean_assert(m_mpq_lar_core_solver.r_basis_is_OK()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + lp_assert(m_mpq_lar_core_solver.r_basis_is_OK()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); } void lar_solver::pop_tableau() { - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); // We remove last variables starting from m_column_names.size() to m_vec_of_canonic_left_sides.size(). // At this moment m_column_names is already popped for (unsigned j = A_r().column_count(); j-- > m_columns_to_ext_vars_or_term_indices.size();) remove_column_from_tableau(j); - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); } void lar_solver::clean_inf_set_of_r_solver_after_pop() { vector became_feas; - clean_large_elements_after_pop(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.m_inf_set); + clean_popped_elements(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.m_inf_set); std::unordered_set basic_columns_with_changed_cost; auto inf_index_copy = m_mpq_lar_core_solver.m_r_solver.m_inf_set.m_index; for (auto j: inf_index_copy) { @@ -1354,14 +1397,14 @@ void lar_solver::clean_inf_set_of_r_solver_after_pop() { } for (unsigned j : became_feas) { - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); m_mpq_lar_core_solver.m_r_solver.m_d[j] -= m_mpq_lar_core_solver.m_r_solver.m_costs[j]; m_mpq_lar_core_solver.m_r_solver.m_costs[j] = zero_of_type(); m_mpq_lar_core_solver.m_r_solver.m_inf_set.erase(j); } became_feas.clear(); for (unsigned j : m_mpq_lar_core_solver.m_r_solver.m_inf_set.m_index) { - lean_assert(m_mpq_lar_core_solver.m_r_heading[j] >= 0); + lp_assert(m_mpq_lar_core_solver.m_r_heading[j] >= 0); if (m_mpq_lar_core_solver.m_r_solver.column_is_feasible(j)) became_feas.push_back(j); } @@ -1374,25 +1417,666 @@ void lar_solver::clean_inf_set_of_r_solver_after_pop() { m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); for (unsigned j : basic_columns_with_changed_cost) m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); - lean_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); } } void lar_solver::shrink_explanation_to_minimum(vector> & explanation) const { // implementing quickXplain quick_xplain::run(explanation, *this); - lean_assert(this->explanation_is_correct(explanation)); + lp_assert(this->explanation_is_correct(explanation)); } -final_check_status lar_solver::check_int_feasibility() { +bool lar_solver::model_is_int_feasible() const { unsigned n = A_r().column_count(); for (unsigned j = 0; j < n; j++) { - if (column_is_integer(j) && column_value_is_integer(j)) - continue; - return final_check_status::GIVEUP; + if (column_is_int(j) && !column_value_is_integer(j)) + return false; } - return final_check_status::DONE; + return true; +} + +bool lar_solver::term_is_int(const lar_term * t) const { + for (auto const & p : t->m_coeffs) + if (! (column_is_int(p.first) && p.second.is_int())) + return false; + return t->m_v.is_int(); +} + +bool lar_solver::var_is_int(var_index v) const { + if (is_term(v)) { + lar_term const& t = get_term(v); + return term_is_int(&t); + } + else { + return column_is_int(v); + } +} + +bool lar_solver::column_is_int(unsigned j) const { + unsigned ext_var = m_columns_to_ext_vars_or_term_indices[j]; + lp_assert(contains(m_ext_vars_to_columns, ext_var)); + return m_ext_vars_to_columns.find(ext_var)->second.is_integer(); +} + +bool lar_solver::column_is_fixed(unsigned j) const { + return m_mpq_lar_core_solver.column_is_fixed(j); +} + + +bool lar_solver::ext_var_is_int(var_index ext_var) const { + auto it = m_ext_vars_to_columns.find(ext_var); + lp_assert(it != m_ext_vars_to_columns.end()); + return it == m_ext_vars_to_columns.end() || it->second.is_integer(); +} + + // below is the initialization functionality of lar_solver + +bool lar_solver::strategy_is_undecided() const { + return m_settings.simplex_strategy() == simplex_strategy_enum::undecided; +} + +var_index lar_solver::add_var(unsigned ext_j, bool is_int) { + TRACE("add_var", tout << "adding var " << ext_j << (is_int? " int" : " nonint") << std::endl;); + var_index i; + lp_assert(ext_j < m_terms_start_index); + + if (ext_j >= m_terms_start_index) + throw 0; // todo : what is the right way to exit? + auto it = m_ext_vars_to_columns.find(ext_j); + if (it != m_ext_vars_to_columns.end()) { + return it->second.ext_j(); + } + lp_assert(m_columns_to_ul_pairs.size() == A_r().column_count()); + i = A_r().column_count(); + m_columns_to_ul_pairs.push_back(ul_pair(static_cast(-1))); + add_non_basic_var_to_core_fields(ext_j, is_int); + lp_assert(sizes_are_correct()); + if (is_int) { + m_mpq_lar_core_solver.m_r_solver.set_tracker_of_x(& m_tracker_of_x_change); + } + return i; +} + +void lar_solver::register_new_ext_var_index(unsigned ext_v, bool is_int) { + lp_assert(!contains(m_ext_vars_to_columns, ext_v)); + unsigned j = static_cast(m_ext_vars_to_columns.size()); + m_ext_vars_to_columns.insert(std::make_pair(ext_v, ext_var_info(j, is_int))); + lp_assert(m_columns_to_ext_vars_or_term_indices.size() == j); + m_columns_to_ext_vars_or_term_indices.push_back(ext_v); +} + +void lar_solver::add_non_basic_var_to_core_fields(unsigned ext_j, bool is_int) { + register_new_ext_var_index(ext_j, is_int); + m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column); + m_columns_with_changed_bound.increase_size_by_one(); + add_new_var_to_core_fields_for_mpq(false); + if (use_lu()) + add_new_var_to_core_fields_for_doubles(false); +} + +void lar_solver::add_new_var_to_core_fields_for_doubles(bool register_in_basis) { + unsigned j = A_d().column_count(); + A_d().add_column(); + lp_assert(m_mpq_lar_core_solver.m_d_x.size() == j); + // lp_assert(m_mpq_lar_core_solver.m_d_low_bounds.size() == j && m_mpq_lar_core_solver.m_d_upper_bounds.size() == j); // restore later + m_mpq_lar_core_solver.m_d_x.resize(j + 1); + m_mpq_lar_core_solver.m_d_low_bounds.resize(j + 1); + m_mpq_lar_core_solver.m_d_upper_bounds.resize(j + 1); + lp_assert(m_mpq_lar_core_solver.m_d_heading.size() == j); // as A().column_count() on the entry to the method + if (register_in_basis) { + A_d().add_row(); + m_mpq_lar_core_solver.m_d_heading.push_back(m_mpq_lar_core_solver.m_d_basis.size()); + m_mpq_lar_core_solver.m_d_basis.push_back(j); + } + else { + m_mpq_lar_core_solver.m_d_heading.push_back(-static_cast(m_mpq_lar_core_solver.m_d_nbasis.size()) - 1); + m_mpq_lar_core_solver.m_d_nbasis.push_back(j); + } +} + +void lar_solver::add_new_var_to_core_fields_for_mpq(bool register_in_basis) { + unsigned j = A_r().column_count(); + A_r().add_column(); + lp_assert(m_mpq_lar_core_solver.m_r_x.size() == j); + // lp_assert(m_mpq_lar_core_solver.m_r_low_bounds.size() == j && m_mpq_lar_core_solver.m_r_upper_bounds.size() == j); // restore later + m_mpq_lar_core_solver.m_r_x.resize(j + 1); + m_mpq_lar_core_solver.m_r_low_bounds.increase_size_by_one(); + m_mpq_lar_core_solver.m_r_upper_bounds.increase_size_by_one(); + m_mpq_lar_core_solver.m_r_solver.m_inf_set.increase_size_by_one(); + m_mpq_lar_core_solver.m_r_solver.m_costs.resize(j + 1); + m_mpq_lar_core_solver.m_r_solver.m_d.resize(j + 1); + lp_assert(m_mpq_lar_core_solver.m_r_heading.size() == j); // as A().column_count() on the entry to the method + if (register_in_basis) { + A_r().add_row(); + m_mpq_lar_core_solver.m_r_heading.push_back(m_mpq_lar_core_solver.m_r_basis.size()); + m_mpq_lar_core_solver.m_r_basis.push_back(j); + if (m_settings.bound_propagation()) + m_rows_with_changed_bounds.insert(A_r().row_count() - 1); + } + else { + m_mpq_lar_core_solver.m_r_heading.push_back(-static_cast(m_mpq_lar_core_solver.m_r_nbasis.size()) - 1); + m_mpq_lar_core_solver.m_r_nbasis.push_back(j); + } } -} // namespace lean + + +var_index lar_solver::add_term_undecided(const vector> & coeffs, + const mpq &m_v) { + m_terms.push_back(new lar_term(coeffs, m_v)); + return m_terms_start_index + m_terms.size() - 1; +} + +// terms +var_index lar_solver::add_term(const vector> & coeffs, + const mpq &m_v) { + if (strategy_is_undecided()) + return add_term_undecided(coeffs, m_v); + + m_terms.push_back(new lar_term(coeffs, m_v)); + unsigned adjusted_term_index = m_terms.size() - 1; + var_index ret = m_terms_start_index + adjusted_term_index; + if (use_tableau() && !coeffs.empty()) { + add_row_for_term(m_terms.back(), ret); + if (m_settings.bound_propagation()) + m_rows_with_changed_bounds.insert(A_r().row_count() - 1); + } + lp_assert(m_ext_vars_to_columns.size() == A_r().column_count()); + return ret; +} + +void lar_solver::add_row_for_term(const lar_term * term, unsigned term_ext_index) { + lp_assert(sizes_are_correct()); + add_row_from_term_no_constraint(term, term_ext_index); + lp_assert(sizes_are_correct()); +} + +void lar_solver::add_row_from_term_no_constraint(const lar_term * term, unsigned term_ext_index) { + register_new_ext_var_index(term_ext_index, term_is_int(term)); + // j will be a new variable + unsigned j = A_r().column_count(); + ul_pair ul(j); + m_columns_to_ul_pairs.push_back(ul); + add_basic_var_to_core_fields(); + if (use_tableau()) { + auto it = iterator_on_term_with_basis_var(*term, j); + A_r().fill_last_row_with_pivoting(it, + m_mpq_lar_core_solver.m_r_solver.m_basis_heading); + m_mpq_lar_core_solver.m_r_solver.m_b.resize(A_r().column_count(), zero_of_type()); + } + else { + fill_last_row_of_A_r(A_r(), term); + } + m_mpq_lar_core_solver.m_r_x[j] = get_basic_var_value_from_row_directly(A_r().row_count() - 1); + if (use_lu()) + fill_last_row_of_A_d(A_d(), term); +} + +void lar_solver::add_basic_var_to_core_fields() { + bool use_lu = m_mpq_lar_core_solver.need_to_presolve_with_double_solver(); + lp_assert(!use_lu || A_r().column_count() == A_d().column_count()); + m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column); + m_columns_with_changed_bound.increase_size_by_one(); + m_rows_with_changed_bounds.increase_size_by_one(); + add_new_var_to_core_fields_for_mpq(true); + if (use_lu) + add_new_var_to_core_fields_for_doubles(true); +} + +bool lar_solver::bound_is_integer_if_needed(unsigned j, const mpq & right_side) const { + if (!column_is_int(j)) + return true; + return right_side.is_int(); +} + +constraint_index lar_solver::add_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side) { + TRACE("lar_solver", tout << "j = " << j << std::endl;); + constraint_index ci = m_constraints.size(); + if (!is_term(j)) { // j is a var + lp_assert(bound_is_integer_if_needed(j, right_side)); + auto vc = new lar_var_constraint(j, kind, right_side); + m_constraints.push_back(vc); + update_column_type_and_bound(j, kind, right_side, ci); + } + else { + add_var_bound_on_constraint_for_term(j, kind, right_side, ci); + } + lp_assert(sizes_are_correct()); + return ci; +} + +void lar_solver::update_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index) { + switch (m_mpq_lar_core_solver.m_column_types[j]) { + case column_type::free_column: + update_free_column_type_and_bound(j, kind, right_side, constr_index); + break; + case column_type::boxed: + update_boxed_column_type_and_bound(j, kind, right_side, constr_index); + break; + case column_type::low_bound: + update_low_bound_column_type_and_bound(j, kind, right_side, constr_index); + break; + case column_type::upper_bound: + update_upper_bound_column_type_and_bound(j, kind, right_side, constr_index); + break; + case column_type::fixed: + update_fixed_column_type_and_bound(j, kind, right_side, constr_index); + break; + default: + lp_assert(false); // cannot be here + } +} + +void lar_solver::add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { + lp_assert(is_term(j)); + unsigned adjusted_term_index = adjust_term_index(j); + lp_assert(!term_is_int(m_terms[adjusted_term_index]) || right_side.is_int()); + auto it = m_ext_vars_to_columns.find(j); + if (it != m_ext_vars_to_columns.end()) { + unsigned term_j = it->second.ext_j(); + mpq rs = right_side - m_terms[adjusted_term_index]->m_v; + m_constraints.push_back(new lar_term_constraint(m_terms[adjusted_term_index], kind, right_side)); + update_column_type_and_bound(term_j, kind, rs, ci); + } + else { + add_constraint_from_term_and_create_new_column_row(j, m_terms[adjusted_term_index], kind, right_side); + } +} + +constraint_index lar_solver::add_constraint(const vector>& left_side_with_terms, lconstraint_kind kind_par, const mpq& right_side_parm) { + vector> left_side; + mpq rs = -right_side_parm; + substitute_terms_in_linear_expression(left_side_with_terms, left_side, rs); + unsigned term_index = add_term(left_side, zero_of_type()); + constraint_index ci = m_constraints.size(); + add_var_bound_on_constraint_for_term(term_index, kind_par, -rs, ci); + return ci; +} + +void lar_solver::add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term, + lconstraint_kind kind, const mpq & right_side) { + + add_row_from_term_no_constraint(term, term_j); + unsigned j = A_r().column_count() - 1; + update_column_type_and_bound(j, kind, right_side - term->m_v, m_constraints.size()); + m_constraints.push_back(new lar_term_constraint(term, kind, right_side)); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); +} + +void lar_solver::decide_on_strategy_and_adjust_initial_state() { + lp_assert(strategy_is_undecided()); + if (m_columns_to_ul_pairs.size() > m_settings.column_number_threshold_for_using_lu_in_lar_solver) { + m_settings.simplex_strategy() = simplex_strategy_enum::lu; + } + else { + m_settings.simplex_strategy() = simplex_strategy_enum::tableau_rows; // todo: when to switch to tableau_costs? + } + adjust_initial_state(); +} + +void lar_solver::adjust_initial_state() { + switch (m_settings.simplex_strategy()) { + case simplex_strategy_enum::lu: + adjust_initial_state_for_lu(); + break; + case simplex_strategy_enum::tableau_rows: + adjust_initial_state_for_tableau_rows(); + break; + case simplex_strategy_enum::tableau_costs: + lp_assert(false); // not implemented + case simplex_strategy_enum::undecided: + adjust_initial_state_for_tableau_rows(); + break; + } +} + +void lar_solver::adjust_initial_state_for_lu() { + copy_from_mpq_matrix(A_d()); + unsigned n = A_d().column_count(); + m_mpq_lar_core_solver.m_d_x.resize(n); + m_mpq_lar_core_solver.m_d_low_bounds.resize(n); + m_mpq_lar_core_solver.m_d_upper_bounds.resize(n); + m_mpq_lar_core_solver.m_d_heading = m_mpq_lar_core_solver.m_r_heading; + m_mpq_lar_core_solver.m_d_basis = m_mpq_lar_core_solver.m_r_basis; + + /* + unsigned j = A_d().column_count(); + A_d().add_column(); + lp_assert(m_mpq_lar_core_solver.m_d_x.size() == j); + // lp_assert(m_mpq_lar_core_solver.m_d_low_bounds.size() == j && m_mpq_lar_core_solver.m_d_upper_bounds.size() == j); // restore later + m_mpq_lar_core_solver.m_d_x.resize(j + 1 ); + m_mpq_lar_core_solver.m_d_low_bounds.resize(j + 1); + m_mpq_lar_core_solver.m_d_upper_bounds.resize(j + 1); + lp_assert(m_mpq_lar_core_solver.m_d_heading.size() == j); // as A().column_count() on the entry to the method + if (register_in_basis) { + A_d().add_row(); + m_mpq_lar_core_solver.m_d_heading.push_back(m_mpq_lar_core_solver.m_d_basis.size()); + m_mpq_lar_core_solver.m_d_basis.push_back(j); + }else { + m_mpq_lar_core_solver.m_d_heading.push_back(- static_cast(m_mpq_lar_core_solver.m_d_nbasis.size()) - 1); + m_mpq_lar_core_solver.m_d_nbasis.push_back(j); + }*/ +} + +void lar_solver::adjust_initial_state_for_tableau_rows() { + for (unsigned j = 0; j < m_terms.size(); j++) { + if (contains(m_ext_vars_to_columns, j + m_terms_start_index)) + continue; + add_row_from_term_no_constraint(m_terms[j], j + m_terms_start_index); + } +} + +// this fills the last row of A_d and sets the basis column: -1 in the last column of the row +void lar_solver::fill_last_row_of_A_d(static_matrix & A, const lar_term* ls) { + lp_assert(A.row_count() > 0); + lp_assert(A.column_count() > 0); + unsigned last_row = A.row_count() - 1; + lp_assert(A.m_rows[last_row].empty()); + + for (auto & t : ls->m_coeffs) { + lp_assert(!is_zero(t.second)); + var_index j = t.first; + A.set(last_row, j, -t.second.get_double()); + } + + unsigned basis_j = A.column_count() - 1; + A.set(last_row, basis_j, -1); +} + +void lar_solver::update_free_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_ind) { + mpq y_of_bound(0); + switch (kind) { + case LT: + y_of_bound = -1; + case LE: + m_mpq_lar_core_solver.m_column_types[j] = column_type::upper_bound; + lp_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); + lp_assert(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j); + { + auto up = numeric_pair(right_side, y_of_bound); + m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; + } + set_upper_bound_witness(j, constr_ind); + break; + case GT: + y_of_bound = 1; + case GE: + m_mpq_lar_core_solver.m_column_types[j] = column_type::low_bound; + lp_assert(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j); + { + auto low = numeric_pair(right_side, y_of_bound); + m_mpq_lar_core_solver.m_r_low_bounds[j] = low; + } + set_low_bound_witness(j, constr_ind); + break; + case EQ: + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = numeric_pair(right_side, zero_of_type()); + set_upper_bound_witness(j, constr_ind); + set_low_bound_witness(j, constr_ind); + break; + + default: + lp_unreachable(); + + } + m_columns_with_changed_bound.insert(j); +} + +void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { + lp_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); + mpq y_of_bound(0); + switch (kind) { + case LT: + y_of_bound = -1; + case LE: + { + auto up = numeric_pair(right_side, y_of_bound); + if (up < m_mpq_lar_core_solver.m_r_upper_bounds()[j]) { + m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; + set_upper_bound_witness(j, ci); + m_columns_with_changed_bound.insert(j); + } + } + break; + case GT: + y_of_bound = 1; + case GE: + m_mpq_lar_core_solver.m_column_types[j] = column_type::boxed; + { + auto low = numeric_pair(right_side, y_of_bound); + m_mpq_lar_core_solver.m_r_low_bounds[j] = low; + set_low_bound_witness(j, ci); + m_columns_with_changed_bound.insert(j); + if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + } + else { + m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j] ? column_type::boxed : column_type::fixed; + } + } + break; + case EQ: + { + auto v = numeric_pair(right_side, zero_of_type()); + if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = lp_status::INFEASIBLE; + set_low_bound_witness(j, ci); + m_infeasible_column_index = j; + } + else { + m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; + m_columns_with_changed_bound.insert(j); + set_low_bound_witness(j, ci); + set_upper_bound_witness(j, ci); + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + } + break; + } + break; + + default: + lp_unreachable(); + + } +} + +void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { + lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::boxed && m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j])); + mpq y_of_bound(0); + switch (kind) { + case LT: + y_of_bound = -1; + case LE: + { + auto up = numeric_pair(right_side, y_of_bound); + if (up < m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; + set_upper_bound_witness(j, ci); + m_columns_with_changed_bound.insert(j); + } + + if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = lp_status::INFEASIBLE; + lp_assert(false); + m_infeasible_column_index = j; + } + else { + if (m_mpq_lar_core_solver.m_r_low_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j]) + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + } + } + break; + case GT: + y_of_bound = 1; + case GE: + { + auto low = numeric_pair(right_side, y_of_bound); + if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_mpq_lar_core_solver.m_r_low_bounds[j] = low; + m_columns_with_changed_bound.insert(j); + set_low_bound_witness(j, ci); + } + if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + } + else if (low == m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + } + } + break; + case EQ: + { + auto v = numeric_pair(right_side, zero_of_type()); + if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + set_upper_bound_witness(j, ci); + } + else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + set_low_bound_witness(j, ci); + } + else { + m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; + set_low_bound_witness(j, ci); + set_upper_bound_witness(j, ci); + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + m_columns_with_changed_bound.insert(j); + } + + break; + } + + default: + lp_unreachable(); + + } +} +void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { + lp_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::low_bound); + mpq y_of_bound(0); + switch (kind) { + case LT: + y_of_bound = -1; + case LE: + { + auto up = numeric_pair(right_side, y_of_bound); + m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; + set_upper_bound_witness(j, ci); + m_columns_with_changed_bound.insert(j); + + if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + } + else { + m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j] ? column_type::boxed : column_type::fixed; + } + } + break; + case GT: + y_of_bound = 1; + case GE: + { + auto low = numeric_pair(right_side, y_of_bound); + if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_mpq_lar_core_solver.m_r_low_bounds[j] = low; + m_columns_with_changed_bound.insert(j); + set_low_bound_witness(j, ci); + } + } + break; + case EQ: + { + auto v = numeric_pair(right_side, zero_of_type()); + if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + set_upper_bound_witness(j, ci); + } + else { + m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; + set_low_bound_witness(j, ci); + set_upper_bound_witness(j, ci); + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + } + m_columns_with_changed_bound.insert(j); + break; + } + + default: + lp_unreachable(); + + } +} + +void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { + lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::fixed && m_mpq_lar_core_solver.m_r_low_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j])); + lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_r_low_bounds()[j].y.is_zero() && m_mpq_lar_core_solver.m_r_upper_bounds()[j].y.is_zero())); + auto v = numeric_pair(right_side, mpq(0)); + + mpq y_of_bound(0); + switch (kind) { + case LT: + if (v <= m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + set_upper_bound_witness(j, ci); + } + break; + case LE: + { + if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + set_upper_bound_witness(j, ci); + } + } + break; + case GT: + { + if (v >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + set_low_bound_witness(j, ci); + } + } + break; + case GE: + { + if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + set_low_bound_witness(j, ci); + } + } + break; + case EQ: + { + if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + set_upper_bound_witness(j, ci); + } + else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = lp_status::INFEASIBLE; + m_infeasible_column_index = j; + set_low_bound_witness(j, ci); + } + break; + } + + default: + lp_unreachable(); + + } +} + + +} // namespace lp diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 02ded6a72..e584c2f26 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -1,6 +1,6 @@ /* Copyright (c) 2017 Microsoft Corporation - Author: Lev Nachmanson + Author: Nikolaj Bjorner, Lev Nachmanson */ #pragma once #include "util/vector.h" @@ -33,7 +33,8 @@ #include "util/lp/int_solver.h" #include "util/lp/nra_solver.h" -namespace lean { +namespace lp { + class lar_solver : public column_namer { @@ -48,11 +49,11 @@ class lar_solver : public column_namer { }; //////////////////// fields ////////////////////////// lp_settings m_settings; - stacked_value m_status; + lp_status m_status; stacked_value m_simplex_strategy; std::unordered_map m_ext_vars_to_columns; vector m_columns_to_ext_vars_or_term_indices; - stacked_vector m_vars_to_ul_pairs; + stacked_vector m_columns_to_ul_pairs; vector m_constraints; stacked_value m_constraint_count; // the set of column indices j such that bounds have changed for j @@ -68,7 +69,8 @@ public: lar_core_solver m_mpq_lar_core_solver; unsigned constraint_count() const; const lar_base_constraint& get_constraint(unsigned ci) const; - + std::function m_tracker_of_x_change; + int_set m_inf_int_set; ////////////////// methods //////////////////////////////// static_matrix> & A_r(); static_matrix> const & A_r() const; @@ -77,7 +79,8 @@ public: static bool valid_index(unsigned j){ return static_cast(j) >= 0;} - + bool column_is_int(unsigned j) const; + bool column_is_fixed(unsigned j) const; public: // init region @@ -85,9 +88,15 @@ public: var_index add_var(unsigned ext_j, bool is_integer); - void register_new_ext_var_index(unsigned ext_v); + void register_new_ext_var_index(unsigned ext_v, bool is_int); - void add_non_basic_var_to_core_fields(unsigned ext_j); + bool term_is_int(const lar_term * t) const; + + bool var_is_int(var_index v) const; + + bool ext_var_is_int(var_index ext_var) const; + + void add_non_basic_var_to_core_fields(unsigned ext_j, bool is_int); void add_new_var_to_core_fields_for_doubles(bool register_in_basis); @@ -143,7 +152,6 @@ public: void clear(); - lar_solver(); void set_propagate_bounds_on_pivoted_rows_mode(bool v); @@ -215,7 +223,7 @@ public: vector get_list_of_all_var_indices() const; void push(); - static void clean_large_elements_after_pop(unsigned n, int_set& set); + static void clean_popped_elements(unsigned n, int_set& set); static void shrink_inf_set_after_pop(unsigned n, int_set & set); @@ -256,7 +264,7 @@ public: void substitute_terms_in_linear_expression( const vector>& left_side_with_terms, - vector> &left_side, mpq & right_side) const; + vector> &left_side, mpq & free_coeff) const; void detect_rows_of_bound_change_column_for_nbasic_column(unsigned j); @@ -321,11 +329,10 @@ public: template void copy_from_mpq_matrix(static_matrix & matr); + column_type get_column_type(const column_info & ci); bool try_to_set_fixed(column_info & ci); - column_type get_column_type(const column_info & ci); - std::string get_column_name(unsigned j) const; bool all_constrained_variables_are_registered(const vector>& left_side); @@ -336,7 +343,7 @@ public: bool the_relations_are_of_same_type(const vector> & evidence, lconstraint_kind & the_kind_of_sum) const; static void register_in_map(std::unordered_map & coeffs, const lar_base_constraint & cn, const mpq & a); - static void register_one_coeff_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j); + static void register_monoid_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j); bool the_left_sides_sum_to_zero(const vector> & evidence) const; @@ -362,9 +369,9 @@ public: int inf_sign) const; - void get_model(std::unordered_map & variable_values) const; + void get_model_do_not_care_about_diff_vars(std::unordered_map & variable_values) const; std::string get_variable_name(var_index vi) const; @@ -373,12 +380,14 @@ public: void print_constraints(std::ostream& out) const ; - void print_terms(std::ostream& out) const ; + void print_terms(std::ostream& out) const; void print_left_side_of_constraint(const lar_base_constraint * c, std::ostream & out) const; void print_term(lar_term const& term, std::ostream & out) const; + void print_term_as_indices(lar_term const& term, std::ostream & out) const; + mpq get_left_side_val(const lar_base_constraint & cns, const std::unordered_map & var_map) const; void print_constraint(const lar_base_constraint * c, std::ostream & out) const; @@ -386,7 +395,7 @@ public: void fill_var_set_for_random_update(unsigned sz, var_index const * vars, vector& column_list); void random_update(unsigned sz, var_index const * vars); - void try_pivot_fixed_vars_from_basis(); + void pivot_fixed_vars_from_basis(); void pop(); bool column_represents_row_in_tableau(unsigned j); void make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j); @@ -398,23 +407,74 @@ public: void pop_tableau(); void clean_inf_set_of_r_solver_after_pop(); void shrink_explanation_to_minimum(vector> & explanation) const; - inline - bool column_is_integer(unsigned j) const { - unsigned ext_var = m_columns_to_ext_vars_or_term_indices[j]; - return m_ext_vars_to_columns.find(ext_var)->second.is_integer(); - } - static bool impq_is_int(const impq& v) { - return v.x.is_int() && is_zero(v.y); - } - inline + bool column_value_is_integer(unsigned j) const { const impq & v = m_mpq_lar_core_solver.m_r_x[j]; - return impq_is_int(v); + return v.is_int(); } - inline bool column_is_real(unsigned j) const { return !column_is_integer(j); } - final_check_status check_int_feasibility(); + bool column_is_real(unsigned j) const { + return !column_is_int(j); + } + + bool model_is_int_feasible() const; + + const impq & column_low_bound(unsigned j) const { + return m_mpq_lar_core_solver.low_bound(j); + } + + const impq & column_upper_bound(unsigned j) const { + return m_mpq_lar_core_solver.upper_bound(j); + } + + bool column_is_bounded(unsigned j) const { + return m_mpq_lar_core_solver.column_is_bounded(j); + } + + void get_bound_constraint_witnesses_for_column(unsigned j, constraint_index & lc, constraint_index & uc) const { + const ul_pair & ul = m_columns_to_ul_pairs[j]; + lc = ul.low_bound_witness(); + uc = ul.upper_bound_witness(); + } + indexed_vector & get_column_in_lu_mode(unsigned j) { + m_column_buffer.clear(); + m_column_buffer.resize(A_r().row_count()); + m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer); + return m_column_buffer; + } + + bool bound_is_integer_if_needed(unsigned j, const mpq & right_side) const; + linear_combination_iterator * get_iterator_on_row(unsigned i) { + return m_mpq_lar_core_solver.m_r_solver.get_iterator_on_row(i); + } + + unsigned get_base_column_in_row(unsigned row_index) const { + return m_mpq_lar_core_solver.m_r_solver.get_base_column_in_row(row_index); + } + + constraint_index get_column_upper_bound_witness(unsigned j) const { + return m_columns_to_ul_pairs()[j].upper_bound_witness(); + } + + constraint_index get_column_low_bound_witness(unsigned j) const { + return m_columns_to_ul_pairs()[j].low_bound_witness(); + } + + void subs_term_columns(lar_term& t) { + vector > pol; + for (const auto & m : t.m_coeffs) { + pol.push_back(std::make_pair(m.second, adjust_column_index_to_term_index(m.first))); + } + mpq v = t.m_v; + vector> pol_after_subs; + // todo : remove the call to substitute_terms_in_linear_expression, when theory_lra handles the terms indices + substitute_terms_in_linear_expression(pol, pol_after_subs, v); + t.clear(); + t = lar_term(pol_after_subs, v); + } + + bool has_int_var() const; }; } diff --git a/src/util/lp/lar_solver_instances.cpp b/src/util/lp/lar_solver_instances.cpp index ccde7e574..602df0326 100644 --- a/src/util/lp/lar_solver_instances.cpp +++ b/src/util/lp/lar_solver_instances.cpp @@ -4,12 +4,8 @@ */ #include "util/lp/lar_solver.cpp" -#include "util/lp/init_lar_solver.cpp" - - - -template void lean::lar_solver::copy_from_mpq_matrix(class lean::static_matrix &); +template void lp::lar_solver::copy_from_mpq_matrix(class lp::static_matrix &); diff --git a/src/util/lp/lar_term.h b/src/util/lp/lar_term.h index 0e715ad0b..10e58dafa 100644 --- a/src/util/lp/lar_term.h +++ b/src/util/lp/lar_term.h @@ -4,13 +4,13 @@ */ #pragma once #include "util/lp/indexed_vector.h" -namespace lean { +namespace lp { struct lar_term { // the term evaluates to sum of m_coeffs + m_v std::unordered_map m_coeffs; mpq m_v; lar_term() {} - void add_to_map(unsigned j, const mpq& c) { + void add_monoid(const mpq& c, unsigned j) { auto it = m_coeffs.find(j); if (it == m_coeffs.end()) { m_coeffs.emplace(j, c); @@ -21,6 +21,10 @@ struct lar_term { } } + bool is_empty() const { + return m_coeffs.size() == 0 && is_zero(m_v); + } + unsigned size() const { return static_cast(m_coeffs.size()); } const std::unordered_map & coeffs() const { @@ -30,7 +34,7 @@ struct lar_term { lar_term(const vector>& coeffs, const mpq & v) : m_v(v) { for (const auto & p : coeffs) { - add_to_map(p.second, p.first); + add_monoid(p.first, p.second); } } bool operator==(const lar_term & a) const { return false; } // take care not to create identical terms @@ -52,7 +56,7 @@ struct lar_term { if (it == m_coeffs.end()) return; const mpq & b = it->second; for (unsigned it_j :li.m_index) { - add_to_map(it_j, - b * li.m_data[it_j]); + add_monoid(- b * li.m_data[it_j], it_j); } m_coeffs.erase(it); } @@ -60,5 +64,26 @@ struct lar_term { bool contains(unsigned j) const { return m_coeffs.find(j) != m_coeffs.end(); } + + void negate() { + for (auto & t : m_coeffs) + t.second.neg(); + } + + template + T apply(const vector& x) const { + T ret = T(m_v); + for (const auto & t : m_coeffs) { + ret += t.second * x[t.first]; + } + return ret; + } + + + void clear() { + m_coeffs.clear(); + m_v = zero_of_type(); + } + }; } diff --git a/src/util/lp/linear_combination_iterator.h b/src/util/lp/linear_combination_iterator.h index 634accfd4..d8a67f1b8 100644 --- a/src/util/lp/linear_combination_iterator.h +++ b/src/util/lp/linear_combination_iterator.h @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #pragma once -namespace lean { +namespace lp { template struct linear_combination_iterator { virtual bool next(T & a, unsigned & i) = 0; diff --git a/src/util/lp/lp_core_solver_base.h b/src/util/lp/lp_core_solver_base.h index a12b7b5d2..0a07055a4 100644 --- a/src/util/lp/lp_core_solver_base.h +++ b/src/util/lp/lp_core_solver_base.h @@ -13,7 +13,10 @@ #include "util/lp/lu.h" #include "util/lp/permutation_matrix.h" #include "util/lp/column_namer.h" -namespace lean { +#include "util/lp/iterator_on_row.h" +#include "util/lp/iterator_on_pivot_row.h" + +namespace lp { template // X represents the type of the x variable and the bounds class lp_core_solver_base { @@ -23,7 +26,14 @@ class lp_core_solver_base { private: lp_status m_status; public: - bool current_x_is_feasible() const { return m_inf_set.size() == 0; } + bool current_x_is_feasible() const { + TRACE("feas", + if (m_inf_set.size()) { + tout << "column " << m_inf_set.m_index[0] << " is infeasible" << std::endl; + } + ); + return m_inf_set.size() == 0; + } bool current_x_is_infeasible() const { return m_inf_set.size() != 0; } int_set m_inf_set; bool m_using_infeas_costs; @@ -59,6 +69,12 @@ public: bool m_tracing_basis_changes; int_set* m_pivoted_rows; bool m_look_for_feasible_solution_only; + std::function * m_tracker_of_x_change; + + void set_tracker_of_x(std::function* tracker) { + m_tracker_of_x_change = tracker; + } + void start_tracing_basis_changes() { m_trace_of_basis_change_vector.resize(0); m_tracing_basis_changes = true; @@ -182,11 +198,11 @@ public: bool need_to_pivot_to_basis_tableau() const { - lean_assert(m_A.is_correct()); + lp_assert(m_A.is_correct()); unsigned m = m_A.row_count(); for (unsigned i = 0; i < m; i++) { unsigned bj = m_basis[i]; - lean_assert(m_A.m_columns[bj].size() > 0); + lp_assert(m_A.m_columns[bj].size() > 0); if (m_A.m_columns[bj].size() > 1 || m_A.get_val(m_A.m_columns[bj][0]) != one_of_type()) return true; } return false; @@ -195,7 +211,7 @@ public: bool reduced_costs_are_correct_tableau() const { if (m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows) return true; - lean_assert(m_A.is_correct()); + lp_assert(m_A.is_correct()); if (m_using_infeas_costs) { if (infeasibility_costs_are_correct() == false) { std::cout << "infeasibility_costs_are_correct() does not hold" << std::endl; @@ -370,11 +386,11 @@ public: } bool make_column_feasible(unsigned j, numeric_pair & delta) { - lean_assert(m_basis_heading[j] < 0); + lp_assert(m_basis_heading[j] < 0); auto & x = m_x[j]; switch (m_column_types[j]) { case column_type::fixed: - lean_assert(m_low_bounds[j] == m_upper_bounds[j]); + lp_assert(m_low_bounds[j] == m_upper_bounds[j]); if (x != m_low_bounds[j]) { delta = m_low_bounds[j] - x; x = m_low_bounds[j]; @@ -410,7 +426,7 @@ public: case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); break; } return false; @@ -429,6 +445,7 @@ public: void init_lu(); int pivots_in_column_and_row_are_different(int entering, int leaving) const; void pivot_fixed_vars_from_basis(); + bool pivot_column_general(unsigned j, unsigned j_basic, indexed_vector & w); bool pivot_for_tableau_on_basis(); bool pivot_row_for_tableau_on_basis(unsigned row); void init_basic_part_of_basis_heading() { @@ -458,7 +475,7 @@ public: } void change_basis_unconditionally(unsigned entering, unsigned leaving) { - lean_assert(m_basis_heading[entering] < 0); + lp_assert(m_basis_heading[entering] < 0); int place_in_non_basis = -1 - m_basis_heading[entering]; if (static_cast(place_in_non_basis) >= m_nbasis.size()) { // entering variable in not in m_nbasis, we need to put it back; @@ -477,7 +494,8 @@ public: } void change_basis(unsigned entering, unsigned leaving) { - lean_assert(m_basis_heading[entering] < 0); + lp_assert(m_basis_heading[entering] < 0); + lp_assert(m_basis_heading[leaving] >= 0); int place_in_basis = m_basis_heading[leaving]; int place_in_non_basis = - m_basis_heading[entering] - 1; @@ -518,7 +536,7 @@ public: case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); break; } return true; @@ -566,10 +584,10 @@ public: case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); } - std::cout << "basis heading = " << m_basis_heading[j] << std::endl; - std::cout << "x = " << m_x[j] << std::endl; + out << "basis heading = " << m_basis_heading[j] << std::endl; + out << "x = " << m_x[j] << std::endl; /* std::cout << "cost = " << m_costs[j] << std::endl; std:: cout << "m_d = " << m_d[j] << std::endl;*/ @@ -658,24 +676,28 @@ public: void update_column_in_inf_set(unsigned j) { if (column_is_feasible(j)) { - m_inf_set.erase(j); + remove_column_from_inf_set(j); } else { - m_inf_set.insert(j); + insert_column_into_inf_set(j); } } void insert_column_into_inf_set(unsigned j) { + if (m_tracker_of_x_change != nullptr) + (*m_tracker_of_x_change)(j, m_x[j]); m_inf_set.insert(j); - lean_assert(!column_is_feasible(j)); + lp_assert(!column_is_feasible(j)); } void remove_column_from_inf_set(unsigned j) { + if (m_tracker_of_x_change != nullptr) + (*m_tracker_of_x_change)(j, m_x[j]); m_inf_set.erase(j); - lean_assert(column_is_feasible(j)); + lp_assert(column_is_feasible(j)); } bool costs_on_nbasis_are_zeros() const { - lean_assert(this->basis_heading_is_correct()); + lp_assert(this->basis_heading_is_correct()); for (unsigned j = 0; j < this->m_n(); j++) { if (this->m_basis_heading[j] < 0) - lean_assert(is_zero(this->m_costs[j])); + lp_assert(is_zero(this->m_costs[j])); } return true; } @@ -686,5 +708,17 @@ public: const unsigned & iters_with_no_cost_growing() const { return m_iters_with_no_cost_growing; } + + linear_combination_iterator * get_iterator_on_row(unsigned i) { + if (m_settings.use_tableau()) + return new iterator_on_row(m_A.m_rows[i]); + calculate_pivot_row(i); + return new iterator_on_pivot_row(m_pivot_row, m_basis[i]); + } + + void calculate_pivot_row(unsigned i); + unsigned get_base_column_in_row(unsigned row_index) const { + return m_basis[row_index]; + } }; } diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index a0dba9de7..5ac6c4c22 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -7,7 +7,7 @@ #include "util/vector.h" #include "util/lp/lp_utils.h" #include "util/lp/lp_core_solver_base.h" -namespace lean { +namespace lp { template lp_core_solver_base:: lp_core_solver_base(static_matrix & A, @@ -24,7 +24,7 @@ lp_core_solver_base(static_matrix & A, const vector & upper_bound_values): m_total_iterations(0), m_iters_with_no_cost_growing(0), - m_status(FEASIBLE), + m_status(lp_status::FEASIBLE), m_inf_set(A.column_count()), m_using_infeas_costs(false), m_pivot_row_of_B_1(A.row_count()), @@ -52,8 +52,9 @@ lp_core_solver_base(static_matrix & A, m_steepest_edge_coefficients(A.column_count()), m_tracing_basis_changes(false), m_pivoted_rows(nullptr), - m_look_for_feasible_solution_only(false) { - lean_assert(bounds_for_boxed_are_set_correctly()); + m_look_for_feasible_solution_only(false), + m_tracker_of_x_change(nullptr) { + lp_assert(bounds_for_boxed_are_set_correctly()); init(); init_basis_heading_and_non_basic_columns_vector(); } @@ -61,7 +62,7 @@ lp_core_solver_base(static_matrix & A, template void lp_core_solver_base:: allocate_basis_heading() { // the rest of initilization will be handled by the factorization class init_basis_heading_and_non_basic_columns_vector(); - lean_assert(basis_heading_is_correct()); + lp_assert(basis_heading_is_correct()); } template void lp_core_solver_base:: init() { @@ -83,8 +84,8 @@ pivot_for_tableau_on_basis() { // i is the pivot row, and j is the pivot column template void lp_core_solver_base:: pivot_to_reduced_costs_tableau(unsigned i, unsigned j) { - if (j >= m_d.size()) - return; + if (j >= m_d.size()) + return; T &a = m_d[j]; if (is_zero(a)) return; @@ -127,7 +128,7 @@ solve_yB(vector & y) { // } // } template void lp_core_solver_base::solve_Bd(unsigned entering, indexed_vector & column) { - lean_assert(!m_settings.use_tableau()); + lp_assert(!m_settings.use_tableau()); if (m_factorization == nullptr) { init_factorization(m_factorization, m_A, m_basis, m_settings); } @@ -137,19 +138,19 @@ template void lp_core_solver_base::solve_Bd(unsig template void lp_core_solver_base:: solve_Bd(unsigned entering) { - lean_assert(m_ed.is_OK()); + lp_assert(m_ed.is_OK()); m_factorization->solve_Bd(entering, m_ed, m_w); if (this->precise()) m_columns_nz[entering] = m_ed.m_index.size(); - lean_assert(m_ed.is_OK()); - lean_assert(m_w.is_OK()); + lp_assert(m_ed.is_OK()); + lp_assert(m_w.is_OK()); #ifdef LEAN_DEBUG // auto B = get_B(*m_factorization, m_basis); // vector a(m_m()); // m_A.copy_column_to_vector(entering, a); // vector cd(m_ed.m_data); // B.apply_from_left(cd, m_settings); - // lean_assert(vectors_are_equal(cd , a)); + // lp_assert(vectors_are_equal(cd , a)); #endif } @@ -208,7 +209,7 @@ restore_m_ed(T * buffer) { template bool lp_core_solver_base:: A_mult_x_is_off() const { - lean_assert(m_x.size() == m_A.column_count()); + lp_assert(m_x.size() == m_A.column_count()); if (numeric_traits::precise()) { for (unsigned i = 0; i < m_m(); i++) { X delta = m_b[i] - m_A.dot_product_with_row(i, m_x); @@ -244,7 +245,7 @@ A_mult_x_is_off() const { } template bool lp_core_solver_base:: A_mult_x_is_off_on_index(const vector & index) const { - lean_assert(m_x.size() == m_A.column_count()); + lp_assert(m_x.size() == m_A.column_count()); if (numeric_traits::precise()) return false; #if RUN_A_MULT_X_IS_OFF_FOR_PRECESE for (unsigned i : index) { @@ -284,13 +285,13 @@ A_mult_x_is_off_on_index(const vector & index) const { // from page 182 of Istvan Maros's book template void lp_core_solver_base:: calculate_pivot_row_of_B_1(unsigned pivot_row) { - lean_assert(! use_tableau()); - lean_assert(m_pivot_row_of_B_1.is_OK()); + lp_assert(! use_tableau()); + lp_assert(m_pivot_row_of_B_1.is_OK()); m_pivot_row_of_B_1.clear(); m_pivot_row_of_B_1.set_value(numeric_traits::one(), pivot_row); - lean_assert(m_pivot_row_of_B_1.is_OK()); + lp_assert(m_pivot_row_of_B_1.is_OK()); m_factorization->solve_yB_with_error_check_indexed(m_pivot_row_of_B_1, m_basis_heading, m_basis, m_settings); - lean_assert(m_pivot_row_of_B_1.is_OK()); + lp_assert(m_pivot_row_of_B_1.is_OK()); } @@ -380,11 +381,11 @@ set_non_basic_x_to_correct_bounds() { break; case column_type::low_bound: m_x[j] = m_low_bounds[j]; - lean_assert(column_is_dual_feasible(j)); + lp_assert(column_is_dual_feasible(j)); break; case column_type::upper_bound: m_x[j] = m_upper_bounds[j]; - lean_assert(column_is_dual_feasible(j)); + lp_assert(column_is_dual_feasible(j)); break; default: break; @@ -402,15 +403,15 @@ column_is_dual_feasible(unsigned j) const { return x_is_at_low_bound(j) && d_is_not_negative(j); case column_type::upper_bound: LP_OUT(m_settings, "upper_bound type should be switched to low_bound" << std::endl); - lean_assert(false); // impossible case + lp_assert(false); // impossible case case column_type::free_column: return numeric_traits::is_zero(m_d[j]); default: LP_OUT(m_settings, "column = " << j << std::endl); LP_OUT(m_settings, "unexpected column type = " << column_type_to_string(m_column_types[j]) << std::endl); - lean_unreachable(); + lp_unreachable(); } - lean_unreachable(); + lp_unreachable(); return false; } template bool lp_core_solver_base:: @@ -493,7 +494,7 @@ template bool lp_core_solver_base::column_is_feas return true; break; default: - lean_unreachable(); + lp_unreachable(); } return false; // it is unreachable } @@ -534,7 +535,7 @@ update_basis_and_x(int entering, int leaving, X const & tt) { if (!find_x_by_solving()) { restore_x(entering, tt); if(A_mult_x_is_off()) { - m_status = FLOATING_POINT_ERROR; + m_status = lp_status::FLOATING_POINT_ERROR; m_iters_with_no_cost_growing++; return false; } @@ -544,7 +545,7 @@ update_basis_and_x(int entering, int leaving, X const & tt) { if (m_factorization->get_status() != LU_status::OK) { std::stringstream s; // s << "failing refactor on off_result for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << total_iterations(); - m_status = FLOATING_POINT_ERROR; + m_status = lp_status::FLOATING_POINT_ERROR; return false; } return false; @@ -566,19 +567,19 @@ update_basis_and_x(int entering, int leaving, X const & tt) { init_lu(); if (m_factorization->get_status() != LU_status::OK) { if (m_look_for_feasible_solution_only && !precise()) { - m_status = UNSTABLE; + m_status = lp_status::UNSTABLE; delete m_factorization; m_factorization = nullptr; return false; } // LP_OUT(m_settings, "failing refactor for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << total_iterations() << std::endl); restore_x_and_refactor(entering, leaving, tt); - if (m_status == FLOATING_POINT_ERROR) + if (m_status == lp_status::FLOATING_POINT_ERROR) return false; - lean_assert(!A_mult_x_is_off()); + lp_assert(!A_mult_x_is_off()); m_iters_with_no_cost_growing++; // LP_OUT(m_settings, "rolled back after failing of init_factorization()" << std::endl); - m_status = UNSTABLE; + m_status = lp_status::UNSTABLE; return false; } return true; @@ -587,7 +588,7 @@ update_basis_and_x(int entering, int leaving, X const & tt) { template bool lp_core_solver_base:: divide_row_by_pivot(unsigned pivot_row, unsigned pivot_col) { - lean_assert(numeric_traits::precise()); + lp_assert(numeric_traits::precise()); int pivot_index = -1; auto & row = m_A.m_rows[pivot_row]; unsigned size = row.size(); @@ -628,7 +629,7 @@ pivot_column_tableau(unsigned j, unsigned piv_row_index) { return false; if (pivot_col_cell_index != 0) { - lean_assert(column.size() > 1); + lp_assert(column.size() > 1); // swap the pivot column cell with the head cell auto c = column[0]; column[0] = column[pivot_col_cell_index]; @@ -639,7 +640,7 @@ pivot_column_tableau(unsigned j, unsigned piv_row_index) { } while (column.size() > 1) { auto & c = column.back(); - lean_assert(c.m_i != piv_row_index); + lp_assert(c.m_i != piv_row_index); if(! m_A.pivot_row_to_row_given_cell(piv_row_index, c, j)) { return false; } @@ -687,7 +688,7 @@ non_basis_is_correctly_represented_in_heading() const { } for (unsigned j = 0; j < m_A.column_count(); j++) { if (m_basis_heading[j] >= 0) { - lean_assert(static_cast(m_basis_heading[j]) < m_A.row_count() && m_basis[m_basis_heading[j]] == j); + lp_assert(static_cast(m_basis_heading[j]) < m_A.row_count() && m_basis[m_basis_heading[j]] == j); } } return true; @@ -695,9 +696,9 @@ non_basis_is_correctly_represented_in_heading() const { template bool lp_core_solver_base:: basis_heading_is_correct() const { - lean_assert(m_basis_heading.size() == m_A.column_count()); - lean_assert(m_basis.size() == m_A.row_count()); - lean_assert(m_nbasis.size() <= m_A.column_count() - m_A.row_count()); // for the dual the size of non basis can be smaller + lp_assert(m_basis_heading.size() == m_A.column_count()); + lp_assert(m_basis.size() == m_A.row_count()); + lp_assert(m_nbasis.size() <= m_A.column_count() - m_A.row_count()); // for the dual the size of non basis can be smaller if (!basis_has_no_doubles()) { // std::cout << "basis_has_no_doubles" << std::endl; return false; @@ -841,7 +842,7 @@ solve_Ax_eq_b() { template void lp_core_solver_base:: snap_non_basic_x_to_bound_and_free_to_zeroes() { for (unsigned j : non_basis()) { - lean_assert(j < m_x.size()); + lp_assert(j < m_x.size()); switch (m_column_types[j]) { case column_type::fixed: case column_type::boxed: @@ -892,9 +893,9 @@ get_non_basic_column_value_position(unsigned j) const { case column_type::upper_bound: return x_is_at_upper_bound(j)? at_upper_bound : not_at_bound; default: - lean_unreachable(); + lp_unreachable(); } - lean_unreachable(); + lp_unreachable(); return at_low_bound; } @@ -923,42 +924,55 @@ template void lp_core_solver_base::transpose_row transpose_basis(i, j); m_A.transpose_rows(i, j); } +// j is the new basic column, j_basic - the leaving column +template bool lp_core_solver_base::pivot_column_general(unsigned j, unsigned j_basic, indexed_vector & w) { + lp_assert(m_basis_heading[j] < 0); + lp_assert(m_basis_heading[j_basic] >= 0); + unsigned row_index = m_basis_heading[j_basic]; + if (m_settings.m_simplex_strategy == simplex_strategy_enum::lu) { + if (m_factorization->need_to_refactor()) { + init_lu(); + } + else { + m_factorization->prepare_entering(j, w); // to init vector w + m_factorization->replace_column(zero_of_type(), w, row_index); + } + if (m_factorization->get_status() != LU_status::OK) { + init_lu(); + return false; + } + else { + change_basis(j, j_basic); + } + } + else { // the tableau case + if (pivot_column_tableau(j, row_index)) + change_basis(j, j_basic); + else return false; + } + return true; +} template void lp_core_solver_base::pivot_fixed_vars_from_basis() { // run over basis and non-basis at the same time indexed_vector w(m_basis.size()); // the buffer unsigned i = 0; // points to basis - unsigned j = 0; // points to nonbasis - for (; i < m_basis.size() && j < m_nbasis.size(); i++) { - unsigned ii = m_basis[i]; - unsigned jj; + for (; i < m_basis.size(); i++) { + unsigned basic_j = m_basis[i]; - if (get_column_type(ii) != column_type::fixed) continue; - while (j < m_nbasis.size()) { - for (; j < m_nbasis.size(); j++) { - jj = m_nbasis[j]; - if (get_column_type(jj) != column_type::fixed) + if (get_column_type(basic_j) != column_type::fixed) continue; + T a; + unsigned j; + auto * it = get_iterator_on_row(i); + while (it->next(a, j)) { + if (j == basic_j) + continue; + if (get_column_type(j) != column_type::fixed) { + if (pivot_column_general(j, basic_j, w)) break; } - if (j >= m_nbasis.size()) - break; - j++; - if (m_factorization->need_to_refactor()) { - change_basis(jj, ii); - init_lu(); - } else { - m_factorization->prepare_entering(jj, w); // to init vector w - m_factorization->replace_column(zero_of_type(), w, m_basis_heading[ii]); - change_basis(jj, ii); - } - if (m_factorization->get_status() != LU_status::OK) { - change_basis(ii, jj); - init_lu(); - } else { - break; - } } - lean_assert(m_factorization->get_status()== LU_status::OK); + delete it; } } @@ -966,7 +980,7 @@ template bool lp_core_solver_base::infeasibility_costs_are_correct() const { if (! this->m_using_infeas_costs) return true; - lean_assert(costs_on_nbasis_are_zeros()); + lp_assert(costs_on_nbasis_are_zeros()); for (unsigned j :this->m_basis) { if (!infeasibility_cost_is_correct_for_column(j)) { std::cout << "infeasibility_cost_is_correct_for_column does not hold\n"; @@ -1011,9 +1025,31 @@ lp_core_solver_base::infeasibility_cost_is_correct_for_column(unsigned j) case column_type::free_column: return is_zero(this->m_costs[j]); default: - lean_assert(false); + lp_assert(false); return true; } } +template +void lp_core_solver_base::calculate_pivot_row(unsigned i) { + lp_assert(!use_tableau()); + lp_assert(m_pivot_row.is_OK()); + m_pivot_row_of_B_1.clear(); + m_pivot_row_of_B_1.resize(m_m()); + m_pivot_row.clear(); + m_pivot_row.resize(m_n()); + if (m_settings.use_tableau()) { + unsigned basis_j = m_basis[i]; + for (auto & c : m_A.m_rows[i]) { + if (c.m_j != basis_j) + m_pivot_row.set_value(c.get_val(), c.m_j); + } + return; + } + + calculate_pivot_row_of_B_1(i); + calculate_pivot_row_when_pivot_row_of_B1_is_ready(i); +} + + } diff --git a/src/util/lp/lp_core_solver_base_instances.cpp b/src/util/lp/lp_core_solver_base_instances.cpp index 17dcb87db..1f9d459bf 100644 --- a/src/util/lp/lp_core_solver_base_instances.cpp +++ b/src/util/lp/lp_core_solver_base_instances.cpp @@ -8,124 +8,125 @@ #include "util/vector.h" #include #include "util/lp/lp_core_solver_base.hpp" -template bool lean::lp_core_solver_base::A_mult_x_is_off() const; -template bool lean::lp_core_solver_base::A_mult_x_is_off_on_index(const vector &) const; -template bool lean::lp_core_solver_base::basis_heading_is_correct() const; -template void lean::lp_core_solver_base::calculate_pivot_row_of_B_1(unsigned int); -template void lean::lp_core_solver_base::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); -template bool lean::lp_core_solver_base::column_is_dual_feasible(unsigned int) const; -template void lean::lp_core_solver_base::fill_reduced_costs_from_m_y_by_rows(); -template bool lean::lp_core_solver_base::find_x_by_solving(); -template lean::non_basic_column_value_position lean::lp_core_solver_base::get_non_basic_column_value_position(unsigned int) const; -template lean::non_basic_column_value_position lean::lp_core_solver_base >::get_non_basic_column_value_position(unsigned int) const; -template lean::non_basic_column_value_position lean::lp_core_solver_base::get_non_basic_column_value_position(unsigned int) const; -template void lean::lp_core_solver_base::init_reduced_costs_for_one_iteration(); -template lean::lp_core_solver_base::lp_core_solver_base( - lean::static_matrix&, vector&, +template bool lp::lp_core_solver_base::A_mult_x_is_off() const; +template bool lp::lp_core_solver_base::A_mult_x_is_off_on_index(const vector &) const; +template bool lp::lp_core_solver_base::basis_heading_is_correct() const; +template void lp::lp_core_solver_base::calculate_pivot_row_of_B_1(unsigned int); +template void lp::lp_core_solver_base::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); +template bool lp::lp_core_solver_base::column_is_dual_feasible(unsigned int) const; +template void lp::lp_core_solver_base::fill_reduced_costs_from_m_y_by_rows(); +template bool lp::lp_core_solver_base::find_x_by_solving(); +template lp::non_basic_column_value_position lp::lp_core_solver_base::get_non_basic_column_value_position(unsigned int) const; +template lp::non_basic_column_value_position lp::lp_core_solver_base >::get_non_basic_column_value_position(unsigned int) const; +template lp::non_basic_column_value_position lp::lp_core_solver_base::get_non_basic_column_value_position(unsigned int) const; +template void lp::lp_core_solver_base::init_reduced_costs_for_one_iteration(); +template lp::lp_core_solver_base::lp_core_solver_base( + lp::static_matrix&, vector&, vector&, vector &, vector &, vector&, vector&, - lean::lp_settings&, const column_namer&, const vector&, + lp::lp_settings&, const column_namer&, const vector&, const vector&, const vector&); -template bool lean::lp_core_solver_base::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); -template bool lean::lp_core_solver_base >::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); -template void lean::lp_core_solver_base::restore_x(unsigned int, double const&); -template void lean::lp_core_solver_base::set_non_basic_x_to_correct_bounds(); -template void lean::lp_core_solver_base::snap_xN_to_bounds_and_free_columns_to_zeroes(); -template void lean::lp_core_solver_base >::snap_xN_to_bounds_and_free_columns_to_zeroes(); -template void lean::lp_core_solver_base::solve_Ax_eq_b(); -template void lean::lp_core_solver_base::solve_Bd(unsigned int); -template void lean::lp_core_solver_base>::solve_Bd(unsigned int, indexed_vector&); -template void lean::lp_core_solver_base::solve_yB(vector&); -template bool lean::lp_core_solver_base::update_basis_and_x(int, int, double const&); -template void lean::lp_core_solver_base::update_x(unsigned int, const double&); -template bool lean::lp_core_solver_base::A_mult_x_is_off() const; -template bool lean::lp_core_solver_base::A_mult_x_is_off_on_index(const vector &) const; -template bool lean::lp_core_solver_base::basis_heading_is_correct() const ; -template void lean::lp_core_solver_base::calculate_pivot_row_of_B_1(unsigned int); -template void lean::lp_core_solver_base::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); -template bool lean::lp_core_solver_base::column_is_dual_feasible(unsigned int) const; -template void lean::lp_core_solver_base::fill_reduced_costs_from_m_y_by_rows(); -template bool lean::lp_core_solver_base::find_x_by_solving(); -template void lean::lp_core_solver_base::init_reduced_costs_for_one_iteration(); -template bool lean::lp_core_solver_base::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); -template void lean::lp_core_solver_base::restore_x(unsigned int, lean::mpq const&); -template void lean::lp_core_solver_base::set_non_basic_x_to_correct_bounds(); -template void lean::lp_core_solver_base::solve_Ax_eq_b(); -template void lean::lp_core_solver_base::solve_Bd(unsigned int); -template void lean::lp_core_solver_base::solve_yB(vector&); -template bool lean::lp_core_solver_base::update_basis_and_x(int, int, lean::mpq const&); -template void lean::lp_core_solver_base::update_x(unsigned int, const lean::mpq&); -template void lean::lp_core_solver_base >::calculate_pivot_row_of_B_1(unsigned int); -template void lean::lp_core_solver_base >::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); -template void lean::lp_core_solver_base >::init(); -template void lean::lp_core_solver_base >::init_basis_heading_and_non_basic_columns_vector(); -template void lean::lp_core_solver_base >::init_reduced_costs_for_one_iteration(); -template lean::lp_core_solver_base >::lp_core_solver_base(lean::static_matrix >&, vector >&, vector&, vector &, vector &, vector >&, vector&, lean::lp_settings&, const column_namer&, const vector&, - const vector >&, - const vector >&); -template bool lean::lp_core_solver_base >::print_statistics_with_cost_and_check_that_the_time_is_over(lean::numeric_pair, std::ostream&); -template void lean::lp_core_solver_base >::snap_xN_to_bounds_and_fill_xB(); -template void lean::lp_core_solver_base >::solve_Bd(unsigned int); -template bool lean::lp_core_solver_base >::update_basis_and_x(int, int, lean::numeric_pair const&); -template void lean::lp_core_solver_base >::update_x(unsigned int, const lean::numeric_pair&); -template lean::lp_core_solver_base::lp_core_solver_base( - lean::static_matrix&, - vector&, +template bool lp::lp_core_solver_base::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); +template bool lp::lp_core_solver_base >::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); +template void lp::lp_core_solver_base::restore_x(unsigned int, double const&); +template void lp::lp_core_solver_base::set_non_basic_x_to_correct_bounds(); +template void lp::lp_core_solver_base::snap_xN_to_bounds_and_free_columns_to_zeroes(); +template void lp::lp_core_solver_base >::snap_xN_to_bounds_and_free_columns_to_zeroes(); +template void lp::lp_core_solver_base::solve_Ax_eq_b(); +template void lp::lp_core_solver_base::solve_Bd(unsigned int); +template void lp::lp_core_solver_base>::solve_Bd(unsigned int, indexed_vector&); +template void lp::lp_core_solver_base::solve_yB(vector&); +template bool lp::lp_core_solver_base::update_basis_and_x(int, int, double const&); +template void lp::lp_core_solver_base::update_x(unsigned int, const double&); +template bool lp::lp_core_solver_base::A_mult_x_is_off() const; +template bool lp::lp_core_solver_base::A_mult_x_is_off_on_index(const vector &) const; +template bool lp::lp_core_solver_base::basis_heading_is_correct() const ; +template void lp::lp_core_solver_base::calculate_pivot_row_of_B_1(unsigned int); +template void lp::lp_core_solver_base::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); +template bool lp::lp_core_solver_base::column_is_dual_feasible(unsigned int) const; +template void lp::lp_core_solver_base::fill_reduced_costs_from_m_y_by_rows(); +template bool lp::lp_core_solver_base::find_x_by_solving(); +template void lp::lp_core_solver_base::init_reduced_costs_for_one_iteration(); +template bool lp::lp_core_solver_base::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); +template void lp::lp_core_solver_base::restore_x(unsigned int, lp::mpq const&); +template void lp::lp_core_solver_base::set_non_basic_x_to_correct_bounds(); +template void lp::lp_core_solver_base::solve_Ax_eq_b(); +template void lp::lp_core_solver_base::solve_Bd(unsigned int); +template void lp::lp_core_solver_base::solve_yB(vector&); +template bool lp::lp_core_solver_base::update_basis_and_x(int, int, lp::mpq const&); +template void lp::lp_core_solver_base::update_x(unsigned int, const lp::mpq&); +template void lp::lp_core_solver_base >::calculate_pivot_row_of_B_1(unsigned int); +template void lp::lp_core_solver_base >::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); +template void lp::lp_core_solver_base >::init(); +template void lp::lp_core_solver_base >::init_basis_heading_and_non_basic_columns_vector(); +template void lp::lp_core_solver_base >::init_reduced_costs_for_one_iteration(); +template lp::lp_core_solver_base >::lp_core_solver_base(lp::static_matrix >&, vector >&, vector&, vector &, vector &, vector >&, vector&, lp::lp_settings&, const column_namer&, const vector&, + const vector >&, + const vector >&); +template bool lp::lp_core_solver_base >::print_statistics_with_cost_and_check_that_the_time_is_over(lp::numeric_pair, std::ostream&); +template void lp::lp_core_solver_base >::snap_xN_to_bounds_and_fill_xB(); +template void lp::lp_core_solver_base >::solve_Bd(unsigned int); +template bool lp::lp_core_solver_base >::update_basis_and_x(int, int, lp::numeric_pair const&); +template void lp::lp_core_solver_base >::update_x(unsigned int, const lp::numeric_pair&); +template lp::lp_core_solver_base::lp_core_solver_base( + lp::static_matrix&, + vector&, vector&, vector &, vector &, - vector&, - vector&, - lean::lp_settings&, + vector&, + vector&, + lp::lp_settings&, const column_namer&, - const vector&, - const vector&, - const vector&); -template bool lean::lp_core_solver_base >::print_statistics_with_iterations_and_check_that_the_time_is_over(std::ostream &); -template std::string lean::lp_core_solver_base::column_name(unsigned int) const; -template void lean::lp_core_solver_base::pretty_print(std::ostream & out); -template void lean::lp_core_solver_base::restore_state(double*, double*); -template void lean::lp_core_solver_base::save_state(double*, double*); -template std::string lean::lp_core_solver_base::column_name(unsigned int) const; -template void lean::lp_core_solver_base::pretty_print(std::ostream & out); -template void lean::lp_core_solver_base::restore_state(lean::mpq*, lean::mpq*); -template void lean::lp_core_solver_base::save_state(lean::mpq*, lean::mpq*); -template std::string lean::lp_core_solver_base >::column_name(unsigned int) const; -template void lean::lp_core_solver_base >::pretty_print(std::ostream & out); -template void lean::lp_core_solver_base >::restore_state(lean::mpq*, lean::mpq*); -template void lean::lp_core_solver_base >::save_state(lean::mpq*, lean::mpq*); -template void lean::lp_core_solver_base >::solve_yB(vector&); -template void lean::lp_core_solver_base::init_lu(); -template void lean::lp_core_solver_base::init_lu(); -template int lean::lp_core_solver_base::pivots_in_column_and_row_are_different(int, int) const; -template int lean::lp_core_solver_base >::pivots_in_column_and_row_are_different(int, int) const; -template int lean::lp_core_solver_base::pivots_in_column_and_row_are_different(int, int) const; -template bool lean::lp_core_solver_base::calc_current_x_is_feasible_include_non_basis(void)const; -template bool lean::lp_core_solver_base::calc_current_x_is_feasible_include_non_basis(void)const; -template bool lean::lp_core_solver_base >::calc_current_x_is_feasible_include_non_basis() const; -template void lean::lp_core_solver_base >::pivot_fixed_vars_from_basis(); -template bool lean::lp_core_solver_base::column_is_feasible(unsigned int) const; -template bool lean::lp_core_solver_base::column_is_feasible(unsigned int) const; -// template void lean::lp_core_solver_base >::print_linear_combination_of_column_indices(vector, std::allocator > > const&, std::ostream&) const; -template bool lean::lp_core_solver_base >::column_is_feasible(unsigned int) const; -template bool lean::lp_core_solver_base >::snap_non_basic_x_to_bound(); -template void lean::lp_core_solver_base >::init_lu(); -template bool lean::lp_core_solver_base >::A_mult_x_is_off_on_index(vector const&) const; -template bool lean::lp_core_solver_base >::find_x_by_solving(); -template void lean::lp_core_solver_base >::restore_x(unsigned int, lean::numeric_pair const&); -template bool lean::lp_core_solver_base::pivot_for_tableau_on_basis(); -template bool lean::lp_core_solver_base::pivot_for_tableau_on_basis(); -template bool lean::lp_core_solver_base>::pivot_for_tableau_on_basis(); -template bool lean::lp_core_solver_base>::pivot_column_tableau(unsigned int, unsigned int); -template bool lean::lp_core_solver_base::pivot_column_tableau(unsigned int, unsigned int); -template bool lean::lp_core_solver_base::pivot_column_tableau(unsigned int, unsigned int); -template void lean::lp_core_solver_base >::transpose_rows_tableau(unsigned int, unsigned int); -template bool lean::lp_core_solver_base >::inf_set_is_correct() const; -template bool lean::lp_core_solver_base::inf_set_is_correct() const; -template bool lean::lp_core_solver_base::inf_set_is_correct() const; -template bool lean::lp_core_solver_base >::infeasibility_costs_are_correct() const; -template bool lean::lp_core_solver_base::infeasibility_costs_are_correct() const; -template bool lean::lp_core_solver_base::infeasibility_costs_are_correct() const; + const vector&, + const vector&, + const vector&); +template bool lp::lp_core_solver_base >::print_statistics_with_iterations_and_check_that_the_time_is_over(std::ostream &); +template std::string lp::lp_core_solver_base::column_name(unsigned int) const; +template void lp::lp_core_solver_base::pretty_print(std::ostream & out); +template void lp::lp_core_solver_base::restore_state(double*, double*); +template void lp::lp_core_solver_base::save_state(double*, double*); +template std::string lp::lp_core_solver_base::column_name(unsigned int) const; +template void lp::lp_core_solver_base::pretty_print(std::ostream & out); +template void lp::lp_core_solver_base::restore_state(lp::mpq*, lp::mpq*); +template void lp::lp_core_solver_base::save_state(lp::mpq*, lp::mpq*); +template std::string lp::lp_core_solver_base >::column_name(unsigned int) const; +template void lp::lp_core_solver_base >::pretty_print(std::ostream & out); +template void lp::lp_core_solver_base >::restore_state(lp::mpq*, lp::mpq*); +template void lp::lp_core_solver_base >::save_state(lp::mpq*, lp::mpq*); +template void lp::lp_core_solver_base >::solve_yB(vector&); +template void lp::lp_core_solver_base::init_lu(); +template void lp::lp_core_solver_base::init_lu(); +template int lp::lp_core_solver_base::pivots_in_column_and_row_are_different(int, int) const; +template int lp::lp_core_solver_base >::pivots_in_column_and_row_are_different(int, int) const; +template int lp::lp_core_solver_base::pivots_in_column_and_row_are_different(int, int) const; +template bool lp::lp_core_solver_base::calc_current_x_is_feasible_include_non_basis(void)const; +template bool lp::lp_core_solver_base::calc_current_x_is_feasible_include_non_basis(void)const; +template bool lp::lp_core_solver_base >::calc_current_x_is_feasible_include_non_basis() const; +template void lp::lp_core_solver_base >::pivot_fixed_vars_from_basis(); +template bool lp::lp_core_solver_base::column_is_feasible(unsigned int) const; +template bool lp::lp_core_solver_base::column_is_feasible(unsigned int) const; +// template void lp::lp_core_solver_base >::print_linear_combination_of_column_indices(vector, std::allocator > > const&, std::ostream&) const; +template bool lp::lp_core_solver_base >::column_is_feasible(unsigned int) const; +template bool lp::lp_core_solver_base >::snap_non_basic_x_to_bound(); +template void lp::lp_core_solver_base >::init_lu(); +template bool lp::lp_core_solver_base >::A_mult_x_is_off_on_index(vector const&) const; +template bool lp::lp_core_solver_base >::find_x_by_solving(); +template void lp::lp_core_solver_base >::restore_x(unsigned int, lp::numeric_pair const&); +template bool lp::lp_core_solver_base::pivot_for_tableau_on_basis(); +template bool lp::lp_core_solver_base::pivot_for_tableau_on_basis(); +template bool lp::lp_core_solver_base>::pivot_for_tableau_on_basis(); +template bool lp::lp_core_solver_base>::pivot_column_tableau(unsigned int, unsigned int); +template bool lp::lp_core_solver_base::pivot_column_tableau(unsigned int, unsigned int); +template bool lp::lp_core_solver_base::pivot_column_tableau(unsigned int, unsigned int); +template void lp::lp_core_solver_base >::transpose_rows_tableau(unsigned int, unsigned int); +template bool lp::lp_core_solver_base >::inf_set_is_correct() const; +template bool lp::lp_core_solver_base::inf_set_is_correct() const; +template bool lp::lp_core_solver_base::inf_set_is_correct() const; +template bool lp::lp_core_solver_base >::infeasibility_costs_are_correct() const; +template bool lp::lp_core_solver_base::infeasibility_costs_are_correct() const; +template bool lp::lp_core_solver_base::infeasibility_costs_are_correct() const; +template void lp::lp_core_solver_base >::calculate_pivot_row(unsigned int); diff --git a/src/util/lp/lp_dual_core_solver.h b/src/util/lp/lp_dual_core_solver.h index b873cb711..71a00c268 100644 --- a/src/util/lp/lp_dual_core_solver.h +++ b/src/util/lp/lp_dual_core_solver.h @@ -11,7 +11,7 @@ #include #include "util/vector.h" -namespace lean { +namespace lp { template class lp_dual_core_solver:public lp_core_solver_base { public: diff --git a/src/util/lp/lp_dual_core_solver.hpp b/src/util/lp/lp_dual_core_solver.hpp index 6565331b3..1b6e696d7 100644 --- a/src/util/lp/lp_dual_core_solver.hpp +++ b/src/util/lp/lp_dual_core_solver.hpp @@ -7,7 +7,7 @@ #include "util/vector.h" #include "util/lp/lp_dual_core_solver.h" -namespace lean { +namespace lp { template void lp_dual_core_solver::init_a_wave_by_zeros() { unsigned j = this->m_m(); @@ -23,7 +23,7 @@ template void lp_dual_core_solver::restore_non_ba while (j--) { if (this->m_basis_heading[j] >= 0 ) continue; if (m_can_enter_basis[j]) { - lean_assert(std::find(nb.begin(), nb.end(), j) == nb.end()); + lp_assert(std::find(nb.begin(), nb.end(), j) == nb.end()); nb.push_back(j); this->m_basis_heading[j] = - static_cast(nb.size()); } @@ -82,25 +82,25 @@ template void lp_dual_core_solver::start_with_ini } template bool lp_dual_core_solver::done() { - if (this->get_status() == OPTIMAL) { + if (this->get_status() == lp_status::OPTIMAL) { return true; } if (this->total_iterations() > this->m_settings.max_total_number_of_iterations) { // debug !!!! - this->set_status(ITERATIONS_EXHAUSTED); + this->set_status(lp_status::ITERATIONS_EXHAUSTED); return true; } return false; // todo, need to be more cases } template T lp_dual_core_solver::get_edge_steepness_for_low_bound(unsigned p) { - lean_assert(this->m_basis_heading[p] >= 0 && static_cast(this->m_basis_heading[p]) < this->m_m()); + lp_assert(this->m_basis_heading[p] >= 0 && static_cast(this->m_basis_heading[p]) < this->m_m()); T del = this->m_x[p] - this->m_low_bounds[p]; del *= del; return del / this->m_betas[this->m_basis_heading[p]]; } template T lp_dual_core_solver::get_edge_steepness_for_upper_bound(unsigned p) { - lean_assert(this->m_basis_heading[p] >= 0 && static_cast(this->m_basis_heading[p]) < this->m_m()); + lp_assert(this->m_basis_heading[p] >= 0 && static_cast(this->m_basis_heading[p]) < this->m_m()); T del = this->m_x[p] - this->m_upper_bounds[p]; del *= del; return del / this->m_betas[this->m_basis_heading[p]]; @@ -135,12 +135,12 @@ template T lp_dual_core_solver::pricing_for_row(u return numeric_traits::zero(); break; case column_type::free_column: - lean_assert(numeric_traits::is_zero(this->m_d[p])); + lp_assert(numeric_traits::is_zero(this->m_d[p])); return numeric_traits::zero(); default: - lean_unreachable(); + lp_unreachable(); } - lean_unreachable(); + lp_unreachable(); return numeric_traits::zero(); } @@ -170,8 +170,8 @@ template void lp_dual_core_solver::pricing_loop(u } } while (i != initial_offset_in_rows && rows_left); if (m_r == -1) { - if (this->get_status() != UNSTABLE) { - this->set_status(OPTIMAL); + if (this->get_status() != lp_status::UNSTABLE) { + this->set_status(lp_status::OPTIMAL); } } else { m_p = this->m_basis[m_r]; @@ -181,10 +181,10 @@ template void lp_dual_core_solver::pricing_loop(u return; } // failure in advance_on_known_p - if (this->get_status() == FLOATING_POINT_ERROR) { + if (this->get_status() == lp_status::FLOATING_POINT_ERROR) { return; } - this->set_status(UNSTABLE); + this->set_status(lp_status::UNSTABLE); m_forbidden_rows.insert(m_r); } } @@ -209,9 +209,9 @@ template bool lp_dual_core_solver::advance_on_kno int pivot_compare_result = this->pivots_in_column_and_row_are_different(m_q, m_p); if (!pivot_compare_result){;} else if (pivot_compare_result == 2) { // the sign is changed, cannot continue - lean_unreachable(); // not implemented yet + lp_unreachable(); // not implemented yet } else { - lean_assert(pivot_compare_result == 1); + lp_assert(pivot_compare_result == 1); this->init_lu(); } DSE_FTran(); @@ -228,21 +228,21 @@ template int lp_dual_core_solver::define_sign_of_ if (this->x_above_upper_bound(m_p)) { return 1; } - lean_unreachable(); + lp_unreachable(); case column_type::low_bound: if (this->x_below_low_bound(m_p)) { return -1; } - lean_unreachable(); + lp_unreachable(); case column_type::upper_bound: if (this->x_above_upper_bound(m_p)) { return 1; } - lean_unreachable(); + lp_unreachable(); default: - lean_unreachable(); + lp_unreachable(); } - lean_unreachable(); + lp_unreachable(); return 0; } @@ -250,10 +250,10 @@ template bool lp_dual_core_solver::can_be_breakpo if (this->pivot_row_element_is_too_small_for_ratio_test(j)) return false; switch (this->m_column_types[j]) { case column_type::low_bound: - lean_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_low_bounds[j])); + lp_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_low_bounds[j])); return m_sign_of_alpha_r * this->m_pivot_row[j] > 0; case column_type::upper_bound: - lean_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_upper_bounds[j])); + lp_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_upper_bounds[j])); return m_sign_of_alpha_r * this->m_pivot_row[j] < 0; case column_type::boxed: { @@ -292,23 +292,23 @@ template T lp_dual_core_solver::get_delta() { if (this->x_above_upper_bound(m_p)) { return this->m_x[m_p] - this->m_upper_bounds[m_p]; } - lean_unreachable(); + lp_unreachable(); case column_type::low_bound: if (this->x_below_low_bound(m_p)) { return this->m_x[m_p] - this->m_low_bounds[m_p]; } - lean_unreachable(); + lp_unreachable(); case column_type::upper_bound: if (this->x_above_upper_bound(m_p)) { return get_edge_steepness_for_upper_bound(m_p); } - lean_unreachable(); + lp_unreachable(); case column_type::fixed: return this->m_x[m_p] - this->m_upper_bounds[m_p]; default: - lean_unreachable(); + lp_unreachable(); } - lean_unreachable(); + lp_unreachable(); return zero_of_type(); } @@ -355,7 +355,7 @@ template void lp_dual_core_solver::update_betas() template void lp_dual_core_solver::apply_flips() { for (unsigned j : m_flipped_boxed) { - lean_assert(this->x_is_at_bound(j)); + lp_assert(this->x_is_at_bound(j)); if (this->x_is_at_low_bound(j)) { this->m_x[j] = this->m_upper_bounds[j]; } else { @@ -385,7 +385,7 @@ template void lp_dual_core_solver::snap_xN_column case column_type::free_column: break; default: - lean_unreachable(); + lp_unreachable(); } } @@ -441,7 +441,7 @@ template bool lp_dual_core_solver::basis_change_a return false; } - lean_assert(d_is_correct()); + lp_assert(d_is_correct()); return true; } @@ -457,7 +457,7 @@ template void lp_dual_core_solver::recover_leavin case free_of_bounds: this->m_x[m_q] = zero_of_type(); default: - lean_unreachable(); + lp_unreachable(); } } @@ -466,12 +466,12 @@ template void lp_dual_core_solver::revert_to_prev this->change_basis_unconditionally(m_p, m_q); init_factorization(this->m_factorization, this->m_A, this->m_basis, this->m_settings); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); // complete failure + this->set_status(lp_status::FLOATING_POINT_ERROR); // complete failure return; } recover_leaving(); if (!this->find_x_by_solving()) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); return; } recalculate_xB_and_d(); @@ -551,10 +551,10 @@ template bool lp_dual_core_solver::delta_keeps_th } template void lp_dual_core_solver::set_status_to_tentative_dual_unbounded_or_dual_unbounded() { - if (this->get_status() == TENTATIVE_DUAL_UNBOUNDED) { - this->set_status(DUAL_UNBOUNDED); + if (this->get_status() == lp_status::TENTATIVE_DUAL_UNBOUNDED) { + this->set_status(lp_status::DUAL_UNBOUNDED); } else { - this->set_status(TENTATIVE_DUAL_UNBOUNDED); + this->set_status(lp_status::TENTATIVE_DUAL_UNBOUNDED); } } @@ -584,7 +584,7 @@ template bool lp_dual_core_solver::tight_breakpoi template T lp_dual_core_solver::calculate_harris_delta_on_breakpoint_set() { bool first_time = true; T ret = zero_of_type(); - lean_assert(m_breakpoint_set.size() > 0); + lp_assert(m_breakpoint_set.size() > 0); for (auto j : m_breakpoint_set) { T t; if (this->x_is_at_low_bound(j)) { @@ -633,7 +633,7 @@ template void lp_dual_core_solver::find_q_on_tigh } } m_tight_set.erase(m_q); - lean_assert(m_q != -1); + lp_assert(m_q != -1); } template void lp_dual_core_solver::find_q_and_tight_set() { @@ -660,7 +660,7 @@ template bool lp_dual_core_solver::ratio_test() { set_status_to_tentative_dual_unbounded_or_dual_unbounded(); return false; } - this->set_status(FEASIBLE); + this->set_status(lp_status::FEASIBLE); find_q_and_tight_set(); if (!tight_breakpoinst_are_all_boxed()) break; T del = m_delta - delta_lost_on_flips_of_tight_breakpoints() * initial_delta_sign; @@ -716,19 +716,19 @@ template void lp_dual_core_solver::update_xb_afte template void lp_dual_core_solver::one_iteration() { unsigned number_of_rows_to_try = get_number_of_rows_to_try_for_leaving(); unsigned offset_in_rows = this->m_settings.random_next() % this->m_m(); - if (this->get_status() == TENTATIVE_DUAL_UNBOUNDED) { + if (this->get_status() == lp_status::TENTATIVE_DUAL_UNBOUNDED) { number_of_rows_to_try = this->m_m(); } else { - this->set_status(FEASIBLE); + this->set_status(lp_status::FEASIBLE); } pricing_loop(number_of_rows_to_try, offset_in_rows); - lean_assert(problem_is_dual_feasible()); + lp_assert(problem_is_dual_feasible()); } template void lp_dual_core_solver::solve() { // see the page 35 - lean_assert(d_is_correct()); - lean_assert(problem_is_dual_feasible()); - lean_assert(this->basis_heading_is_correct()); + lp_assert(d_is_correct()); + lp_assert(problem_is_dual_feasible()); + lp_assert(this->basis_heading_is_correct()); this->set_total_iterations(0); this->iters_with_no_cost_growing() = 0; do { @@ -736,7 +736,7 @@ template void lp_dual_core_solver::solve() { // s return; } one_iteration(); - } while (this->get_status() != FLOATING_POINT_ERROR && this->get_status() != DUAL_UNBOUNDED && this->get_status() != OPTIMAL && + } while (this->get_status() != lp_status::FLOATING_POINT_ERROR && this->get_status() != lp_status::DUAL_UNBOUNDED && this->get_status() != lp_status::OPTIMAL && this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements && this->total_iterations() <= this->m_settings.max_total_number_of_iterations); } diff --git a/src/util/lp/lp_dual_core_solver_instances.cpp b/src/util/lp/lp_dual_core_solver_instances.cpp index 8016088f8..9484d34a3 100644 --- a/src/util/lp/lp_dual_core_solver_instances.cpp +++ b/src/util/lp/lp_dual_core_solver_instances.cpp @@ -8,22 +8,22 @@ #include "util/vector.h" #include #include "util/lp/lp_dual_core_solver.hpp" -template void lean::lp_dual_core_solver::start_with_initial_basis_and_make_it_dual_feasible(); -template void lean::lp_dual_core_solver::solve(); -template lean::lp_dual_core_solver::lp_dual_core_solver(lean::static_matrix&, vector&, +template void lp::lp_dual_core_solver::start_with_initial_basis_and_make_it_dual_feasible(); +template void lp::lp_dual_core_solver::solve(); +template lp::lp_dual_core_solver::lp_dual_core_solver(lp::static_matrix&, vector&, vector&, vector&, vector&, vector &, vector &, vector&, - vector&, + vector&, vector&, vector&, - lean::lp_settings&, const lean::column_namer&); -template void lean::lp_dual_core_solver::start_with_initial_basis_and_make_it_dual_feasible(); -template void lean::lp_dual_core_solver::solve(); -template void lean::lp_dual_core_solver::restore_non_basis(); -template void lean::lp_dual_core_solver::restore_non_basis(); -template void lean::lp_dual_core_solver::revert_to_previous_basis(); -template void lean::lp_dual_core_solver::revert_to_previous_basis(); + lp::lp_settings&, const lp::column_namer&); +template void lp::lp_dual_core_solver::start_with_initial_basis_and_make_it_dual_feasible(); +template void lp::lp_dual_core_solver::solve(); +template void lp::lp_dual_core_solver::restore_non_basis(); +template void lp::lp_dual_core_solver::restore_non_basis(); +template void lp::lp_dual_core_solver::revert_to_previous_basis(); +template void lp::lp_dual_core_solver::revert_to_previous_basis(); diff --git a/src/util/lp/lp_dual_simplex.h b/src/util/lp/lp_dual_simplex.h index 4dff2a4f1..58d9b7240 100644 --- a/src/util/lp/lp_dual_simplex.h +++ b/src/util/lp/lp_dual_simplex.h @@ -7,7 +7,7 @@ #include "util/lp/lp_utils.h" #include "util/lp/lp_solver.h" #include "util/lp/lp_dual_core_solver.h" -namespace lean { +namespace lp { template class lp_dual_simplex: public lp_solver { diff --git a/src/util/lp/lp_dual_simplex.hpp b/src/util/lp/lp_dual_simplex.hpp index 5047e117f..7f6f686ca 100644 --- a/src/util/lp/lp_dual_simplex.hpp +++ b/src/util/lp/lp_dual_simplex.hpp @@ -3,35 +3,35 @@ Author: Lev Nachmanson */ #include "util/lp/lp_dual_simplex.h" -namespace lean{ +namespace lp{ template void lp_dual_simplex::decide_on_status_after_stage1() { switch (m_core_solver->get_status()) { - case OPTIMAL: + case lp_status::OPTIMAL: if (this->m_settings.abs_val_is_smaller_than_artificial_tolerance(m_core_solver->get_cost())) { - this->m_status = FEASIBLE; + this->m_status = lp_status::FEASIBLE; } else { - this->m_status = UNBOUNDED; + this->m_status = lp_status::UNBOUNDED; } break; - case DUAL_UNBOUNDED: - lean_unreachable(); - case ITERATIONS_EXHAUSTED: - this->m_status = ITERATIONS_EXHAUSTED; + case lp_status::DUAL_UNBOUNDED: + lp_unreachable(); + case lp_status::ITERATIONS_EXHAUSTED: + this->m_status = lp_status::ITERATIONS_EXHAUSTED; break; - case TIME_EXHAUSTED: - this->m_status = TIME_EXHAUSTED; + case lp_status::TIME_EXHAUSTED: + this->m_status = lp_status::TIME_EXHAUSTED; break; - case FLOATING_POINT_ERROR: - this->m_status = FLOATING_POINT_ERROR; + case lp_status::FLOATING_POINT_ERROR: + this->m_status = lp_status::FLOATING_POINT_ERROR; break; default: - lean_unreachable(); + lp_unreachable(); } } template void lp_dual_simplex::fix_logical_for_stage2(unsigned j) { - lean_assert(j >= this->number_of_core_structurals()); + lp_assert(j >= this->number_of_core_structurals()); switch (m_column_types_of_logicals[j - this->number_of_core_structurals()]) { case column_type::low_bound: m_low_bounds[j] = numeric_traits::zero(); @@ -44,7 +44,7 @@ template void lp_dual_simplex::fix_logical_for_st m_can_enter_basis[j] = false; break; default: - lean_unreachable(); + lp_unreachable(); } } @@ -58,7 +58,7 @@ template void lp_dual_simplex::fix_structural_for break; case column_type::fixed: case column_type::upper_bound: - lean_unreachable(); + lp_unreachable(); case column_type::boxed: this->m_upper_bounds[j] = ci->get_adjusted_upper_bound() / this->m_column_scale[j]; m_low_bounds[j] = numeric_traits::zero(); @@ -70,7 +70,7 @@ template void lp_dual_simplex::fix_structural_for m_column_types_of_core_solver[j] = column_type::free_column; break; default: - lean_unreachable(); + lp_unreachable(); } // T cost_was = this->m_costs[j]; this->set_scaled_cost(j); @@ -99,23 +99,23 @@ template void lp_dual_simplex::solve_for_stage2() m_core_solver->solve_yB(m_core_solver->m_y); m_core_solver->fill_reduced_costs_from_m_y_by_rows(); m_core_solver->start_with_initial_basis_and_make_it_dual_feasible(); - m_core_solver->set_status(FEASIBLE); + m_core_solver->set_status(lp_status::FEASIBLE); m_core_solver->solve(); switch (m_core_solver->get_status()) { - case OPTIMAL: - this->m_status = OPTIMAL; + case lp_status::OPTIMAL: + this->m_status = lp_status::OPTIMAL; break; - case DUAL_UNBOUNDED: - this->m_status = INFEASIBLE; + case lp_status::DUAL_UNBOUNDED: + this->m_status = lp_status::INFEASIBLE; break; - case TIME_EXHAUSTED: - this->m_status = TIME_EXHAUSTED; + case lp_status::TIME_EXHAUSTED: + this->m_status = lp_status::TIME_EXHAUSTED; break; - case FLOATING_POINT_ERROR: - this->m_status = FLOATING_POINT_ERROR; + case lp_status::FLOATING_POINT_ERROR: + this->m_status = lp_status::FLOATING_POINT_ERROR; break; default: - lean_unreachable(); + lp_unreachable(); } this->m_second_stage_iterations = m_core_solver->total_iterations(); this->m_total_iterations = (this->m_first_stage_iterations + this->m_second_stage_iterations); @@ -129,7 +129,7 @@ template void lp_dual_simplex::fill_x_with_zeros( } template void lp_dual_simplex::stage1() { - lean_assert(m_core_solver == nullptr); + lp_assert(m_core_solver == nullptr); this->m_x.resize(this->m_A->column_count(), numeric_traits::zero()); if (this->m_settings.get_message_ostream() != nullptr) this->print_statistics_on_A(*this->m_settings.get_message_ostream()); @@ -151,7 +151,7 @@ template void lp_dual_simplex::stage1() { m_core_solver->start_with_initial_basis_and_make_it_dual_feasible(); if (this->m_settings.abs_val_is_smaller_than_artificial_tolerance(m_core_solver->get_cost())) { // skipping stage 1 - m_core_solver->set_status(OPTIMAL); + m_core_solver->set_status(lp_status::OPTIMAL); m_core_solver->set_total_iterations(0); } else { m_core_solver->solve(); @@ -177,7 +177,7 @@ template void lp_dual_simplex::fill_first_stage_s } template column_type lp_dual_simplex::get_column_type(unsigned j) { - lean_assert(j < this->m_A->column_count()); + lp_assert(j < this->m_A->column_count()); if (j >= this->number_of_core_structurals()) { return m_column_types_of_logicals[j - this->number_of_core_structurals()]; } @@ -186,12 +186,12 @@ template column_type lp_dual_simplex::get_column_ template void lp_dual_simplex::fill_costs_bounds_types_and_can_enter_basis_for_the_first_stage_solver_structural_column(unsigned j) { // see 4.7 in the dissertation of Achim Koberstein - lean_assert(this->m_core_solver_columns_to_external_columns.find(j) != + lp_assert(this->m_core_solver_columns_to_external_columns.find(j) != this->m_core_solver_columns_to_external_columns.end()); T free_bound = T(1e4); // see 4.8 unsigned jj = this->m_core_solver_columns_to_external_columns[j]; - lean_assert(this->m_map_from_var_index_to_column_info.find(jj) != this->m_map_from_var_index_to_column_info.end()); + lp_assert(this->m_map_from_var_index_to_column_info.find(jj) != this->m_map_from_var_index_to_column_info.end()); column_info * ci = this->m_map_from_var_index_to_column_info[jj]; switch (ci->get_column_type()) { case column_type::upper_bound: { @@ -221,14 +221,14 @@ template void lp_dual_simplex::fill_costs_bounds_ this->m_upper_bounds[j] = this->m_low_bounds[j] = numeric_traits::zero(); // is it needed? break; default: - lean_unreachable(); + lp_unreachable(); } m_column_types_of_core_solver[j] = column_type::boxed; } template void lp_dual_simplex::fill_costs_bounds_types_and_can_enter_basis_for_the_first_stage_solver_logical_column(unsigned j) { this->m_costs[j] = 0; - lean_assert(get_column_type(j) != column_type::upper_bound); + lp_assert(get_column_type(j) != column_type::upper_bound); if ((m_can_enter_basis[j] = (get_column_type(j) == column_type::low_bound))) { m_column_types_of_core_solver[j] = column_type::boxed; this->m_low_bounds[j] = numeric_traits::zero(); @@ -254,7 +254,7 @@ template void lp_dual_simplex::fill_costs_and_bou template void lp_dual_simplex::fill_first_stage_solver_fields_for_row_slack_and_artificial(unsigned row, unsigned & slack_var, unsigned & artificial) { - lean_assert(row < this->row_count()); + lp_assert(row < this->row_count()); auto & constraint = this->m_constraints[this->m_core_solver_rows_to_external_rows[row]]; // we need to bring the program to the form Ax = b T rs = this->m_b[row]; @@ -336,7 +336,7 @@ template void lp_dual_simplex::find_maximal_solut this->flip_costs(); // do it for now, todo ( remove the flipping) this->cleanup(); - if (this->m_status == INFEASIBLE) { + if (this->m_status == lp_status::INFEASIBLE) { return; } this->fill_matrix_A_and_init_right_side(); @@ -346,7 +346,7 @@ template void lp_dual_simplex::find_maximal_solut fill_first_stage_solver_fields(); copy_m_b_aside_and_set_it_to_zeros(); stage1(); - if (this->m_status == FEASIBLE) { + if (this->m_status == lp_status::FEASIBLE) { stage2(); } } diff --git a/src/util/lp/lp_dual_simplex_instances.cpp b/src/util/lp/lp_dual_simplex_instances.cpp index 6610814d8..a79a93748 100644 --- a/src/util/lp/lp_dual_simplex_instances.cpp +++ b/src/util/lp/lp_dual_simplex_instances.cpp @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #include "util/lp/lp_dual_simplex.hpp" -template lean::mpq lean::lp_dual_simplex::get_current_cost() const; -template void lean::lp_dual_simplex::find_maximal_solution(); -template double lean::lp_dual_simplex::get_current_cost() const; -template void lean::lp_dual_simplex::find_maximal_solution(); +template lp::mpq lp::lp_dual_simplex::get_current_cost() const; +template void lp::lp_dual_simplex::find_maximal_solution(); +template double lp::lp_dual_simplex::get_current_cost() const; +template void lp::lp_dual_simplex::find_maximal_solution(); diff --git a/src/util/lp/lp_primal_core_solver.h b/src/util/lp/lp_primal_core_solver.h index 3fada1e5d..7577516d2 100644 --- a/src/util/lp/lp_primal_core_solver.h +++ b/src/util/lp/lp_primal_core_solver.h @@ -23,7 +23,7 @@ #include "util/lp/binary_heap_priority_queue.h" #include "util/lp/int_set.h" #include "util/lp/iterator_on_row.h" -namespace lean { +namespace lp { // This core solver solves (Ax=b, low_bound_values \leq x \leq upper_bound_values, maximize costs*x ) // The right side b is given implicitly by x and the basis @@ -70,7 +70,7 @@ public: // unsigned len = 100000000; // for (unsigned j : this->m_inf_set.m_index) { // int i = this->m_basis_heading[j]; - // lean_assert(i >= 0); + // lp_assert(i >= 0); // unsigned row_len = this->m_A.m_rows[i].size(); // if (row_len < len) { // choices.clear(); @@ -98,8 +98,8 @@ public: bool column_is_benefitial_for_entering_basis_on_sign_row_strategy(unsigned j, int sign) const { // sign = 1 means the x of the basis column of the row has to grow to become feasible, when the coeff before j is neg, or x - has to diminish when the coeff is pos // we have xbj = -aj * xj - lean_assert(this->m_basis_heading[j] < 0); - lean_assert(this->column_is_feasible(j)); + lp_assert(this->m_basis_heading[j] < 0); + lp_assert(this->column_is_feasible(j)); switch (this->m_column_types[j]) { case column_type::free_column: return true; case column_type::fixed: return false; @@ -117,13 +117,13 @@ public: return !this->x_is_at_upper_bound(j); } - lean_assert(false); // cannot be here + lp_assert(false); // cannot be here return false; } bool needs_to_grow(unsigned bj) const { - lean_assert(!this->column_is_feasible(bj)); + lp_assert(!this->column_is_feasible(bj)); switch(this->m_column_types[bj]) { case column_type::free_column: return false; @@ -134,12 +134,12 @@ public: default: return false; } - lean_assert(false); // unreachable + lp_assert(false); // unreachable return false; } int inf_sign_of_column(unsigned bj) const { - lean_assert(!this->column_is_feasible(bj)); + lp_assert(!this->column_is_feasible(bj)); switch(this->m_column_types[bj]) { case column_type::free_column: return 0; @@ -151,7 +151,7 @@ public: default: return -1; } - lean_assert(false); // unreachable + lp_assert(false); // unreachable return 0; } @@ -159,7 +159,7 @@ public: bool monoid_can_decrease(const row_cell & rc) const { unsigned j = rc.m_j; - lean_assert(this->column_is_feasible(j)); + lp_assert(this->column_is_feasible(j)); switch (this->m_column_types[j]) { case column_type::free_column: return true; @@ -186,13 +186,13 @@ public: default: return false; } - lean_assert(false); // unreachable + lp_assert(false); // unreachable return false; } bool monoid_can_increase(const row_cell & rc) const { unsigned j = rc.m_j; - lean_assert(this->column_is_feasible(j)); + lp_assert(this->column_is_feasible(j)); switch (this->m_column_types[j]) { case column_type::free_column: return true; @@ -219,7 +219,7 @@ public: default: return false; } - lean_assert(false); // unreachable + lp_assert(false); // unreachable return false; } @@ -329,24 +329,24 @@ public: } void limit_theta_on_basis_column_for_inf_case_m_neg_upper_bound(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m < 0 && this->m_column_types[j] == column_type::upper_bound); + lp_assert(m < 0 && this->m_column_types[j] == column_type::upper_bound); limit_inf_on_upper_bound_m_neg(m, this->m_x[j], this->m_upper_bounds[j], theta, unlimited); } void limit_theta_on_basis_column_for_inf_case_m_neg_low_bound(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m < 0 && this->m_column_types[j] == column_type::low_bound); + lp_assert(m < 0 && this->m_column_types[j] == column_type::low_bound); limit_inf_on_bound_m_neg(m, this->m_x[j], this->m_low_bounds[j], theta, unlimited); } void limit_theta_on_basis_column_for_inf_case_m_pos_low_bound(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m > 0 && this->m_column_types[j] == column_type::low_bound); + lp_assert(m > 0 && this->m_column_types[j] == column_type::low_bound); limit_inf_on_low_bound_m_pos(m, this->m_x[j], this->m_low_bounds[j], theta, unlimited); } void limit_theta_on_basis_column_for_inf_case_m_pos_upper_bound(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m > 0 && this->m_column_types[j] == column_type::upper_bound); + lp_assert(m > 0 && this->m_column_types[j] == column_type::upper_bound); limit_inf_on_bound_m_pos(m, this->m_x[j], this->m_upper_bounds[j], theta, unlimited); }; @@ -388,7 +388,7 @@ public: bool need_to_switch_costs() const { if (this->m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows) return false; - // lean_assert(calc_current_x_is_feasible() == current_x_is_feasible()); + // lp_assert(calc_current_x_is_feasible() == current_x_is_feasible()); return this->current_x_is_feasible() == this->m_using_infeas_costs; } @@ -443,7 +443,7 @@ public: if (j == -1) return -1; - lean_assert(!this->column_is_feasible(j)); + lp_assert(!this->column_is_feasible(j)); switch (this->m_column_types[j]) { case column_type::fixed: case column_type::upper_bound: @@ -459,7 +459,8 @@ public: new_val_for_leaving = this->m_low_bounds[j]; break; default: - lean_assert(false); + lp_assert(false); + new_val_for_leaving = numeric_traits::zero(); // does not matter } return j; } @@ -468,7 +469,7 @@ public: X new_val_for_leaving; int leaving = find_leaving_tableau_rows(new_val_for_leaving); if (leaving == -1) { - this->set_status(OPTIMAL); + this->set_status(lp_status::OPTIMAL); return; } @@ -484,14 +485,14 @@ public: T a_ent; int entering = find_beneficial_column_in_row_tableau_rows(this->m_basis_heading[leaving], a_ent); if (entering == -1) { - this->set_status(INFEASIBLE); + this->set_status(lp_status::INFEASIBLE); return; } X theta = (this->m_x[leaving] - new_val_for_leaving) / a_ent; advance_on_entering_and_leaving_tableau_rows(entering, leaving, theta ); - lean_assert(this->m_x[leaving] == new_val_for_leaving); + lp_assert(this->m_x[leaving] == new_val_for_leaving); if (this->current_x_is_feasible()) - this->set_status(OPTIMAL); + this->set_status(lp_status::OPTIMAL); } void fill_breakpoints_array(unsigned entering); @@ -506,13 +507,13 @@ public: void update_basis_and_x_with_comparison(unsigned entering, unsigned leaving, X delta); void decide_on_status_when_cannot_find_entering() { - lean_assert(!need_to_switch_costs()); - this->set_status(this->current_x_is_feasible()? OPTIMAL: INFEASIBLE); + lp_assert(!need_to_switch_costs()); + this->set_status(this->current_x_is_feasible()? lp_status::OPTIMAL: lp_status::INFEASIBLE); } // void limit_theta_on_basis_column_for_feas_case_m_neg(unsigned j, const T & m, X & theta) { - // lean_assert(m < 0); - // lean_assert(this->m_column_type[j] == low_bound || this->m_column_type[j] == boxed); + // lp_assert(m < 0); + // lp_assert(this->m_column_type[j] == low_bound || this->m_column_type[j] == boxed); // const X & eps = harris_eps_for_bound(this->m_low_bounds[j]); // if (this->above_bound(this->m_x[j], this->m_low_bounds[j])) { // theta = std::min((this->m_low_bounds[j] -this->m_x[j] - eps) / m, theta); @@ -521,7 +522,7 @@ public: // } void limit_theta_on_basis_column_for_feas_case_m_neg_no_check(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m < 0); + lp_assert(m < 0); const X& eps = harris_eps_for_bound(this->m_low_bounds[j]); limit_theta((this->m_low_bounds[j] - this->m_x[j] - eps) / m, theta, unlimited); if (theta < zero_of_type()) theta = zero_of_type(); @@ -529,7 +530,7 @@ public: bool limit_inf_on_bound_m_neg(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) { // x gets smaller - lean_assert(m < 0); + lp_assert(m < 0); if (numeric_traits::precise()) { if (this->below_bound(x, bound)) return false; if (this->above_bound(x, bound)) { @@ -553,7 +554,7 @@ public: bool limit_inf_on_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) { // x gets larger - lean_assert(m > 0); + lp_assert(m > 0); if (numeric_traits::precise()) { if (this->above_bound(x, bound)) return false; if (this->below_bound(x, bound)) { @@ -578,14 +579,14 @@ public: void limit_inf_on_low_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) { if (numeric_traits::precise()) { // x gets larger - lean_assert(m > 0); + lp_assert(m > 0); if (this->below_bound(x, bound)) { limit_theta((bound - x) / m, theta, unlimited); } } else { // x gets larger - lean_assert(m > 0); + lp_assert(m > 0); const X& eps = harris_eps_for_bound(bound); if (this->below_bound(x, bound)) { limit_theta((bound - x + eps) / m, theta, unlimited); @@ -595,7 +596,7 @@ public: void limit_inf_on_upper_bound_m_neg(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) { // x gets smaller - lean_assert(m < 0); + lp_assert(m < 0); const X& eps = harris_eps_for_bound(bound); if (this->above_bound(x, bound)) { limit_theta((bound - x - eps) / m, theta, unlimited); @@ -603,7 +604,7 @@ public: } void limit_theta_on_basis_column_for_inf_case_m_pos_boxed(unsigned j, const T & m, X & theta, bool & unlimited) { - // lean_assert(m > 0 && this->m_column_type[j] == column_type::boxed); + // lp_assert(m > 0 && this->m_column_type[j] == column_type::boxed); const X & x = this->m_x[j]; const X & lbound = this->m_low_bounds[j]; @@ -623,7 +624,7 @@ public: } void limit_theta_on_basis_column_for_inf_case_m_neg_boxed(unsigned j, const T & m, X & theta, bool & unlimited) { - // lean_assert(m < 0 && this->m_column_type[j] == column_type::boxed); + // lp_assert(m < 0 && this->m_column_type[j] == column_type::boxed); const X & x = this->m_x[j]; const X & ubound = this->m_upper_bounds[j]; if (this->above_bound(x, ubound)) { @@ -641,7 +642,7 @@ public: } } void limit_theta_on_basis_column_for_feas_case_m_pos(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m > 0); + lp_assert(m > 0); const T& eps = harris_eps_for_bound(this->m_upper_bounds[j]); if (this->below_bound(this->m_x[j], this->m_upper_bounds[j])) { limit_theta((this->m_upper_bounds[j] - this->m_x[j] + eps) / m, theta, unlimited); @@ -653,7 +654,7 @@ public: } void limit_theta_on_basis_column_for_feas_case_m_pos_no_check(unsigned j, const T & m, X & theta, bool & unlimited ) { - lean_assert(m > 0); + lp_assert(m > 0); const X& eps = harris_eps_for_bound(this->m_upper_bounds[j]); limit_theta( (this->m_upper_bounds[j] - this->m_x[j] + eps) / m, theta, unlimited); if (theta < zero_of_type()) { @@ -719,7 +720,7 @@ public: break; default: - lean_unreachable(); + lp_unreachable(); } if (!unlimited && theta < zero_of_type()) { theta = zero_of_type(); @@ -778,7 +779,7 @@ public: if (this->m_basis_heading[j] < 0) continue; if (!this->column_is_feasible(j)) - this->m_inf_set.insert(j); + this->insert_column_into_inf_set(j); } } @@ -802,7 +803,7 @@ public: case column_type::free_column: return 0; default: - lean_assert(false); + lp_assert(false); } return 0; } @@ -837,7 +838,7 @@ public: return -1; break; default: - lean_assert(false); + lp_assert(false); } return 0; @@ -863,7 +864,7 @@ public: // the delta is between the old and the new cost (old - new) void update_reduced_cost_for_basic_column_cost_change(const T & delta, unsigned j) { - lean_assert(this->m_basis_heading[j] >= 0); + lp_assert(this->m_basis_heading[j] >= 0); unsigned i = static_cast(this->m_basis_heading[j]); for (const row_cell & rc : this->m_A.m_rows[i]) { unsigned k = rc.m_j; @@ -914,7 +915,7 @@ public: } else { m_converted_harris_eps = zero_of_type(); } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } // constructor @@ -942,7 +943,7 @@ public: upper_bound_values), m_beta(A.row_count()), m_converted_harris_eps(convert_struct::convert(this->m_settings.harris_feasibility_tolerance)) { - lean_assert(initial_x_is_correct()); + lp_assert(initial_x_is_correct()); m_low_bounds_dummy.resize(A.column_count(), zero_of_type()); m_enter_price_eps = numeric_traits::precise() ? numeric_traits::zero() : T(1e-5); #ifdef LEAN_DEBUG diff --git a/src/util/lp/lp_primal_core_solver.hpp b/src/util/lp/lp_primal_core_solver.hpp index 47eec468a..27c92e5e0 100644 --- a/src/util/lp/lp_primal_core_solver.hpp +++ b/src/util/lp/lp_primal_core_solver.hpp @@ -9,13 +9,13 @@ #include #include #include "util/lp/lp_primal_core_solver.h" -namespace lean { +namespace lp { // This core solver solves (Ax=b, low_bound_values \leq x \leq upper_bound_values, maximize costs*x ) // The right side b is given implicitly by x and the basis template void lp_primal_core_solver::sort_non_basis_rational() { - lean_assert(numeric_traits::precise()); + lp_assert(numeric_traits::precise()); if (this->m_settings.use_tableau()) { std::sort(this->m_nbasis.begin(), this->m_nbasis.end(), [this](unsigned a, unsigned b) { unsigned ca = this->m_A.number_of_non_zeroes_in_column(a); @@ -70,11 +70,11 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_on_breakpoin const T & d = this->m_d[j]; switch (this->m_column_types[j]) { case column_type::low_bound: - lean_assert(this->x_is_at_low_bound(j)); + lp_assert(this->x_is_at_low_bound(j)); ret = d < -m_epsilon_of_reduced_cost; break; case column_type::upper_bound: - lean_assert(this->x_is_at_upper_bound(j)); + lp_assert(this->x_is_at_upper_bound(j)); ret = d > m_epsilon_of_reduced_cost; break; case column_type::fixed: @@ -83,7 +83,7 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_on_breakpoin case column_type::boxed: { bool low_bound = this->x_is_at_low_bound(j); - lean_assert(low_bound || this->x_is_at_upper_bound(j)); + lp_assert(low_bound || this->x_is_at_upper_bound(j)); ret = (low_bound && d < -m_epsilon_of_reduced_cost) || ((!low_bound) && d > m_epsilon_of_reduced_cost); } break; @@ -91,7 +91,7 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_on_breakpoin ret = d > m_epsilon_of_reduced_cost || d < - m_epsilon_of_reduced_cost; break; default: - lean_unreachable(); + lp_unreachable(); ret = false; break; } @@ -127,14 +127,14 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_basis(unsign } break; default: - lean_unreachable(); + lp_unreachable(); break; } return false; } template bool lp_primal_core_solver::column_is_benefitial_for_entering_basis_precise(unsigned j) const { - lean_assert (numeric_traits::precise()); + lp_assert (numeric_traits::precise()); if (this->m_using_infeas_costs && this->m_settings.use_breakpoints_in_feasibility_search) return column_is_benefitial_for_entering_on_breakpoints(j); const T& dj = this->m_d[j]; @@ -167,7 +167,7 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_basis_precis } break; default: - lean_unreachable(); + lp_unreachable(); break; } return false; @@ -175,7 +175,7 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_basis_precis template int lp_primal_core_solver::choose_entering_column_presize(unsigned number_of_benefitial_columns_to_go_over) { // at this moment m_y = cB * B(-1) - lean_assert(numeric_traits::precise()); + lp_assert(numeric_traits::precise()); if (number_of_benefitial_columns_to_go_over == 0) return -1; if (this->m_basis_sort_counter == 0) { @@ -259,7 +259,7 @@ int lp_primal_core_solver::choose_entering_column(unsigned number_of_benef template int lp_primal_core_solver::advance_on_sorted_breakpoints(unsigned entering, X &t) { T slope_at_entering = this->m_d[entering]; breakpoint * last_bp = nullptr; - lean_assert(m_breakpoint_indices_queue.is_empty()==false); + lp_assert(m_breakpoint_indices_queue.is_empty()==false); while (m_breakpoint_indices_queue.is_empty() == false) { unsigned bi = m_breakpoint_indices_queue.dequeue(); breakpoint *b = &m_breakpoints[bi]; @@ -274,7 +274,7 @@ template int lp_primal_core_solver::advance_on_so } } } - lean_assert (last_bp != nullptr); + lp_assert (last_bp != nullptr); t = last_bp->m_delta; return last_bp->m_j; } @@ -282,13 +282,13 @@ template int lp_primal_core_solver::advance_on_so template int lp_primal_core_solver::find_leaving_and_t_with_breakpoints(unsigned entering, X & t){ - lean_assert(this->precise() == false); + lp_assert(this->precise() == false); fill_breakpoints_array(entering); return advance_on_sorted_breakpoints(entering, t); } template bool lp_primal_core_solver::get_harris_theta(X & theta) { - lean_assert(this->m_ed.is_OK()); + lp_assert(this->m_ed.is_OK()); bool unlimited = true; for (unsigned i : this->m_ed.m_index) { if (this->m_settings.abs_val_is_smaller_than_pivot_tolerance(this->m_ed[i])) continue; @@ -345,13 +345,13 @@ template bool lp_primal_core_solver::try_jump_to_ if (m_sign_of_entering_delta > 0) { t = this->m_upper_bounds[entering] - this->m_x[entering]; if (unlimited || t <= theta){ - lean_assert(t >= zero_of_type()); + lp_assert(t >= zero_of_type()); return true; } } else { // m_sign_of_entering_delta == -1 t = this->m_x[entering] - this->m_low_bounds[entering]; if (unlimited || t <= theta) { - lean_assert(t >= zero_of_type()); + lp_assert(t >= zero_of_type()); return true; } } @@ -360,7 +360,7 @@ template bool lp_primal_core_solver::try_jump_to_ if (m_sign_of_entering_delta > 0) { t = this->m_upper_bounds[entering] - this->m_x[entering]; if (unlimited || t <= theta){ - lean_assert(t >= zero_of_type()); + lp_assert(t >= zero_of_type()); return true; } } @@ -369,7 +369,7 @@ template bool lp_primal_core_solver::try_jump_to_ if (m_sign_of_entering_delta < 0) { t = this->m_x[entering] - this->m_low_bounds[entering]; if (unlimited || t <= theta) { - lean_assert(t >= zero_of_type()); + lp_assert(t >= zero_of_type()); return true; } } @@ -405,7 +405,7 @@ template int lp_primal_core_solver::find_leaving_ do { unsigned i = this->m_ed.m_index[k]; const T & ed = this->m_ed[i]; - lean_assert(!numeric_traits::is_zero(ed)); + lp_assert(!numeric_traits::is_zero(ed)); unsigned j = this->m_basis[i]; limit_theta_on_basis_column(j, - ed * m_sign_of_entering_delta, t, unlimited); if (!unlimited) { @@ -424,7 +424,7 @@ template int lp_primal_core_solver::find_leaving_ while (k != initial_k) { unsigned i = this->m_ed.m_index[k]; const T & ed = this->m_ed[i]; - lean_assert(!numeric_traits::is_zero(ed)); + lp_assert(!numeric_traits::is_zero(ed)); unsigned j = this->m_basis[i]; unlimited = true; limit_theta_on_basis_column(j, -ed * m_sign_of_entering_delta, ratio, unlimited); @@ -464,7 +464,7 @@ template int lp_primal_core_solver::find_leavi return find_leaving_and_t_with_breakpoints(entering, t); X theta; bool unlimited = get_harris_theta(theta); - lean_assert(unlimited || theta >= zero_of_type()); + lp_assert(unlimited || theta >= zero_of_type()); if (try_jump_to_another_bound_on_entering(entering, theta, t, unlimited)) return entering; if (unlimited) return -1; @@ -533,7 +533,7 @@ template X lp_primal_core_solver::get_max_boun template void lp_primal_core_solver::check_Ax_equal_b() { dense_matrix d(this->m_A); T * ls = d.apply_from_left_with_different_dims(this->m_x); - lean_assert(vectors_are_equal(ls, this->m_b, this->m_m())); + lp_assert(vectors_are_equal(ls, this->m_b, this->m_m())); delete [] ls; } template void lp_primal_core_solver::check_the_bounds() { @@ -543,8 +543,8 @@ template void lp_primal_core_solver::check_the } template void lp_primal_core_solver::check_bound(unsigned i) { - lean_assert (!(this->column_has_low_bound(i) && (numeric_traits::zero() > this->m_x[i]))); - lean_assert (!(this->column_has_upper_bound(i) && (this->m_upper_bounds[i] < this->m_x[i]))); + lp_assert (!(this->column_has_low_bound(i) && (numeric_traits::zero() > this->m_x[i]))); + lp_assert (!(this->column_has_upper_bound(i) && (this->m_upper_bounds[i] < this->m_x[i]))); } template void lp_primal_core_solver::check_correctness() { @@ -560,8 +560,8 @@ void lp_primal_core_solver::update_reduced_costs_from_pivot_row(unsigned e // the basis heading has changed already #ifdef LEAN_DEBUG auto & basis_heading = this->m_basis_heading; - lean_assert(basis_heading[entering] >= 0 && static_cast(basis_heading[entering]) < this->m_m()); - lean_assert(basis_heading[leaving] < 0); + lp_assert(basis_heading[entering] >= 0 && static_cast(basis_heading[entering]) < this->m_m()); + lp_assert(basis_heading[leaving] < 0); #endif T pivot = this->m_pivot_row[entering]; T dq = this->m_d[entering]/pivot; @@ -584,7 +584,7 @@ void lp_primal_core_solver::update_reduced_costs_from_pivot_row(unsigned e template int lp_primal_core_solver::refresh_reduced_cost_at_entering_and_check_that_it_is_off(unsigned entering) { if (numeric_traits::precise()) return 0; T reduced_at_entering_was = this->m_d[entering]; // can benefit from going over non-zeros of m_ed - lean_assert(abs(reduced_at_entering_was) > m_epsilon_of_reduced_cost); + lp_assert(abs(reduced_at_entering_was) > m_epsilon_of_reduced_cost); T refreshed_cost = this->m_costs[entering]; unsigned i = this->m_m(); while (i--) refreshed_cost -= this->m_costs[this->m_basis[i]] * this->m_ed[i]; @@ -619,7 +619,7 @@ template void lp_primal_core_solver::backup_an m_costs_backup = this->m_costs; } else { T cost_max = std::max(max_abs_in_vector(this->m_costs), T(1)); - lean_assert(m_costs_backup.size() == 0); + lp_assert(m_costs_backup.size() == 0); for (unsigned j = 0; j < this->m_costs.size(); j++) m_costs_backup.push_back(this->m_costs[j] /= cost_max); } @@ -649,16 +649,16 @@ template void lp_primal_core_solver::init_run( template void lp_primal_core_solver::calc_working_vector_beta_for_column_norms(){ - lean_assert(numeric_traits::precise() == false); - lean_assert(this->m_ed.is_OK()); - lean_assert(m_beta.is_OK()); + lp_assert(numeric_traits::precise() == false); + lp_assert(this->m_ed.is_OK()); + lp_assert(m_beta.is_OK()); m_beta = this->m_ed; this->m_factorization->solve_yB_with_error_check_indexed(m_beta, this->m_basis_heading, this->m_basis, this->m_settings); } template void lp_primal_core_solver::advance_on_entering_equal_leaving(int entering, X & t) { - lean_assert(!this->A_mult_x_is_off() ); + lp_assert(!this->A_mult_x_is_off() ); this->update_x(entering, t * m_sign_of_entering_delta); if (this->A_mult_x_is_off_on_index(this->m_ed.m_index) && !this->find_x_by_solving()) { this->init_lu(); @@ -670,7 +670,7 @@ void lp_primal_core_solver::advance_on_entering_equal_leaving(int entering } } if (this->m_using_infeas_costs) { - lean_assert(is_zero(this->m_costs[entering])); + lp_assert(is_zero(this->m_costs[entering])); init_infeasibility_costs_for_changed_basis_only(); } if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible()) @@ -683,10 +683,10 @@ void lp_primal_core_solver::advance_on_entering_equal_leaving(int entering } template void lp_primal_core_solver::advance_on_entering_and_leaving(int entering, int leaving, X & t) { - lean_assert(entering >= 0 && m_non_basis_list.back() == static_cast(entering)); - lean_assert(this->m_using_infeas_costs || t >= zero_of_type()); - lean_assert(leaving >= 0 && entering >= 0); - lean_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes + lp_assert(entering >= 0 && m_non_basis_list.back() == static_cast(entering)); + lp_assert(this->m_using_infeas_costs || t >= zero_of_type()); + lp_assert(leaving >= 0 && entering >= 0); + lp_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes if (entering == leaving) { advance_on_entering_equal_leaving(entering, t); return; @@ -698,14 +698,14 @@ template void lp_primal_core_solver::advance_on_en int pivot_compare_result = this->pivots_in_column_and_row_are_different(entering, leaving); if (!pivot_compare_result){;} else if (pivot_compare_result == 2) { // the sign is changed, cannot continue - this->set_status(UNSTABLE); + this->set_status(lp_status::UNSTABLE); this->iters_with_no_cost_growing()++; return; } else { - lean_assert(pivot_compare_result == 1); + lp_assert(pivot_compare_result == 1); this->init_lu(); if (this->m_factorization == nullptr || this->m_factorization->get_status() != LU_status::OK) { - this->set_status(UNSTABLE); + this->set_status(lp_status::UNSTABLE); this->iters_with_no_cost_growing()++; return; } @@ -717,10 +717,10 @@ template void lp_primal_core_solver::advance_on_en t = -t; } if (!this->update_basis_and_x(entering, leaving, t)) { - if (this->get_status() == FLOATING_POINT_ERROR) + if (this->get_status() == lp_status::FLOATING_POINT_ERROR) return; if (this->m_look_for_feasible_solution_only) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); return; } init_reduced_costs(); @@ -733,7 +733,7 @@ template void lp_primal_core_solver::advance_on_en } if (this->current_x_is_feasible()) { - this->set_status(FEASIBLE); + this->set_status(lp_status::FEASIBLE); if (this->m_look_for_feasible_solution_only) return; } @@ -746,7 +746,7 @@ template void lp_primal_core_solver::advance_on_en } else { update_reduced_costs_from_pivot_row(entering, leaving); } - lean_assert(!need_to_switch_costs()); + lp_assert(!need_to_switch_costs()); std::list::iterator it = m_non_basis_list.end(); it--; * it = static_cast(leaving); @@ -754,13 +754,13 @@ template void lp_primal_core_solver::advance_on_en template void lp_primal_core_solver::advance_on_entering_precise(int entering) { - lean_assert(numeric_traits::precise()); - lean_assert(entering > -1); + lp_assert(numeric_traits::precise()); + lp_assert(entering > -1); this->solve_Bd(entering); X t; int leaving = find_leaving_and_t_precise(entering, t); if (leaving == -1) { - this->set_status(UNBOUNDED); + this->set_status(lp_status::UNBOUNDED); return; } advance_on_entering_and_leaving(entering, leaving, t); @@ -771,12 +771,12 @@ template void lp_primal_core_solver::advance_on_e advance_on_entering_precise(entering); return; } - lean_assert(entering > -1); + lp_assert(entering > -1); this->solve_Bd(entering); int refresh_result = refresh_reduced_cost_at_entering_and_check_that_it_is_off(entering); if (refresh_result) { if (this->m_look_for_feasible_solution_only) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); return; } @@ -791,7 +791,7 @@ template void lp_primal_core_solver::advance_on_e int leaving = find_leaving_and_t(entering, t); if (leaving == -1){ if (!this->current_x_is_feasible()) { - lean_assert(!numeric_traits::precise()); // we cannot have unbounded with inf costs + lp_assert(!numeric_traits::precise()); // we cannot have unbounded with inf costs // if (m_look_for_feasible_solution_only) { // this->m_status = INFEASIBLE; @@ -799,19 +799,19 @@ template void lp_primal_core_solver::advance_on_e // } - if (this->get_status() == UNSTABLE) { - this->set_status(FLOATING_POINT_ERROR); + if (this->get_status() == lp_status::UNSTABLE) { + this->set_status(lp_status::FLOATING_POINT_ERROR); return; } init_infeasibility_costs(); - this->set_status(UNSTABLE); + this->set_status(lp_status::UNSTABLE); return; } - if (this->get_status() == TENTATIVE_UNBOUNDED) { - this->set_status(UNBOUNDED); + if (this->get_status() == lp_status::TENTATIVE_UNBOUNDED) { + this->set_status(lp_status::UNBOUNDED); } else { - this->set_status(TENTATIVE_UNBOUNDED); + this->set_status(lp_status::TENTATIVE_UNBOUNDED); } return; } @@ -825,7 +825,7 @@ template void lp_primal_core_solver::push_forw template unsigned lp_primal_core_solver::get_number_of_non_basic_column_to_try_for_enter() { unsigned ret = static_cast(this->m_nbasis.size()); - if (this->get_status() == TENTATIVE_UNBOUNDED) + if (this->get_status() == lp_status::TENTATIVE_UNBOUNDED) return ret; // we really need to find entering with a large reduced cost if (ret > 300) { ret = (unsigned)(ret * this->m_settings.percent_of_entering_to_check / 100); @@ -852,12 +852,12 @@ template unsigned lp_primal_core_solver::solve() init_run(); if (this->current_x_is_feasible() && this->m_look_for_feasible_solution_only) { - this->set_status(FEASIBLE); + this->set_status(lp_status::FEASIBLE); return 0; } if ((!numeric_traits::precise()) && this->A_mult_x_is_off()) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); return 0; } do { @@ -865,10 +865,10 @@ template unsigned lp_primal_core_solver::solve() return this->total_iterations(); } one_iteration(); - lean_assert(!this->m_using_infeas_costs || this->costs_on_nbasis_are_zeros()); + lp_assert(!this->m_using_infeas_costs || this->costs_on_nbasis_are_zeros()); switch (this->get_status()) { - case OPTIMAL: // double check that we are at optimum - case INFEASIBLE: + case lp_status::OPTIMAL: // double check that we are at optimum + case lp_status::INFEASIBLE: if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible()) break; if (!numeric_traits::precise()) { @@ -877,7 +877,7 @@ template unsigned lp_primal_core_solver::solve() this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status (FLOATING_POINT_ERROR); + this->set_status (lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); @@ -885,7 +885,7 @@ template unsigned lp_primal_core_solver::solve() decide_on_status_when_cannot_find_entering(); break; } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } else { // precise case if (this->m_look_for_feasible_solution_only) { // todo: keep the reduced costs correct all the time! init_reduced_costs(); @@ -893,31 +893,31 @@ template unsigned lp_primal_core_solver::solve() decide_on_status_when_cannot_find_entering(); break; } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } } break; - case TENTATIVE_UNBOUNDED: + case lp_status::TENTATIVE_UNBOUNDED: this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); break; - case UNBOUNDED: + case lp_status::UNBOUNDED: if (this->current_x_is_infeasible()) { init_reduced_costs(); - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } break; - case UNSTABLE: - lean_assert(! (numeric_traits::precise())); + case lp_status::UNSTABLE: + lp_assert(! (numeric_traits::precise())); this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); @@ -926,13 +926,13 @@ template unsigned lp_primal_core_solver::solve() default: break; // do nothing } - } while (this->get_status() != FLOATING_POINT_ERROR + } while (this->get_status() != lp_status::FLOATING_POINT_ERROR && - this->get_status() != UNBOUNDED + this->get_status() != lp_status::UNBOUNDED && - this->get_status() != OPTIMAL + this->get_status() != lp_status::OPTIMAL && - this->get_status() != INFEASIBLE + this->get_status() != lp_status::INFEASIBLE && this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements && @@ -940,7 +940,7 @@ template unsigned lp_primal_core_solver::solve() && !(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)); - lean_assert(this->get_status() == FLOATING_POINT_ERROR + lp_assert(this->get_status() == lp_status::FLOATING_POINT_ERROR || this->current_x_is_feasible() == false || @@ -957,7 +957,7 @@ template void lp_primal_core_solver::delete_fa // according to Swietanowski, " A new steepest edge approximation for the simplex method for linear programming" template void lp_primal_core_solver::init_column_norms() { - lean_assert(numeric_traits::precise() == false); + lp_assert(numeric_traits::precise() == false); for (unsigned j = 0; j < this->m_n(); j++) { this->m_column_norms[j] = T(static_cast(this->m_A.m_columns[j].size() + 1)) @@ -967,7 +967,7 @@ template void lp_primal_core_solver::init_column_ // debug only template T lp_primal_core_solver::calculate_column_norm_exactly(unsigned j) { - lean_assert(numeric_traits::precise() == false); + lp_assert(numeric_traits::precise() == false); indexed_vector w(this->m_m()); this->m_A.copy_column_to_vector(j, w); vector d(this->m_m()); @@ -979,8 +979,8 @@ template T lp_primal_core_solver::calculate_colum } template void lp_primal_core_solver::update_or_init_column_norms(unsigned entering, unsigned leaving) { - lean_assert(numeric_traits::precise() == false); - lean_assert(m_column_norm_update_counter <= this->m_settings.column_norms_update_frequency); + lp_assert(numeric_traits::precise() == false); + lp_assert(m_column_norm_update_counter <= this->m_settings.column_norms_update_frequency); if (m_column_norm_update_counter == this->m_settings.column_norms_update_frequency) { m_column_norm_update_counter = 0; init_column_norms(); @@ -992,7 +992,7 @@ template void lp_primal_core_solver::update_or // following Swietanowski - A new steepest ... template void lp_primal_core_solver::update_column_norms(unsigned entering, unsigned leaving) { - lean_assert(numeric_traits::precise() == false); + lp_assert(numeric_traits::precise() == false); T pivot = this->m_pivot_row[entering]; T g_ent = calculate_norm_of_entering_exactly() / pivot / pivot; if (!numeric_traits::precise()) { @@ -1027,8 +1027,8 @@ template T lp_primal_core_solver::calculate_no // calling it stage1 is too cryptic template void lp_primal_core_solver::find_feasible_solution() { this->m_look_for_feasible_solution_only = true; - lean_assert(this->non_basic_columns_are_set_correctly()); - this->set_status(UNKNOWN); + lp_assert(this->non_basic_columns_are_set_correctly()); + this->set_status(lp_status::UNKNOWN); solve(); } @@ -1072,15 +1072,15 @@ template void lp_primal_core_solver::fill_breakpo template bool lp_primal_core_solver::done() { - if (this->get_status() == OPTIMAL || this->get_status() == FLOATING_POINT_ERROR) return true; - if (this->get_status() == INFEASIBLE) { + if (this->get_status() == lp_status::OPTIMAL || this->get_status() == lp_status::FLOATING_POINT_ERROR) return true; + if (this->get_status() == lp_status::INFEASIBLE) { return true; } if (this->m_iters_with_no_cost_growing >= this->m_settings.max_number_of_iterations_with_no_improvements) { - this->get_status() = ITERATIONS_EXHAUSTED; return true; + this->get_status() = lp_status::ITERATIONS_EXHAUSTED; return true; } if (this->total_iterations() >= this->m_settings.max_total_number_of_iterations) { - this->get_status() = ITERATIONS_EXHAUSTED; return true; + this->get_status() = lp_status::ITERATIONS_EXHAUSTED; return true; } return false; } @@ -1095,8 +1095,8 @@ void lp_primal_core_solver::init_infeasibility_costs_for_changed_basis_onl template void lp_primal_core_solver::init_infeasibility_costs() { - lean_assert(this->m_x.size() >= this->m_n()); - lean_assert(this->m_column_types.size() >= this->m_n()); + lp_assert(this->m_x.size() >= this->m_n()); + lp_assert(this->m_column_types.size() >= this->m_n()); for (unsigned j = this->m_n(); j--;) init_infeasibility_cost_for_column(j); this->m_using_infeas_costs = true; @@ -1138,7 +1138,8 @@ lp_primal_core_solver::get_infeasibility_cost_for_column(unsigned j) const ret = numeric_traits::zero(); break; default: - lean_assert(false); + lp_assert(false); + ret = numeric_traits::zero(); // does not matter break; } @@ -1191,14 +1192,14 @@ lp_primal_core_solver::init_infeasibility_cost_for_column(unsigned j) { this->m_costs[j] = numeric_traits::zero(); break; default: - lean_assert(false); + lp_assert(false); break; } if (numeric_traits::is_zero(this->m_costs[j])) { - this->m_inf_set.erase(j); + this->remove_column_from_inf_set(j); } else { - this->m_inf_set.insert(j); + this->insert_column_into_inf_set(j); } if (!this->m_settings.use_breakpoints_in_feasibility_search) { this->m_costs[j] = - this->m_costs[j]; @@ -1222,7 +1223,7 @@ template void lp_primal_core_solver::print_column case column_type::free_column: out << "( _" << this->m_x[j] << "_)" << std::endl; default: - lean_unreachable(); + lp_unreachable(); } } @@ -1261,7 +1262,7 @@ template std::string lp_primal_core_solver::break case upper_break: return "upper_break"; case fixed_break: return "fixed_break"; default: - lean_assert(false); + lp_assert(false); break; } return "type is not found"; @@ -1274,7 +1275,7 @@ template void lp_primal_core_solver::print_breakp template void lp_primal_core_solver::init_reduced_costs() { - lean_assert(!this->use_tableau()); + lp_assert(!this->use_tableau()); if (this->current_x_is_infeasible() && !this->m_using_infeas_costs) { init_infeasibility_costs(); } else if (this->current_x_is_feasible() && this->m_using_infeas_costs) { @@ -1289,12 +1290,12 @@ void lp_primal_core_solver::init_reduced_costs() { template void lp_primal_core_solver::change_slope_on_breakpoint(unsigned entering, breakpoint * b, T & slope_at_entering) { if (b->m_j == entering) { - lean_assert(b->m_type != fixed_break && (!is_zero(b->m_delta))); + lp_assert(b->m_type != fixed_break && (!is_zero(b->m_delta))); slope_at_entering += m_sign_of_entering_delta; return; } - lean_assert(this->m_basis_heading[b->m_j] >= 0); + lp_assert(this->m_basis_heading[b->m_j] >= 0); unsigned i_row = this->m_basis_heading[b->m_j]; const T & d = - this->m_ed[i_row]; if (numeric_traits::is_zero(d)) return; @@ -1313,13 +1314,13 @@ template void lp_primal_core_solver::change_sl slope_at_entering += delta; break; default: - lean_assert(false); + lp_assert(false); } } template void lp_primal_core_solver::try_add_breakpoint_in_row(unsigned i) { - lean_assert(i < this->m_m()); + lp_assert(i < this->m_m()); const T & d = this->m_ed[i]; // the coefficient before m_entering in the i-th row if (d == 0) return; // the change of x[m_entering] will not change the corresponding basis x unsigned j = this->m_basis[i]; @@ -1341,7 +1342,7 @@ template void lp_primal_core_solver::try_add_b case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); break; } } @@ -1365,7 +1366,7 @@ template void lp_primal_core_solver::print_bound_ out << "inf, inf" << std::endl; break; default: - lean_assert(false); + lp_assert(false); break; } } diff --git a/src/util/lp/lp_primal_core_solver_instances.cpp b/src/util/lp/lp_primal_core_solver_instances.cpp index ca231fd34..8e5890bf5 100644 --- a/src/util/lp/lp_primal_core_solver_instances.cpp +++ b/src/util/lp/lp_primal_core_solver_instances.cpp @@ -10,18 +10,18 @@ #include "util/lp/lar_solver.h" #include "util/lp/lp_primal_core_solver.hpp" #include "util/lp/lp_primal_core_solver_tableau.hpp" -namespace lean { +namespace lp { template void lp_primal_core_solver::find_feasible_solution(); -template void lean::lp_primal_core_solver >::find_feasible_solution(); +template void lp::lp_primal_core_solver >::find_feasible_solution(); template unsigned lp_primal_core_solver::solve(); template unsigned lp_primal_core_solver::solve_with_tableau(); template unsigned lp_primal_core_solver::solve(); template unsigned lp_primal_core_solver >::solve(); -template void lean::lp_primal_core_solver::clear_breakpoints(); -template bool lean::lp_primal_core_solver::update_basis_and_x_tableau(int, int, lean::mpq const&); -template bool lean::lp_primal_core_solver::update_basis_and_x_tableau(int, int, double const&); -template bool lean::lp_primal_core_solver >::update_basis_and_x_tableau(int, int, lean::numeric_pair const&); +template void lp::lp_primal_core_solver::clear_breakpoints(); +template bool lp::lp_primal_core_solver::update_basis_and_x_tableau(int, int, lp::mpq const&); +template bool lp::lp_primal_core_solver::update_basis_and_x_tableau(int, int, double const&); +template bool lp::lp_primal_core_solver >::update_basis_and_x_tableau(int, int, lp::numeric_pair const&); } diff --git a/src/util/lp/lp_primal_core_solver_tableau.hpp b/src/util/lp/lp_primal_core_solver_tableau.hpp index 0c09c22c9..867c321ba 100644 --- a/src/util/lp/lp_primal_core_solver_tableau.hpp +++ b/src/util/lp/lp_primal_core_solver_tableau.hpp @@ -4,7 +4,7 @@ */ // this is a part of lp_primal_core_solver that deals with the tableau #include "util/lp/lp_primal_core_solver.h" -namespace lean { +namespace lp { template void lp_primal_core_solver::one_iteration_tableau() { int entering = choose_entering_column_tableau(); if (entering == -1) { @@ -13,14 +13,14 @@ template void lp_primal_core_solver::one_iteratio else { advance_on_entering_tableau(entering); } - lean_assert(this->inf_set_is_correct()); + lp_assert(this->inf_set_is_correct()); } template void lp_primal_core_solver::advance_on_entering_tableau(int entering) { X t; int leaving = find_leaving_and_t_tableau(entering, t); if (leaving == -1) { - this->set_status(UNBOUNDED); + this->set_status(lp_status::UNBOUNDED); return; } advance_on_entering_and_leaving_tableau(entering, leaving, t); @@ -37,7 +37,7 @@ template int lp_primal_core_solver::choose_enteri //this moment m_y = cB * B(-1) unsigned number_of_benefitial_columns_to_go_over = get_number_of_non_basic_column_to_try_for_enter(); - lean_assert(numeric_traits::precise()); + lp_assert(numeric_traits::precise()); if (number_of_benefitial_columns_to_go_over == 0) return -1; if (this->m_basis_sort_counter == 0) { @@ -85,12 +85,12 @@ template unsigned lp_primal_core_solver::solve_with_tableau() { init_run_tableau(); if (this->current_x_is_feasible() && this->m_look_for_feasible_solution_only) { - this->set_status(FEASIBLE); + this->set_status(lp_status::FEASIBLE); return 0; } if ((!numeric_traits::precise()) && this->A_mult_x_is_off()) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); return 0; } do { @@ -102,8 +102,8 @@ unsigned lp_primal_core_solver::solve_with_tableau() { else one_iteration_tableau(); switch (this->get_status()) { - case OPTIMAL: // double check that we are at optimum - case INFEASIBLE: + case lp_status::OPTIMAL: // double check that we are at optimum + case lp_status::INFEASIBLE: if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible()) break; if (!numeric_traits::precise()) { @@ -112,7 +112,7 @@ unsigned lp_primal_core_solver::solve_with_tableau() { this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); @@ -120,7 +120,7 @@ unsigned lp_primal_core_solver::solve_with_tableau() { decide_on_status_when_cannot_find_entering(); break; } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } else { // precise case if ((!this->infeasibility_costs_are_correct())) { init_reduced_costs_tableau(); // forcing recalc @@ -128,31 +128,31 @@ unsigned lp_primal_core_solver::solve_with_tableau() { decide_on_status_when_cannot_find_entering(); break; } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } } break; - case TENTATIVE_UNBOUNDED: + case lp_status::TENTATIVE_UNBOUNDED: this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); break; - case UNBOUNDED: + case lp_status::UNBOUNDED: if (this->current_x_is_infeasible()) { init_reduced_costs(); - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } break; - case UNSTABLE: - lean_assert(! (numeric_traits::precise())); + case lp_status::UNSTABLE: + lp_assert(! (numeric_traits::precise())); this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); @@ -161,13 +161,13 @@ unsigned lp_primal_core_solver::solve_with_tableau() { default: break; // do nothing } - } while (this->get_status() != FLOATING_POINT_ERROR + } while (this->get_status() != lp_status::FLOATING_POINT_ERROR && - this->get_status() != UNBOUNDED + this->get_status() != lp_status::UNBOUNDED && - this->get_status() != OPTIMAL + this->get_status() != lp_status::OPTIMAL && - this->get_status() != INFEASIBLE + this->get_status() != lp_status::INFEASIBLE && this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements && @@ -175,7 +175,7 @@ unsigned lp_primal_core_solver::solve_with_tableau() { && !(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)); - lean_assert(this->get_status() == FLOATING_POINT_ERROR + lp_assert(this->get_status() == lp_status::FLOATING_POINT_ERROR || this->current_x_is_feasible() == false || @@ -184,13 +184,13 @@ unsigned lp_primal_core_solver::solve_with_tableau() { } template void lp_primal_core_solver::advance_on_entering_and_leaving_tableau(int entering, int leaving, X & t) { - lean_assert(this->A_mult_x_is_off() == false); - lean_assert(leaving >= 0 && entering >= 0); - lean_assert((this->m_settings.simplex_strategy() == + lp_assert(this->A_mult_x_is_off() == false); + lp_assert(leaving >= 0 && entering >= 0); + lp_assert((this->m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows) || m_non_basis_list.back() == static_cast(entering)); - lean_assert(this->m_using_infeas_costs || !is_neg(t)); - lean_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes + lp_assert(this->m_using_infeas_costs || !is_neg(t)); + lp_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes if (entering == leaving) { advance_on_entering_equal_leaving_tableau(entering, t); return; @@ -201,7 +201,7 @@ template void lp_primal_core_solver::advance_on_en t = -t; } this->update_basis_and_x_tableau(entering, leaving, t); - lean_assert(this->A_mult_x_is_off() == false); + lp_assert(this->A_mult_x_is_off() == false); this->iters_with_no_cost_growing() = 0; } else { this->pivot_column_tableau(entering, this->m_basis_heading[leaving]); @@ -216,7 +216,7 @@ template void lp_primal_core_solver::advance_on_en this->init_reduced_costs_tableau(); } - lean_assert(!need_to_switch_costs()); + lp_assert(!need_to_switch_costs()); std::list::iterator it = m_non_basis_list.end(); it--; * it = static_cast(leaving); @@ -225,7 +225,7 @@ template void lp_primal_core_solver::advance_on_en template void lp_primal_core_solver::advance_on_entering_equal_leaving_tableau(int entering, X & t) { - lean_assert(!this->A_mult_x_is_off() ); + lp_assert(!this->A_mult_x_is_off() ); this->update_x_tableau(entering, t * m_sign_of_entering_delta); if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible()) return; @@ -246,7 +246,7 @@ template int lp_primal_core_solver::find_leaving_ const column_cell & c = col[k]; unsigned i = c.m_i; const T & ed = this->m_A.get_val(c); - lean_assert(!numeric_traits::is_zero(ed)); + lp_assert(!numeric_traits::is_zero(ed)); unsigned j = this->m_basis[i]; limit_theta_on_basis_column(j, - ed * m_sign_of_entering_delta, t, unlimited); if (!unlimited) { @@ -265,7 +265,7 @@ template int lp_primal_core_solver::find_leaving_ const column_cell & c = col[k]; unsigned i = c.m_i; const T & ed = this->m_A.get_val(c); - lean_assert(!numeric_traits::is_zero(ed)); + lp_assert(!numeric_traits::is_zero(ed)); unsigned j = this->m_basis[i]; unlimited = true; limit_theta_on_basis_column(j, -ed * m_sign_of_entering_delta, ratio, unlimited); @@ -298,12 +298,12 @@ template int lp_primal_core_solver::find_leaving_ } template void lp_primal_core_solver::init_run_tableau() { // print_matrix(&(this->m_A), std::cout); - lean_assert(this->A_mult_x_is_off() == false); - lean_assert(basis_columns_are_set_correctly()); + lp_assert(this->A_mult_x_is_off() == false); + lp_assert(basis_columns_are_set_correctly()); this->m_basis_sort_counter = 0; // to initiate the sort of the basis this->set_total_iterations(0); this->iters_with_no_cost_growing() = 0; - lean_assert(this->inf_set_is_correct()); + lp_assert(this->inf_set_is_correct()); if (this->current_x_is_feasible() && this->m_look_for_feasible_solution_only) return; if (this->m_settings.backup_costs) @@ -317,13 +317,13 @@ template void lp_primal_core_solver::init_run_tab } if (this->m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows) init_tableau_rows(); - lean_assert(this->reduced_costs_are_correct_tableau()); - lean_assert(!this->need_to_pivot_to_basis_tableau()); + lp_assert(this->reduced_costs_are_correct_tableau()); + lp_assert(!this->need_to_pivot_to_basis_tableau()); } template bool lp_primal_core_solver:: update_basis_and_x_tableau(int entering, int leaving, X const & tt) { - lean_assert(this->use_tableau()); + lp_assert(this->use_tableau()); update_x_tableau(entering, tt); this->pivot_column_tableau(entering, this->m_basis_heading[leaving]); this->change_basis(entering, leaving); @@ -340,8 +340,8 @@ update_x_tableau(unsigned entering, const X& delta) { } } else { // m_using_infeas_costs == true this->m_x[entering] += delta; - lean_assert(this->column_is_feasible(entering)); - lean_assert(this->m_costs[entering] == zero_of_type()); + lp_assert(this->column_is_feasible(entering)); + lp_assert(this->m_costs[entering] == zero_of_type()); // m_d[entering] can change because of the cost change for basic columns. for (const auto & c : this->m_A.m_columns[entering]) { unsigned i = c.m_i; @@ -349,18 +349,18 @@ update_x_tableau(unsigned entering, const X& delta) { this->m_x[j] -= delta * this->m_A.get_val(c); update_inf_cost_for_column_tableau(j); if (is_zero(this->m_costs[j])) - this->m_inf_set.erase(j); + this->remove_column_from_inf_set(j); else - this->m_inf_set.insert(j); + this->insert_column_into_inf_set(j); } } - lean_assert(this->A_mult_x_is_off() == false); + lp_assert(this->A_mult_x_is_off() == false); } template void lp_primal_core_solver:: update_inf_cost_for_column_tableau(unsigned j) { - lean_assert(this->m_settings.simplex_strategy() != simplex_strategy_enum::tableau_rows); - lean_assert(this->m_using_infeas_costs); + lp_assert(this->m_settings.simplex_strategy() != simplex_strategy_enum::tableau_rows); + lp_assert(this->m_using_infeas_costs); T new_cost = get_infeasibility_cost_for_column(j); T delta = this->m_costs[j] - new_cost; if (is_zero(delta)) diff --git a/src/util/lp/lp_primal_simplex.h b/src/util/lp/lp_primal_simplex.h index 715d76408..b55fecdcd 100644 --- a/src/util/lp/lp_primal_simplex.h +++ b/src/util/lp/lp_primal_simplex.h @@ -12,7 +12,7 @@ #include "util/lp/lp_primal_core_solver.h" #include "util/lp/lp_solver.h" #include "util/lp/iterator_on_row.h" -namespace lean { +namespace lp { template class lp_primal_simplex: public lp_solver { lp_primal_core_solver * m_core_solver; diff --git a/src/util/lp/lp_primal_simplex.hpp b/src/util/lp/lp_primal_simplex.hpp index b6b6006e5..759095355 100644 --- a/src/util/lp/lp_primal_simplex.hpp +++ b/src/util/lp/lp_primal_simplex.hpp @@ -6,7 +6,7 @@ #include "util/vector.h" #include "util/lp/lp_primal_simplex.h" -namespace lean { +namespace lp { template void lp_primal_simplex::fill_costs_and_x_for_first_stage_solver(unsigned original_number_of_columns) { unsigned slack_var = original_number_of_columns; unsigned artificial = original_number_of_columns + this->m_slacks; @@ -61,7 +61,7 @@ template void lp_primal_simplex::fill_costs_and_x int row, unsigned & slack_var, unsigned & artificial) { - lean_assert(row >= 0 && row < this->row_count()); + lp_assert(row >= 0 && row < this->row_count()); auto & constraint = this->m_constraints[this->m_core_solver_rows_to_external_rows[row]]; // we need to bring the program to the form Ax = b T rs = this->m_b[row]; @@ -86,7 +86,7 @@ template void lp_primal_simplex::fill_costs_and_x (*this->m_A)(row, slack_var) = - numeric_traits::one(); if (rs > 0) { - lean_assert(numeric_traits::is_zero(this->m_x[slack_var])); + lp_assert(numeric_traits::is_zero(this->m_x[slack_var])); // adding one artificial this->m_column_types[artificial] = column_type::low_bound; (*this->m_A)(row, artificial) = numeric_traits::one(); @@ -108,7 +108,7 @@ template void lp_primal_simplex::fill_costs_and_x if (rs < 0) { // adding one artificial - lean_assert(numeric_traits::is_zero(this->m_x[slack_var])); + lp_assert(numeric_traits::is_zero(this->m_x[slack_var])); this->m_column_types[artificial] = column_type::low_bound; (*this->m_A)(row, artificial) = - numeric_traits::one(); this->m_costs[artificial] = artificial_cost; @@ -177,12 +177,12 @@ template void lp_primal_simplex::fill_A_x_and_bas } template void lp_primal_simplex::fill_A_x_and_basis_for_stage_one_total_inf_for_row(unsigned row) { - lean_assert(row < this->row_count()); + lp_assert(row < this->row_count()); auto ext_row_it = this->m_core_solver_rows_to_external_rows.find(row); - lean_assert(ext_row_it != this->m_core_solver_rows_to_external_rows.end()); + lp_assert(ext_row_it != this->m_core_solver_rows_to_external_rows.end()); unsigned ext_row = ext_row_it->second; auto constr_it = this->m_constraints.find(ext_row); - lean_assert(constr_it != this->m_constraints.end()); + lp_assert(constr_it != this->m_constraints.end()); auto & constraint = constr_it->second; unsigned j = this->m_A->column_count(); // j is a slack variable this->m_A->add_column(); @@ -209,14 +209,14 @@ template void lp_primal_simplex::fill_A_x_and_bas this->m_upper_bounds[j] = m_low_bounds[j] = zero_of_type(); break; default: - lean_unreachable(); + lp_unreachable(); } } template void lp_primal_simplex::solve_with_total_inf() { int total_vars = this->m_A->column_count() + this->row_count(); if (total_vars == 0) { - this->m_status = OPTIMAL; + this->m_status = lp_status::OPTIMAL; return; } m_low_bounds.clear(); @@ -281,10 +281,10 @@ template T lp_primal_simplex::get_row_value(unsig T ret = numeric_traits::zero(); for (auto & pair : it->second) { auto cit = this->m_map_from_var_index_to_column_info.find(pair.first); - lean_assert(cit != this->m_map_from_var_index_to_column_info.end()); + lp_assert(cit != this->m_map_from_var_index_to_column_info.end()); column_info * ci = cit->second; auto sol_it = solution.find(ci->get_name()); - lean_assert(sol_it != solution.end()); + lp_assert(sol_it != solution.end()); T column_val = sol_it->second; if (out != nullptr) { (*out) << pair.second << "(" << ci->get_name() << "=" << column_val << ") "; @@ -329,7 +329,7 @@ template bool lp_primal_simplex::row_constraint_h } return true;; } - lean_unreachable(); + lp_unreachable(); return false; // it is unreachable } diff --git a/src/util/lp/lp_primal_simplex_instances.cpp b/src/util/lp/lp_primal_simplex_instances.cpp index 37b639489..249be218c 100644 --- a/src/util/lp/lp_primal_simplex_instances.cpp +++ b/src/util/lp/lp_primal_simplex_instances.cpp @@ -8,13 +8,13 @@ #include "util/vector.h" #include #include "util/lp/lp_primal_simplex.hpp" -template bool lean::lp_primal_simplex::bounds_hold(std::unordered_map, std::equal_to, std::allocator > > const&); -template bool lean::lp_primal_simplex::row_constraints_hold(std::unordered_map, std::equal_to, std::allocator > > const&); -template double lean::lp_primal_simplex::get_current_cost() const; -template double lean::lp_primal_simplex::get_column_value(unsigned int) const; -template lean::lp_primal_simplex::~lp_primal_simplex(); -template lean::lp_primal_simplex::~lp_primal_simplex(); -template lean::mpq lean::lp_primal_simplex::get_current_cost() const; -template lean::mpq lean::lp_primal_simplex::get_column_value(unsigned int) const; -template void lean::lp_primal_simplex::find_maximal_solution(); -template void lean::lp_primal_simplex::find_maximal_solution(); +template bool lp::lp_primal_simplex::bounds_hold(std::unordered_map, std::equal_to, std::allocator > > const&); +template bool lp::lp_primal_simplex::row_constraints_hold(std::unordered_map, std::equal_to, std::allocator > > const&); +template double lp::lp_primal_simplex::get_current_cost() const; +template double lp::lp_primal_simplex::get_column_value(unsigned int) const; +template lp::lp_primal_simplex::~lp_primal_simplex(); +template lp::lp_primal_simplex::~lp_primal_simplex(); +template lp::mpq lp::lp_primal_simplex::get_current_cost() const; +template lp::mpq lp::lp_primal_simplex::get_column_value(unsigned int) const; +template void lp::lp_primal_simplex::find_maximal_solution(); +template void lp::lp_primal_simplex::find_maximal_solution(); diff --git a/src/util/lp/lp_settings.h b/src/util/lp/lp_settings.h index 37c2b1f57..895d6e678 100644 --- a/src/util/lp/lp_settings.h +++ b/src/util/lp/lp_settings.h @@ -12,28 +12,21 @@ #include "util/lp/lp_utils.h" #include "util/stopwatch.h" -namespace lean { +namespace lp { typedef unsigned var_index; typedef unsigned constraint_index; typedef unsigned row_index; -enum class final_check_status { - DONE, - CONTINUE, - UNSAT, - GIVEUP -}; typedef vector> explanation_t; - enum class column_type { free_column = 0, - low_bound = 1, - upper_bound = 2, - boxed = 3, - fixed = 4 - }; + low_bound = 1, + upper_bound = 2, + boxed = 3, + fixed = 4 +}; enum class simplex_strategy_enum { undecided = 3, @@ -44,7 +37,7 @@ enum class simplex_strategy_enum { std::string column_type_to_string(column_type t); -enum lp_status { +enum class lp_status { UNKNOWN, INFEASIBLE, TENTATIVE_UNBOUNDED, @@ -86,11 +79,14 @@ public: }; struct stats { + unsigned m_make_feasible; unsigned m_total_iterations; unsigned m_iters_with_no_cost_growing; unsigned m_num_factorizations; unsigned m_num_of_implied_bounds; unsigned m_need_to_solve_inf; + unsigned m_max_cols; + unsigned m_max_rows; stats() { reset(); } void reset() { memset(this, 0, sizeof(*this)); } }; @@ -209,7 +205,8 @@ public: use_breakpoints_in_feasibility_search(false), max_row_length_for_bound_propagation(300), backup_costs(true), - column_number_threshold_for_using_lu_in_lar_solver(4000) + column_number_threshold_for_using_lu_in_lar_solver(4000), + m_int_branch_cut_threshold(100) {} void set_resource_limit(lp_resource_limit& lim) { m_resource_limit = &lim; } @@ -289,13 +286,13 @@ public: return m_simplex_strategy; } - bool use_lu() const { - return m_simplex_strategy == simplex_strategy_enum::lu; - } + bool use_lu() const { + return m_simplex_strategy == simplex_strategy_enum::lu; + } bool use_tableau() const { - return m_simplex_strategy == simplex_strategy_enum::tableau_rows || - m_simplex_strategy == simplex_strategy_enum::tableau_costs; + return m_simplex_strategy == simplex_strategy_enum::tableau_rows || + m_simplex_strategy == simplex_strategy_enum::tableau_costs; } bool use_tableau_rows() const { @@ -316,6 +313,7 @@ public: unsigned max_row_length_for_bound_propagation; bool backup_costs; unsigned column_number_threshold_for_using_lu_in_lar_solver; + unsigned m_int_branch_cut_threshold; }; // end of lp_settings class @@ -377,7 +375,7 @@ inline void print_blanks(int n, std::ostream & out) { // after a push of the last element we ensure that the vector increases // we also suppose that before the last push the vector was increasing inline void ensure_increasing(vector & v) { - lean_assert(v.size() > 0); + lp_assert(v.size() > 0); unsigned j = v.size() - 1; for (; j > 0; j-- ) if (v[j] <= v[j - 1]) { diff --git a/src/util/lp/lp_settings.hpp b/src/util/lp/lp_settings.hpp index b27d837e0..fd5d8d8ea 100644 --- a/src/util/lp/lp_settings.hpp +++ b/src/util/lp/lp_settings.hpp @@ -6,7 +6,7 @@ #include #include "util/vector.h" #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { std::string column_type_to_string(column_type t) { switch (t) { case column_type::fixed: return "fixed"; @@ -14,27 +14,27 @@ std::string column_type_to_string(column_type t) { case column_type::low_bound: return "low_bound"; case column_type::upper_bound: return "upper_bound"; case column_type::free_column: return "free_column"; - default: lean_unreachable(); + default: lp_unreachable(); } return "unknown"; // it is unreachable } const char* lp_status_to_string(lp_status status) { switch (status) { - case UNKNOWN: return "UNKNOWN"; - case INFEASIBLE: return "INFEASIBLE"; - case UNBOUNDED: return "UNBOUNDED"; - case TENTATIVE_DUAL_UNBOUNDED: return "TENTATIVE_DUAL_UNBOUNDED"; - case DUAL_UNBOUNDED: return "DUAL_UNBOUNDED"; - case OPTIMAL: return "OPTIMAL"; - case FEASIBLE: return "FEASIBLE"; - case FLOATING_POINT_ERROR: return "FLOATING_POINT_ERROR"; - case TIME_EXHAUSTED: return "TIME_EXHAUSTED"; - case ITERATIONS_EXHAUSTED: return "ITERATIONS_EXHAUSTED"; - case EMPTY: return "EMPTY"; - case UNSTABLE: return "UNSTABLE"; + case lp_status::UNKNOWN: return "UNKNOWN"; + case lp_status::INFEASIBLE: return "INFEASIBLE"; + case lp_status::UNBOUNDED: return "UNBOUNDED"; + case lp_status::TENTATIVE_DUAL_UNBOUNDED: return "TENTATIVE_DUAL_UNBOUNDED"; + case lp_status::DUAL_UNBOUNDED: return "DUAL_UNBOUNDED"; + case lp_status::OPTIMAL: return "OPTIMAL"; + case lp_status::FEASIBLE: return "FEASIBLE"; + case lp_status::FLOATING_POINT_ERROR: return "FLOATING_POINT_ERROR"; + case lp_status::TIME_EXHAUSTED: return "TIME_EXHAUSTED"; + case lp_status::ITERATIONS_EXHAUSTED: return "ITERATIONS_EXHAUSTED"; + case lp_status::EMPTY: return "EMPTY"; + case lp_status::UNSTABLE: return "UNSTABLE"; default: - lean_unreachable(); + lp_unreachable(); } return "UNKNOWN"; // it is unreachable } @@ -49,7 +49,7 @@ lp_status lp_status_from_string(std::string status) { if (status == "TIME_EXHAUSTED") return lp_status::TIME_EXHAUSTED; if (status == "ITERATIONS_EXHAUSTED") return lp_status::ITERATIONS_EXHAUSTED; if (status == "EMPTY") return lp_status::EMPTY; - lean_unreachable(); + lp_unreachable(); return lp_status::UNKNOWN; // it is unreachable } diff --git a/src/util/lp/lp_settings_instances.cpp b/src/util/lp/lp_settings_instances.cpp index e9a3888ba..9e809e7c6 100644 --- a/src/util/lp/lp_settings_instances.cpp +++ b/src/util/lp/lp_settings_instances.cpp @@ -2,9 +2,9 @@ Copyright (c) 2017 Microsoft Corporation Author: Lev Nachmanson */ -#include "util/vector.h" #include +#include "util/vector.h" #include "util/lp/lp_settings.hpp" -template bool lean::vectors_are_equal(vector const&, vector const&); -template bool lean::vectors_are_equal(vector const&, vector const&); +template bool lp::vectors_are_equal(vector const&, vector const&); +template bool lp::vectors_are_equal(vector const&, vector const&); diff --git a/src/util/lp/lp_solver.h b/src/util/lp/lp_solver.h index 1bfe7dcdc..6c878c687 100644 --- a/src/util/lp/lp_solver.h +++ b/src/util/lp/lp_solver.h @@ -15,7 +15,7 @@ #include "util/lp/scaler.h" #include "util/lp/linear_combination_iterator.h" #include "util/lp/bound_analyzer_on_row.h" -namespace lean { +namespace lp { enum lp_relation { Less_or_equal, Equal, diff --git a/src/util/lp/lp_solver.hpp b/src/util/lp/lp_solver.hpp index 135616a69..3c7f35587 100644 --- a/src/util/lp/lp_solver.hpp +++ b/src/util/lp/lp_solver.hpp @@ -6,7 +6,7 @@ #include #include "util/vector.h" #include "util/lp/lp_solver.h" -namespace lean { +namespace lp { template column_info * lp_solver::get_or_create_column_info(unsigned column) { auto it = m_map_from_var_index_to_column_info.find(column); return (it == m_map_from_var_index_to_column_info.end())? (m_map_from_var_index_to_column_info[column] = new column_info(static_cast(-1))) : it->second; @@ -32,7 +32,7 @@ template T lp_solver::get_column_cost_value(unsig return ci->get_cost() * get_column_value(j); } template void lp_solver::add_constraint(lp_relation relation, T right_side, unsigned row_index) { - lean_assert(m_constraints.find(row_index) == m_constraints.end()); + lp_assert(m_constraints.find(row_index) == m_constraints.end()); lp_constraint cs(right_side, relation); m_constraints[row_index] = cs; } @@ -158,10 +158,10 @@ template void lp_solver::pin_vars_on_row_with_sig column_info * ci = m_map_from_var_index_to_column_info[j]; T a = t.second; if (a * sign > numeric_traits::zero()) { - lean_assert(ci->upper_bound_is_set()); + lp_assert(ci->upper_bound_is_set()); ci->set_fixed_value(ci->get_upper_bound()); } else { - lean_assert(ci->low_bound_is_set()); + lp_assert(ci->low_bound_is_set()); ci->set_fixed_value(ci->get_low_bound()); } } @@ -223,7 +223,7 @@ template bool lp_solver::row_e_is_obsolete(std T rs = m_constraints[row_index].m_rs; if (row_is_zero(row)) { if (!is_zero(rs)) - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } @@ -233,7 +233,7 @@ template bool lp_solver::row_e_is_obsolete(std T diff = low_bound - rs; if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)){ // low_bound > rs + m_settings.refactor_epsilon - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } if (val_is_smaller_than_eps(-diff, m_settings.refactor_tolerance)){ @@ -248,7 +248,7 @@ template bool lp_solver::row_e_is_obsolete(std T diff = rs - upper_bound; if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)) { // upper_bound < rs - m_settings.refactor_tolerance - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } if (val_is_smaller_than_eps(-diff, m_settings.refactor_tolerance)){ @@ -264,7 +264,7 @@ template bool lp_solver::row_ge_is_obsolete(std: T rs = m_constraints[row_index].m_rs; if (row_is_zero(row)) { if (rs > zero_of_type()) - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } @@ -273,7 +273,7 @@ template bool lp_solver::row_ge_is_obsolete(std: T diff = rs - upper_bound; if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)) { // upper_bound < rs - m_settings.refactor_tolerance - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } if (val_is_smaller_than_eps(-diff, m_settings.refactor_tolerance)){ @@ -290,7 +290,7 @@ template bool lp_solver::row_le_is_obsolete(std:: T rs = m_constraints[row_index].m_rs; if (row_is_zero(row)) { if (rs < zero_of_type()) - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } @@ -328,7 +328,7 @@ template bool lp_solver::row_is_obsolete(std:: case lp_relation::Less_or_equal: return row_le_is_obsolete(row, row_index); } - lean_unreachable(); + lp_unreachable(); return false; // it is unreachable } @@ -343,7 +343,7 @@ template void lp_solver::remove_fixed_or_zero_col vector removed; for (auto & col : row) { unsigned j = col.first; - lean_assert(m_map_from_var_index_to_column_info.find(j) != m_map_from_var_index_to_column_info.end()); + lp_assert(m_map_from_var_index_to_column_info.find(j) != m_map_from_var_index_to_column_info.end()); column_info * ci = m_map_from_var_index_to_column_info[j]; if (ci->is_fixed()) { removed.push_back(j); @@ -412,7 +412,7 @@ template void lp_solver::map_external_columns_to_ } unsigned j = col.first; auto column_info_it = m_map_from_var_index_to_column_info.find(j); - lean_assert(column_info_it != m_map_from_var_index_to_column_info.end()); + lp_assert(column_info_it != m_map_from_var_index_to_column_info.end()); auto j_column = column_info_it->second->get_column_index(); if (!is_valid(j_column)) { // j is a newcomer @@ -435,14 +435,14 @@ template void lp_solver::fill_A_from_A_values() { m_A = new static_matrix(static_cast(m_A_values.size()), number_of_core_structurals()); for (auto & t : m_A_values) { auto row_it = m_external_rows_to_core_solver_rows.find(t.first); - lean_assert(row_it != m_external_rows_to_core_solver_rows.end()); + lp_assert(row_it != m_external_rows_to_core_solver_rows.end()); unsigned row = row_it->second; for (auto k : t.second) { auto column_info_it = m_map_from_var_index_to_column_info.find(k.first); - lean_assert(column_info_it != m_map_from_var_index_to_column_info.end()); + lp_assert(column_info_it != m_map_from_var_index_to_column_info.end()); column_info *ci = column_info_it->second; unsigned col = ci->get_column_index(); - lean_assert(is_valid(col)); + lp_assert(is_valid(col)); bool col_is_flipped = m_map_from_var_index_to_column_info[k.first]->is_flipped(); if (!col_is_flipped) { (*m_A)(row, col) = k.second; @@ -456,7 +456,7 @@ template void lp_solver::fill_A_from_A_values() { template void lp_solver::fill_matrix_A_and_init_right_side() { map_external_rows_to_core_solver_rows(); map_external_columns_to_core_solver_columns(); - lean_assert(m_A == nullptr); + lp_assert(m_A == nullptr); fill_A_from_A_values(); m_b.resize(m_A->row_count()); } @@ -468,7 +468,7 @@ template void lp_solver::count_slacks_and_artific } template void lp_solver::count_slacks_and_artificials_for_row(unsigned i) { - lean_assert(this->m_constraints.find(this->m_core_solver_rows_to_external_rows[i]) != this->m_constraints.end()); + lp_assert(this->m_constraints.find(this->m_core_solver_rows_to_external_rows[i]) != this->m_constraints.end()); auto & constraint = this->m_constraints[this->m_core_solver_rows_to_external_rows[i]]; switch (constraint.m_relation) { case Equal: @@ -504,7 +504,7 @@ template T lp_solver::low_bound_shift_for_row( template void lp_solver::fill_m_b() { for (int i = this->row_count() - 1; i >= 0; i--) { - lean_assert(this->m_constraints.find(this->m_core_solver_rows_to_external_rows[i]) != this->m_constraints.end()); + lp_assert(this->m_constraints.find(this->m_core_solver_rows_to_external_rows[i]) != this->m_constraints.end()); unsigned external_i = this->m_core_solver_rows_to_external_rows[i]; auto & constraint = this->m_constraints[external_i]; this->m_b[i] = constraint.m_rs - low_bound_shift_for_row(external_i); @@ -542,13 +542,13 @@ template T lp_solver::get_column_value_with_core_ template void lp_solver::set_scaled_cost(unsigned j) { // grab original costs but modify it with the column scales - lean_assert(j < this->m_column_scale.size()); + lp_assert(j < this->m_column_scale.size()); column_info * ci = this->m_map_from_var_index_to_column_info[this->m_core_solver_columns_to_external_columns[j]]; T cost = ci->get_cost(); if (ci->is_flipped()){ cost *= -1; } - lean_assert(ci->is_fixed() == false); + lp_assert(ci->is_fixed() == false); this->m_costs[j] = cost * this->m_column_scale[j]; } } diff --git a/src/util/lp/lp_solver_instances.cpp b/src/util/lp/lp_solver_instances.cpp index 5df490cae..dce86914c 100644 --- a/src/util/lp/lp_solver_instances.cpp +++ b/src/util/lp/lp_solver_instances.cpp @@ -4,37 +4,37 @@ */ #include #include "util/lp/lp_solver.hpp" -template void lean::lp_solver::add_constraint(lean::lp_relation, double, unsigned int); -template void lean::lp_solver::cleanup(); -template void lean::lp_solver::count_slacks_and_artificials(); -template void lean::lp_solver::fill_m_b(); -template void lean::lp_solver::fill_matrix_A_and_init_right_side(); -template void lean::lp_solver::flip_costs(); -template double lean::lp_solver::get_column_cost_value(unsigned int, lean::column_info*) const; -template int lean::lp_solver::get_column_index_by_name(std::string) const; -template double lean::lp_solver::get_column_value_with_core_solver(unsigned int, lean::lp_core_solver_base*) const; -template lean::column_info* lean::lp_solver::get_or_create_column_info(unsigned int); -template void lean::lp_solver::give_symbolic_name_to_column(std::string, unsigned int); -template void lean::lp_solver::print_statistics_on_A(std::ostream & out); -template bool lean::lp_solver::problem_is_empty(); -template void lean::lp_solver::scale(); -template void lean::lp_solver::set_scaled_cost(unsigned int); -template lean::lp_solver::~lp_solver(); -template void lean::lp_solver::add_constraint(lean::lp_relation, lean::mpq, unsigned int); -template void lean::lp_solver::cleanup(); -template void lean::lp_solver::count_slacks_and_artificials(); -template void lean::lp_solver::fill_m_b(); -template void lean::lp_solver::fill_matrix_A_and_init_right_side(); -template void lean::lp_solver::flip_costs(); -template lean::mpq lean::lp_solver::get_column_cost_value(unsigned int, lean::column_info*) const; -template int lean::lp_solver::get_column_index_by_name(std::string) const; -template lean::mpq lean::lp_solver::get_column_value_by_name(std::string) const; -template lean::mpq lean::lp_solver::get_column_value_with_core_solver(unsigned int, lean::lp_core_solver_base*) const; -template lean::column_info* lean::lp_solver::get_or_create_column_info(unsigned int); -template void lean::lp_solver::give_symbolic_name_to_column(std::string, unsigned int); -template void lean::lp_solver::print_statistics_on_A(std::ostream & out); -template bool lean::lp_solver::problem_is_empty(); -template void lean::lp_solver::scale(); -template void lean::lp_solver::set_scaled_cost(unsigned int); -template lean::lp_solver::~lp_solver(); -template double lean::lp_solver::get_column_value_by_name(std::string) const; +template void lp::lp_solver::add_constraint(lp::lp_relation, double, unsigned int); +template void lp::lp_solver::cleanup(); +template void lp::lp_solver::count_slacks_and_artificials(); +template void lp::lp_solver::fill_m_b(); +template void lp::lp_solver::fill_matrix_A_and_init_right_side(); +template void lp::lp_solver::flip_costs(); +template double lp::lp_solver::get_column_cost_value(unsigned int, lp::column_info*) const; +template int lp::lp_solver::get_column_index_by_name(std::string) const; +template double lp::lp_solver::get_column_value_with_core_solver(unsigned int, lp::lp_core_solver_base*) const; +template lp::column_info* lp::lp_solver::get_or_create_column_info(unsigned int); +template void lp::lp_solver::give_symbolic_name_to_column(std::string, unsigned int); +template void lp::lp_solver::print_statistics_on_A(std::ostream & out); +template bool lp::lp_solver::problem_is_empty(); +template void lp::lp_solver::scale(); +template void lp::lp_solver::set_scaled_cost(unsigned int); +template lp::lp_solver::~lp_solver(); +template void lp::lp_solver::add_constraint(lp::lp_relation, lp::mpq, unsigned int); +template void lp::lp_solver::cleanup(); +template void lp::lp_solver::count_slacks_and_artificials(); +template void lp::lp_solver::fill_m_b(); +template void lp::lp_solver::fill_matrix_A_and_init_right_side(); +template void lp::lp_solver::flip_costs(); +template lp::mpq lp::lp_solver::get_column_cost_value(unsigned int, lp::column_info*) const; +template int lp::lp_solver::get_column_index_by_name(std::string) const; +template lp::mpq lp::lp_solver::get_column_value_by_name(std::string) const; +template lp::mpq lp::lp_solver::get_column_value_with_core_solver(unsigned int, lp::lp_core_solver_base*) const; +template lp::column_info* lp::lp_solver::get_or_create_column_info(unsigned int); +template void lp::lp_solver::give_symbolic_name_to_column(std::string, unsigned int); +template void lp::lp_solver::print_statistics_on_A(std::ostream & out); +template bool lp::lp_solver::problem_is_empty(); +template void lp::lp_solver::scale(); +template void lp::lp_solver::set_scaled_cost(unsigned int); +template lp::lp_solver::~lp_solver(); +template double lp::lp_solver::get_column_value_by_name(std::string) const; diff --git a/src/util/lp/lp_utils.cpp b/src/util/lp/lp_utils.cpp index 8cb98974e..7d5f46f2d 100644 --- a/src/util/lp/lp_utils.cpp +++ b/src/util/lp/lp_utils.cpp @@ -4,7 +4,7 @@ */ #include "util/lp/lp_utils.h" #ifdef lp_for_z3 -namespace lean { +namespace lp { double numeric_traits::g_zero = 0.0; double numeric_traits::g_one = 1.0; } diff --git a/src/util/lp/lp_utils.h b/src/util/lp/lp_utils.h index 2be15d79a..e1d5c5b8a 100644 --- a/src/util/lp/lp_utils.h +++ b/src/util/lp/lp_utils.h @@ -27,14 +27,14 @@ bool contains(const std::unordered_map & map, const A& key) { #define LEAN_DEBUG 1 #endif -namespace lean { +namespace lp { inline void throw_exception(const std::string & str) { throw default_exception(str); } typedef z3_exception exception; -#define lean_assert(_x_) { SASSERT(_x_); } - inline void lean_unreachable() { lean_assert(false); } +#define lp_assert(_x_) { SASSERT(_x_); } + inline void lp_unreachable() { lp_assert(false); } template inline X zero_of_type() { return numeric_traits::zero(); } template inline X one_of_type() { return numeric_traits::one(); } template inline bool is_zero(const X & v) { return numeric_traits::is_zero(v); } @@ -68,8 +68,8 @@ template struct hash> { }; template<> -struct hash> { - inline size_t operator()(const lean::numeric_pair & v) const { +struct hash> { + inline size_t operator()(const lp::numeric_pair & v) const { size_t seed = 0; hash_combine(seed, v.x); hash_combine(seed, v.y); @@ -91,26 +91,26 @@ struct hash> { #endif namespace std { template<> -struct hash { - inline size_t operator()(const lean::mpq & v) const { +struct hash { + inline size_t operator()(const lp::mpq & v) const { return v.hash(); } }; } -namespace lean { +namespace lp { template inline bool precise() { return numeric_traits::precise();} template inline X one_of_type() { return numeric_traits::one(); } template inline bool is_zero(const X & v) { return numeric_traits::is_zero(v); } template inline double get_double(const X & v) { return numeric_traits::get_double(v); } template inline T zero_of_type() {return numeric_traits::zero();} inline void throw_exception(std::string str) { throw exception(str); } -template inline T from_string(std::string const & ) { lean_unreachable();} +template inline T from_string(std::string const & ) { lp_unreachable();} template <> double inline from_string(std::string const & str) { return atof(str.c_str());} template <> mpq inline from_string(std::string const & str) { return mpq(atof(str.c_str())); } -} // closing lean +} // closing lp template inline void hash_combine(std::size_t & seed, const T & v) { seed ^= std::hash()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); @@ -126,8 +126,8 @@ template struct hash> { } }; template<> -struct hash> { - inline size_t operator()(const lean::numeric_pair & v) const { +struct hash> { + inline size_t operator()(const lp::numeric_pair & v) const { size_t seed = 0; hash_combine(seed, v.x); hash_combine(seed, v.y); diff --git a/src/util/lp/lu.h b/src/util/lp/lu.h index 0d8163a14..ff95fe258 100644 --- a/src/util/lp/lu.h +++ b/src/util/lp/lu.h @@ -18,7 +18,7 @@ #include "util/lp/row_eta_matrix.h" #include "util/lp/square_dense_submatrix.h" #include "util/lp/dense_matrix.h" -namespace lean { +namespace lp { #ifdef LEAN_DEBUG template // print the nr x nc submatrix at the top left corner void print_submatrix(sparse_matrix & m, unsigned mr, unsigned nc); @@ -32,7 +32,7 @@ void print_matrix(sparse_matrix& m, std::ostream & out); template X dot_product(const vector & a, const vector & b) { - lean_assert(a.size() == b.size()); + lp_assert(a.size() == b.size()); auto r = zero_of_type(); for (unsigned i = 0; i < a.size(); i++) { r += a[i] * b[i]; @@ -99,7 +99,7 @@ public: m_i = p.apply_reverse(m_i); #ifdef LEAN_DEBUG - // lean_assert(*this == deb); + // lp_assert(*this == deb); #endif } }; // end of one_elem_on_diag @@ -291,7 +291,7 @@ public: bool need_to_refactor() { return m_refactor_counter >= 200; } void adjust_dimension_with_matrix_A() { - lean_assert(m_A.row_count() >= m_dim); + lp_assert(m_A.row_count() >= m_dim); m_dim = m_A.row_count(); m_U.resize(m_dim); m_Q.resize(m_dim); @@ -305,7 +305,7 @@ public: unsigned m = m_A.row_count(); unsigned m_prev = m_U.dimension(); - lean_assert(m_A.column_count() == heading.size()); + lp_assert(m_A.column_count() == heading.size()); for (unsigned i = m_prev; i < m; i++) { for (const row_cell & c : m_A.m_rows[i]) { @@ -321,14 +321,14 @@ public: void add_last_rows_to_B(const vector & heading, const std::unordered_set & columns_to_replace) { unsigned m = m_A.row_count(); - lean_assert(m_A.column_count() == heading.size()); + lp_assert(m_A.column_count() == heading.size()); adjust_dimension_with_matrix_A(); m_w_for_extension.resize(m); // At this moment the LU is correct // for B extended by only by ones at the diagonal in the lower right corner for (unsigned j :columns_to_replace) { - lean_assert(heading[j] >= 0); + lp_assert(heading[j] >= 0); replace_column_with_only_change_at_last_rows(j, heading[j]); if (get_status() == LU_status::Degenerated) break; diff --git a/src/util/lp/lu.hpp b/src/util/lp/lu.hpp index 2d2c7c7c4..64ac8efe2 100644 --- a/src/util/lp/lu.hpp +++ b/src/util/lp/lu.hpp @@ -9,7 +9,7 @@ #include #include "util/debug.h" #include "util/lp/lu.h" -namespace lean { +namespace lp { #ifdef LEAN_DEBUG template // print the nr x nc submatrix at the top left corner void print_submatrix(sparse_matrix & m, unsigned mr, unsigned nc, std::ostream & out) { @@ -122,29 +122,29 @@ lu::lu(static_matrix const & A, m_failure(false), m_row_eta_work_vector(A.row_count()), m_refactor_counter(0) { - lean_assert(!(numeric_traits::precise() && settings.use_tableau())); + lp_assert(!(numeric_traits::precise() && settings.use_tableau())); #ifdef LEAN_DEBUG debug_test_of_basis(A, basis); #endif ++m_settings.st().m_num_factorizations; create_initial_factorization(); #ifdef LEAN_DEBUG - // lean_assert(check_correctness()); + // lp_assert(check_correctness()); #endif } template void lu::debug_test_of_basis(static_matrix const & A, vector & basis) { std::set set; for (unsigned i = 0; i < A.row_count(); i++) { - lean_assert(basis[i]< A.column_count()); + lp_assert(basis[i]< A.column_count()); set.insert(basis[i]); } - lean_assert(set.size() == A.row_count()); + lp_assert(set.size() == A.row_count()); } template void lu::solve_By(indexed_vector & y) { - lean_assert(false); // not implemented + lp_assert(false); // not implemented // init_vector_y(y); // solve_By_when_y_is_ready(y); } @@ -277,20 +277,20 @@ void lu::solve_yB(vector& y) { template void lu::solve_yB_indexed(indexed_vector& y) { - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); // first solve yU = cb*R(-1) m_R.apply_reverse_from_right_to_T(y); // got y = cb*R(-1) - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); m_U.solve_y_U_indexed(y, m_settings); // got y*U=cb*R(-1) - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); m_Q.apply_reverse_from_right_to_T(y); - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); for (auto e = m_tail.rbegin(); e != m_tail.rend(); ++e) { #ifdef LEAN_DEBUG (*e)->set_number_of_columns(m_dim); #endif (*e)->apply_from_right(y); - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); } } @@ -304,8 +304,8 @@ void lu::add_delta_to_solution(const vector& yc, vector& y){ template void lu::add_delta_to_solution_indexed(indexed_vector& y) { // the delta sits in m_y_copy, put result into y - lean_assert(y.is_OK()); - lean_assert(m_y_copy.is_OK()); + lp_assert(y.is_OK()); + lp_assert(m_y_copy.is_OK()); m_ii.clear(); m_ii.resize(y.data_size()); for (unsigned i : y.m_index) @@ -315,7 +315,7 @@ void lu::add_delta_to_solution_indexed(indexed_vector& y) { if (m_ii[i] == 0) m_ii.set_value(1, i); } - lean_assert(m_ii.is_OK()); + lp_assert(m_ii.is_OK()); y.m_index.clear(); for (unsigned i : m_ii.m_index) { @@ -326,7 +326,7 @@ void lu::add_delta_to_solution_indexed(indexed_vector& y) { v = zero_of_type(); } - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); } template @@ -343,7 +343,7 @@ void lu::find_error_of_yB_indexed(const indexed_vector& y, const vector // it is a non efficient version indexed_vector yc = m_y_copy; yc.m_index.clear(); - lean_assert(!numeric_traits::precise()); + lp_assert(!numeric_traits::precise()); { vector d_basis(y.m_data.size()); @@ -364,10 +364,10 @@ void lu::find_error_of_yB_indexed(const indexed_vector& y, const vector } } #endif - lean_assert(m_ii.is_OK()); + lp_assert(m_ii.is_OK()); m_ii.clear(); m_ii.resize(y.data_size()); - lean_assert(m_y_copy.is_OK()); + lp_assert(m_y_copy.is_OK()); // put the error into m_y_copy for (auto k : y.m_index) { auto & row = m_A.m_rows[k]; @@ -399,7 +399,7 @@ void lu::find_error_of_yB_indexed(const indexed_vector& y, const vector m_y_copy.set_value(v, k); } } - lean_assert(m_y_copy.is_OK()); + lp_assert(m_y_copy.is_OK()); } @@ -419,12 +419,12 @@ void lu::solve_yB_with_error_check_indexed(indexed_vector & y, const ve } return; } - lean_assert(m_y_copy.is_OK()); - lean_assert(y.is_OK()); + lp_assert(m_y_copy.is_OK()); + lp_assert(y.is_OK()); if (y.m_index.size() * ratio_of_index_size_to_all_size() < m_A.column_count()) { m_y_copy = y; solve_yB_indexed(y); - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); if (y.m_index.size() * ratio_of_index_size_to_all_size() >= m_A.column_count()) { find_error_of_yB(m_y_copy.m_data, y.m_data, basis); solve_yB(m_y_copy.m_data); @@ -436,7 +436,7 @@ void lu::solve_yB_with_error_check_indexed(indexed_vector & y, const ve solve_yB_indexed(m_y_copy); add_delta_to_solution_indexed(y); } - lean_assert(m_y_copy.is_OK()); + lp_assert(m_y_copy.is_OK()); } else { solve_yB_with_error_check(y.m_data, basis); y.restore_index_and_clean_from_data(); @@ -489,7 +489,7 @@ template void lu::perform_transformations_on_w(indexed_vector& w) { apply_lp_list_to_w(w); m_Q.apply_reverse_from_left(w); - // TBD does not compile: lean_assert(numeric_traits::precise() || check_vector_for_small_values(w, m_settings)); + // TBD does not compile: lp_assert(numeric_traits::precise() || check_vector_for_small_values(w, m_settings)); } // see Chvatal 24.3 @@ -503,7 +503,7 @@ template void lu::apply_lp_list_to_w(indexed_vector & w) { for (unsigned i = 0; i < m_tail.size(); i++) { m_tail[i]->apply_from_left_to_T(w, m_settings); - // TBD does not compile: lean_assert(check_vector_for_small_values(w, m_settings)); + // TBD does not compile: lp_assert(check_vector_for_small_values(w, m_settings)); } } template @@ -595,7 +595,7 @@ void lu::check_apply_lp_lists_to_w(T * w) { permutation_matrix qr = m_Q.get_reverse(); apply_to_vector(qr, w); for (int i = m_dim - 1; i >= 0; i--) { - lean_assert(abs(w[i] - w[i]) < 0.0000001); + lp_assert(abs(w[i] - w[i]) < 0.0000001); } } @@ -640,7 +640,7 @@ bool lu::is_correct(const vector& basis) { #ifdef LEAN_DEBUG template dense_matrix lu::tail_product() { - lean_assert(tail_size() > 0); + lp_assert(tail_size() > 0); dense_matrix left_side = permutation_matrix(m_dim); for (unsigned i = 0; i < tail_size(); i++) { matrix* lp = get_lp_matrix(i); @@ -690,8 +690,8 @@ template bool lu::all_columns_and_rows_are_active() { unsigned i = m_dim; while (i--) { - lean_assert(m_U.col_is_active(i)); - lean_assert(m_U.row_is_active(i)); + lp_assert(m_U.col_is_active(i)); + lp_assert(m_U.row_is_active(i)); } return true; } @@ -733,9 +733,9 @@ void lu::create_initial_factorization(){ } } if (j == m_dim) { - // TBD does not compile: lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); - // lean_assert(is_correct()); - // lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); + // TBD does not compile: lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); + // lp_assert(is_correct()); + // lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); return; } j++; @@ -748,12 +748,12 @@ void lu::create_initial_factorization(){ } } m_dense_LU->update_parent_matrix(m_settings); - lean_assert(m_dense_LU->is_L_matrix()); + lp_assert(m_dense_LU->is_L_matrix()); m_dense_LU->conjugate_by_permutation(m_Q); push_matrix_to_tail(m_dense_LU); m_refactor_counter = 0; - // lean_assert(is_correct()); - // lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); + // lp_assert(is_correct()); + // lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); } template @@ -780,7 +780,7 @@ void lu::scan_last_row_to_work_vector(unsigned lowest_row_of_the_bump) { vector> & last_row_vec = m_U.get_row_values(m_U.adjust_row(lowest_row_of_the_bump)); for (auto & iv : last_row_vec) { if (is_zero(iv.m_value)) continue; - lean_assert(!m_settings.abs_val_is_smaller_than_drop_tolerance(iv.m_value)); + lp_assert(!m_settings.abs_val_is_smaller_than_drop_tolerance(iv.m_value)); unsigned adjusted_col = m_U.adjust_column_inverse(iv.m_index); if (adjusted_col < lowest_row_of_the_bump) { m_row_eta_work_vector.set_value(-iv.m_value, adjusted_col); @@ -801,14 +801,14 @@ void lu::pivot_and_solve_the_system(unsigned replaced_column, unsigned low vector> & row = m_U.get_row_values(aj); for (auto & iv : row) { unsigned col = m_U.adjust_column_inverse(iv.m_index); - lean_assert(col >= j || numeric_traits::is_zero(iv.m_value)); + lp_assert(col >= j || numeric_traits::is_zero(iv.m_value)); if (col == j) continue; if (numeric_traits::is_zero(iv.m_value)) { continue; } // the -v is for solving the system ( to zero the last row), and +v is for pivoting T delta = col < lowest_row_of_the_bump? -v * iv.m_value: v * iv.m_value; - lean_assert(numeric_traits::is_zero(delta) == false); + lp_assert(numeric_traits::is_zero(delta) == false); @@ -885,15 +885,15 @@ void lu::replace_column(T pivot_elem_for_checking, indexed_vector & w, push_matrix_to_tail(row_eta); } calculate_Lwave_Pwave_for_bump(replaced_column, lowest_row_of_the_bump); - // lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); - // lean_assert(w.is_OK() && m_row_eta_work_vector.is_OK()); + // lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); + // lp_assert(w.is_OK() && m_row_eta_work_vector.is_OK()); } template void lu::calculate_Lwave_Pwave_for_bump(unsigned replaced_column, unsigned lowest_row_of_the_bump){ T diagonal_elem; if (replaced_column < lowest_row_of_the_bump) { diagonal_elem = m_row_eta_work_vector[lowest_row_of_the_bump]; - // lean_assert(m_row_eta_work_vector.is_OK()); + // lp_assert(m_row_eta_work_vector.is_OK()); m_U.set_row_from_work_vector_and_clean_work_vector_not_adjusted(m_U.adjust_row(lowest_row_of_the_bump), m_row_eta_work_vector, m_settings); } else { diagonal_elem = m_U(lowest_row_of_the_bump, lowest_row_of_the_bump); // todo - get it more efficiently @@ -904,7 +904,7 @@ void lu::calculate_Lwave_Pwave_for_bump(unsigned replaced_column, unsigned } calculate_Lwave_Pwave_for_last_row(lowest_row_of_the_bump, diagonal_elem); - // lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); + // lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); } template @@ -930,8 +930,8 @@ void init_factorization(lu* & factorization, static_matrix & m_A, ve #ifdef LEAN_DEBUG template dense_matrix get_B(lu& f, const vector& basis) { - lean_assert(basis.size() == f.dimension()); - lean_assert(basis.size() == f.m_U.dimension()); + lp_assert(basis.size() == f.dimension()); + lp_assert(basis.size() == f.m_U.dimension()); dense_matrix B(f.dimension(), f.dimension()); for (unsigned i = 0; i < f.dimension(); i++) for (unsigned j = 0; j < f.dimension(); j++) diff --git a/src/util/lp/lu_instances.cpp b/src/util/lp/lu_instances.cpp index c8ff7b2f4..97fa3eed9 100644 --- a/src/util/lp/lu_instances.cpp +++ b/src/util/lp/lu_instances.cpp @@ -8,56 +8,56 @@ #include "util/vector.h" #include "util/debug.h" #include "util/lp/lu.hpp" -template double lean::dot_product(vector const&, vector const&); -template lean::lu::lu(lean::static_matrix const&, vector&, lean::lp_settings&); -template void lean::lu::push_matrix_to_tail(lean::tail_matrix*); -template void lean::lu::replace_column(double, lean::indexed_vector&, unsigned); -template void lean::lu::solve_Bd(unsigned int, lean::indexed_vector&, lean::indexed_vector&); -template lean::lu::~lu(); -template void lean::lu::push_matrix_to_tail(lean::tail_matrix*); -template void lean::lu::solve_Bd(unsigned int, lean::indexed_vector&, lean::indexed_vector&); -template lean::lu::~lu(); -template void lean::lu >::push_matrix_to_tail(lean::tail_matrix >*); -template void lean::lu >::solve_Bd(unsigned int, lean::indexed_vector&, lean::indexed_vector&); -template lean::lu >::~lu(); -template lean::mpq lean::dot_product(vector const&, vector const&); -template void lean::init_factorization(lean::lu*&, lean::static_matrix&, vector&, lean::lp_settings&); -template void lean::init_factorization(lean::lu*&, lean::static_matrix&, vector&, lean::lp_settings&); -template void lean::init_factorization >(lean::lu >*&, lean::static_matrix >&, vector&, lean::lp_settings&); +template double lp::dot_product(vector const&, vector const&); +template lp::lu::lu(lp::static_matrix const&, vector&, lp::lp_settings&); +template void lp::lu::push_matrix_to_tail(lp::tail_matrix*); +template void lp::lu::replace_column(double, lp::indexed_vector&, unsigned); +template void lp::lu::solve_Bd(unsigned int, lp::indexed_vector&, lp::indexed_vector&); +template lp::lu::~lu(); +template void lp::lu::push_matrix_to_tail(lp::tail_matrix*); +template void lp::lu::solve_Bd(unsigned int, lp::indexed_vector&, lp::indexed_vector&); +template lp::lu::~lu(); +template void lp::lu >::push_matrix_to_tail(lp::tail_matrix >*); +template void lp::lu >::solve_Bd(unsigned int, lp::indexed_vector&, lp::indexed_vector&); +template lp::lu >::~lu(); +template lp::mpq lp::dot_product(vector const&, vector const&); +template void lp::init_factorization(lp::lu*&, lp::static_matrix&, vector&, lp::lp_settings&); +template void lp::init_factorization(lp::lu*&, lp::static_matrix&, vector&, lp::lp_settings&); +template void lp::init_factorization >(lp::lu >*&, lp::static_matrix >&, vector&, lp::lp_settings&); #ifdef LEAN_DEBUG -template void lean::print_matrix(lean::sparse_matrix&, std::ostream & out); -template void lean::print_matrix(lean::static_matrix&, std::ostream&); -template void lean::print_matrix >(lean::static_matrix >&, std::ostream&); -template void lean::print_matrix(lean::static_matrix&, std::ostream & out); -template bool lean::lu::is_correct(const vector& basis); -template bool lean::lu >::is_correct( vector const &); -template lean::dense_matrix lean::get_B(lean::lu&, const vector& basis); -template lean::dense_matrix lean::get_B(lean::lu&, vector const&); +template void lp::print_matrix(lp::sparse_matrix&, std::ostream & out); +template void lp::print_matrix(lp::static_matrix&, std::ostream&); +template void lp::print_matrix >(lp::static_matrix >&, std::ostream&); +template void lp::print_matrix(lp::static_matrix&, std::ostream & out); +template bool lp::lu::is_correct(const vector& basis); +template bool lp::lu >::is_correct( vector const &); +template lp::dense_matrix lp::get_B(lp::lu&, const vector& basis); +template lp::dense_matrix lp::get_B(lp::lu&, vector const&); #endif -template bool lean::lu::pivot_the_row(int); // NOLINT -template void lean::lu::init_vector_w(unsigned int, lean::indexed_vector&); -template void lean::lu::solve_By(vector&); -template void lean::lu::solve_By_when_y_is_ready_for_X(vector&); -template void lean::lu::solve_yB_with_error_check(vector&, const vector& basis); -template void lean::lu::solve_yB_with_error_check_indexed(lean::indexed_vector&, vector const&, const vector & basis, const lp_settings&); -template void lean::lu::replace_column(lean::mpq, lean::indexed_vector&, unsigned); -template void lean::lu::solve_By(vector&); -template void lean::lu::solve_By_when_y_is_ready_for_X(vector&); -template void lean::lu::solve_yB_with_error_check(vector&, const vector& basis); -template void lean::lu::solve_yB_with_error_check_indexed(lean::indexed_vector&, vector< int > const&, const vector & basis, const lp_settings&); -template void lean::lu >::solve_yB_with_error_check_indexed(lean::indexed_vector&, vector< int > const&, const vector & basis, const lp_settings&); -template void lean::lu >::init_vector_w(unsigned int, lean::indexed_vector&); -template void lean::lu >::replace_column(lean::mpq, lean::indexed_vector&, unsigned); -template void lean::lu >::solve_Bd_faster(unsigned int, lean::indexed_vector&); -template void lean::lu >::solve_By(vector >&); -template void lean::lu >::solve_By_when_y_is_ready_for_X(vector >&); -template void lean::lu >::solve_yB_with_error_check(vector&, const vector& basis); -template void lean::lu::solve_By(lean::indexed_vector&); -template void lean::lu::solve_By(lean::indexed_vector&); -template void lean::lu::solve_yB_indexed(lean::indexed_vector&); -template void lean::lu::solve_yB_indexed(lean::indexed_vector&); -template void lean::lu >::solve_yB_indexed(lean::indexed_vector&); -template void lean::lu::solve_By_for_T_indexed_only(lean::indexed_vector&, lean::lp_settings const&); -template void lean::lu::solve_By_for_T_indexed_only(lean::indexed_vector&, lean::lp_settings const&); +template bool lp::lu::pivot_the_row(int); // NOLINT +template void lp::lu::init_vector_w(unsigned int, lp::indexed_vector&); +template void lp::lu::solve_By(vector&); +template void lp::lu::solve_By_when_y_is_ready_for_X(vector&); +template void lp::lu::solve_yB_with_error_check(vector&, const vector& basis); +template void lp::lu::solve_yB_with_error_check_indexed(lp::indexed_vector&, vector const&, const vector & basis, const lp_settings&); +template void lp::lu::replace_column(lp::mpq, lp::indexed_vector&, unsigned); +template void lp::lu::solve_By(vector&); +template void lp::lu::solve_By_when_y_is_ready_for_X(vector&); +template void lp::lu::solve_yB_with_error_check(vector&, const vector& basis); +template void lp::lu::solve_yB_with_error_check_indexed(lp::indexed_vector&, vector< int > const&, const vector & basis, const lp_settings&); +template void lp::lu >::solve_yB_with_error_check_indexed(lp::indexed_vector&, vector< int > const&, const vector & basis, const lp_settings&); +template void lp::lu >::init_vector_w(unsigned int, lp::indexed_vector&); +template void lp::lu >::replace_column(lp::mpq, lp::indexed_vector&, unsigned); +template void lp::lu >::solve_Bd_faster(unsigned int, lp::indexed_vector&); +template void lp::lu >::solve_By(vector >&); +template void lp::lu >::solve_By_when_y_is_ready_for_X(vector >&); +template void lp::lu >::solve_yB_with_error_check(vector&, const vector& basis); +template void lp::lu::solve_By(lp::indexed_vector&); +template void lp::lu::solve_By(lp::indexed_vector&); +template void lp::lu::solve_yB_indexed(lp::indexed_vector&); +template void lp::lu::solve_yB_indexed(lp::indexed_vector&); +template void lp::lu >::solve_yB_indexed(lp::indexed_vector&); +template void lp::lu::solve_By_for_T_indexed_only(lp::indexed_vector&, lp::lp_settings const&); +template void lp::lu::solve_By_for_T_indexed_only(lp::indexed_vector&, lp::lp_settings const&); diff --git a/src/util/lp/matrix.h b/src/util/lp/matrix.h index 63fd5c01e..fb177551e 100644 --- a/src/util/lp/matrix.h +++ b/src/util/lp/matrix.h @@ -8,7 +8,7 @@ #include "util/vector.h" #include #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { // used for debugging purposes only template class matrix { diff --git a/src/util/lp/matrix.hpp b/src/util/lp/matrix.hpp index d032cab8c..45e4c3da2 100644 --- a/src/util/lp/matrix.hpp +++ b/src/util/lp/matrix.hpp @@ -7,7 +7,7 @@ #include #include #include "util/lp/matrix.h" -namespace lean { +namespace lp { template bool matrix::is_equal(const matrix& other) { if (other.row_count() != row_count() || other.column_count() != column_count()) diff --git a/src/util/lp/matrix_instances.cpp b/src/util/lp/matrix_instances.cpp index aeee62786..ae37a2e69 100644 --- a/src/util/lp/matrix_instances.cpp +++ b/src/util/lp/matrix_instances.cpp @@ -7,10 +7,10 @@ #include "util/lp/matrix.hpp" #include "util/lp/static_matrix.h" #include -template void lean::print_matrix(lean::matrix const*, std::ostream & out); -template bool lean::matrix::is_equal(lean::matrix const&); -template void lean::print_matrix >(lean::matrix > const *, std::basic_ostream > &); -template void lean::print_matrix(lean::matrix const*, std::ostream&); -template bool lean::matrix >::is_equal(lean::matrix > const&); -template bool lean::matrix::is_equal(lean::matrix const&); +template void lp::print_matrix(lp::matrix const*, std::ostream & out); +template bool lp::matrix::is_equal(lp::matrix const&); +template void lp::print_matrix >(lp::matrix > const *, std::basic_ostream > &); +template void lp::print_matrix(lp::matrix const*, std::ostream&); +template bool lp::matrix >::is_equal(lp::matrix > const&); +template bool lp::matrix::is_equal(lp::matrix const&); #endif diff --git a/src/util/lp/mps_reader.h b/src/util/lp/mps_reader.h index eb83735ca..257cf63e2 100644 --- a/src/util/lp/mps_reader.h +++ b/src/util/lp/mps_reader.h @@ -19,7 +19,7 @@ #include "util/lp/lar_solver.h" #include "util/lp/lp_utils.h" #include "util/lp/lp_solver.h" -namespace lean { +namespace lp { inline bool my_white_space(const char & a) { return a == ' ' || a == '\t'; } @@ -160,9 +160,9 @@ class mps_reader { if (m_line[i] == ' ') break; } - lean_assert(m_line.size() >= offset); - lean_assert(m_line.size() >> i); - lean_assert(i >= offset); + lp_assert(m_line.size() >= offset); + lp_assert(m_line.size() >> i); + lp_assert(i >= offset); return m_line.substr(offset, i - offset); } @@ -497,7 +497,7 @@ class mps_reader { void create_or_update_bound() { const unsigned name_offset = 14; - lean_assert(m_line.size() >= 14); + lp_assert(m_line.size() >= 14); vector bound_string = split_and_trim(m_line.substr(name_offset, m_line.size())); if (bound_string.size() == 0) { @@ -603,7 +603,7 @@ class mps_reader { } for (auto s : row_with_range->m_row_columns) { - lean_assert(m_columns.find(s.first) != m_columns.end()); + lp_assert(m_columns.find(s.first) != m_columns.end()); other_bound_range_row->m_row_columns[s.first] = s.second; } } @@ -679,7 +679,7 @@ class mps_reader { if (row->m_name != m_cost_row_name) { solver->add_constraint(get_relation_from_row(row->m_type), row->m_right_side, row->m_index); for (auto s : row->m_row_columns) { - lean_assert(m_columns.find(s.first) != m_columns.end()); + lp_assert(m_columns.find(s.first) != m_columns.end()); solver->set_row_column_coefficient(row->m_index, m_columns[s.first]->m_index, s.second); } } else { @@ -714,7 +714,7 @@ class mps_reader { void set_solver_cost(row * row, lp_solver *solver) { for (auto s : row->m_row_columns) { std::string name = s.first; - lean_assert(m_columns.find(name) != m_columns.end()); + lp_assert(m_columns.find(name) != m_columns.end()); mps_reader::column * col = m_columns[name]; solver->set_cost_for_column(col->m_index, s.second); } @@ -723,7 +723,7 @@ class mps_reader { public: void set_message_stream(std::ostream * o) { - lean_assert(o != nullptr); + lp_assert(o != nullptr); m_message_stream = o; } vector column_names() { diff --git a/src/util/lp/nra_solver.cpp b/src/util/lp/nra_solver.cpp index 48d957aab..dd5d970bf 100644 --- a/src/util/lp/nra_solver.cpp +++ b/src/util/lp/nra_solver.cpp @@ -1,9 +1,8 @@ /* Copyright (c) 2017 Microsoft Corporation - Author: Lev Nachmanson + Author: Nikolaj Bjorner */ -#pragma once #include "util/lp/lar_solver.h" #include "util/lp/nra_solver.h" #include "nlsat/nlsat_solver.h" @@ -14,47 +13,45 @@ namespace nra { + struct mon_eq { + mon_eq(lp::var_index v, unsigned sz, lp::var_index const* vs): + m_v(v), m_vs(sz, vs) {} + lp::var_index m_v; + svector m_vs; + }; + struct solver::imp { - lean::lar_solver& s; - reslimit& m_limit; // TBD: extract from lar_solver - params_ref m_params; // TBD: pass from outside + lp::lar_solver& s; + reslimit& m_limit; + params_ref m_params; u_map m_lp2nl; // map from lar_solver variables to nlsat::solver variables - nlsat::solver m_nlsat; + scoped_ptr m_nlsat; + vector m_monomials; + unsigned_vector m_monomials_lim; + mutable std::unordered_map m_variable_values; // current model - struct mon_eq { - mon_eq(lean::var_index v, unsigned sz, lean::var_index const* vs): - m_v(v), m_vs(sz, vs) {} - lean::var_index m_v; - svector m_vs; - }; - - vector m_monomials; - unsigned_vector m_lim; - mutable std::unordered_map m_variable_values; // current model - - imp(lean::lar_solver& s, reslimit& lim, params_ref const& p): + imp(lp::lar_solver& s, reslimit& lim, params_ref const& p): s(s), m_limit(lim), - m_params(p), - m_nlsat(m_limit, m_params) { + m_params(p) { } bool need_check() { return !m_monomials.empty() && !check_assignments(); } - void add(lean::var_index v, unsigned sz, lean::var_index const* vs) { + void add(lp::var_index v, unsigned sz, lp::var_index const* vs) { m_monomials.push_back(mon_eq(v, sz, vs)); } void push() { - m_lim.push_back(m_monomials.size()); + m_monomials_lim.push_back(m_monomials.size()); } void pop(unsigned n) { if (n == 0) return; - m_monomials.shrink(m_lim[m_lim.size() - n]); - m_lim.shrink(m_lim.size() - n); + m_monomials.shrink(m_monomials_lim[m_monomials_lim.size() - n]); + m_monomials_lim.shrink(m_monomials_lim.size() - n); } /* @@ -79,7 +76,6 @@ namespace nra { return true; } - /** \brief one-shot nlsat check. A one shot checker is the least functionality that can @@ -89,10 +85,11 @@ namespace nra { with the remaining solver. TBD: use partial model from lra_solver to prime the state of nlsat_solver. + TBD: explore more incremental ways of applying nlsat (using assumptions) */ - lbool check(lean::explanation_t& ex) { + lbool check(lp::explanation_t& ex) { SASSERT(need_check()); - m_nlsat.reset(); + m_nlsat = alloc(nlsat::solver, m_limit, m_params); m_lp2nl.reset(); vector core; @@ -107,14 +104,14 @@ namespace nra { } // TBD: add variable bounds? - lbool r = m_nlsat.check(); - TRACE("arith", m_nlsat.display(tout << r << "\n");); + lbool r = m_nlsat->check(); + TRACE("arith", m_nlsat->display(tout << r << "\n");); switch (r) { case l_true: break; case l_false: ex.reset(); - m_nlsat.get_core(core); + m_nlsat->get_core(core); for (auto c : core) { unsigned idx = static_cast(static_cast(c) - this); ex.push_back(std::pair(rational(1), idx)); @@ -129,7 +126,7 @@ namespace nra { } void add_monomial_eq(mon_eq const& m) { - polynomial::manager& pm = m_nlsat.pm(); + polynomial::manager& pm = m_nlsat->pm(); svector vars; for (auto v : m.m_vs) { vars.push_back(lp2nl(v)); @@ -143,13 +140,13 @@ namespace nra { polynomial::polynomial_ref p(pm.mk_polynomial(2, coeffs.c_ptr(), mls), pm); polynomial::polynomial* ps[1] = { p }; bool even[1] = { false }; - nlsat::literal lit = m_nlsat.mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, even); - m_nlsat.mk_clause(1, &lit, 0); + nlsat::literal lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, even); + m_nlsat->mk_clause(1, &lit, 0); } void add_constraint(unsigned idx) { auto& c = s.get_constraint(idx); - auto& pm = m_nlsat.pm(); + auto& pm = m_nlsat->pm(); auto k = c.m_kind; auto rhs = c.m_right_side; auto lhs = c.get_left_side_coefficients(); @@ -169,45 +166,48 @@ namespace nra { polynomial::polynomial* ps[1] = { p }; bool is_even[1] = { false }; nlsat::literal lit; - switch (k) { - case lean::lconstraint_kind::LE: - lit = ~m_nlsat.mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even); - break; - case lean::lconstraint_kind::GE: - lit = ~m_nlsat.mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even); - break; - case lean::lconstraint_kind::LT: - lit = m_nlsat.mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even); - break; - case lean::lconstraint_kind::GT: - lit = m_nlsat.mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even); - break; - case lean::lconstraint_kind::EQ: - lit = m_nlsat.mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, is_even); - break; - } nlsat::assumption a = this + idx; - m_nlsat.mk_clause(1, &lit, a); + switch (k) { + case lp::lconstraint_kind::LE: + lit = ~m_nlsat->mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even); + break; + case lp::lconstraint_kind::GE: + lit = ~m_nlsat->mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even); + break; + case lp::lconstraint_kind::LT: + lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even); + break; + case lp::lconstraint_kind::GT: + lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even); + break; + case lp::lconstraint_kind::EQ: + lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, is_even); + break; + } + m_nlsat->mk_clause(1, &lit, a); } - bool is_int(lean::var_index v) { - // TBD: is it s.column_is_integer(v), if then the function should take a var_index and not unsigned; s.is_int(v); - return false; + bool is_int(lp::var_index v) { + return s.var_is_int(v); } - polynomial::var lp2nl(lean::var_index v) { + polynomial::var lp2nl(lp::var_index v) { polynomial::var r; if (!m_lp2nl.find(v, r)) { - r = m_nlsat.mk_var(is_int(v)); + r = m_nlsat->mk_var(is_int(v)); m_lp2nl.insert(v, r); } return r; } - nlsat::anum const& value(lean::var_index v) const { - return m_nlsat.value(m_lp2nl.find(v)); + nlsat::anum const& value(lp::var_index v) const { + return m_nlsat->value(m_lp2nl.find(v)); + } + + nlsat::anum_manager& am() { + return m_nlsat->am(); } std::ostream& display(std::ostream& out) const { @@ -220,10 +220,9 @@ namespace nra { } return out; } - }; - solver::solver(lean::lar_solver& s, reslimit& lim, params_ref const& p) { + solver::solver(lp::lar_solver& s, reslimit& lim, params_ref const& p) { m_imp = alloc(imp, s, lim, p); } @@ -231,11 +230,11 @@ namespace nra { dealloc(m_imp); } - void solver::add_monomial(lean::var_index v, unsigned sz, lean::var_index const* vs) { + void solver::add_monomial(lp::var_index v, unsigned sz, lp::var_index const* vs) { m_imp->add(v, sz, vs); } - lbool solver::check(lean::explanation_t& ex) { + lbool solver::check(lp::explanation_t& ex) { return m_imp->check(ex); } @@ -255,8 +254,13 @@ namespace nra { return m_imp->display(out); } - nlsat::anum const& solver::value(lean::var_index v) const { + nlsat::anum const& solver::value(lp::var_index v) const { return m_imp->value(v); } + nlsat::anum_manager& solver::am() { + return m_imp->am(); + } + + } diff --git a/src/util/lp/nra_solver.h b/src/util/lp/nra_solver.h index cc09e24d6..70e614e91 100644 --- a/src/util/lp/nra_solver.h +++ b/src/util/lp/nra_solver.h @@ -1,6 +1,6 @@ /* Copyright (c) 2017 Microsoft Corporation - Author: Lev Nachmanson + Author: Nikolaj Bjorner */ #pragma once @@ -10,7 +10,7 @@ #include "util/params.h" #include "nlsat/nlsat_solver.h" -namespace lean { +namespace lp { class lar_solver; } @@ -25,7 +25,7 @@ namespace nra { public: - solver(lean::lar_solver& s, reslimit& lim, params_ref const& p = params_ref()); + solver(lp::lar_solver& s, reslimit& lim, params_ref const& p = params_ref()); ~solver(); @@ -33,13 +33,13 @@ namespace nra { \brief Add a definition v = vs[0]*vs[1]*...*vs[sz-1] The variable v is equal to the product of variables vs. */ - void add_monomial(lean::var_index v, unsigned sz, lean::var_index const* vs); + void add_monomial(lp::var_index v, unsigned sz, lp::var_index const* vs); /* \brief Check feasiblity of linear constraints augmented by polynomial definitions that are added. */ - lbool check(lean::explanation_t& ex); + lbool check(lp::explanation_t& ex); /* \brief determine whether nra check is needed. @@ -49,7 +49,9 @@ namespace nra { /* \brief Access model. */ - nlsat::anum const& value(lean::var_index v) const; + nlsat::anum const& value(lp::var_index v) const; + + nlsat::anum_manager& am(); /* \brief push and pop scope. diff --git a/src/util/lp/numeric_pair.h b/src/util/lp/numeric_pair.h index 84c99b3b1..b41f6b565 100644 --- a/src/util/lp/numeric_pair.h +++ b/src/util/lp/numeric_pair.h @@ -17,11 +17,11 @@ // include "util/numerics/mpq.h" // include "util/numerics/numeric_traits.h" #endif -namespace lean { +namespace lp { #ifdef lp_for_z3 // rename rationals typedef rational mpq; #else - typedef lean::mpq mpq; + typedef lp::mpq mpq; #endif @@ -73,8 +73,8 @@ template struct convert_struct { static X convert(const Y & y){ return X(y);} static bool is_epsilon_small(const X & x, const double & y) { return std::abs(numeric_traits::get_double(x)) < y; } - static bool below_bound_numeric(const X &, const X &, const Y &) { /*lean_unreachable();*/ return false;} - static bool above_bound_numeric(const X &, const X &, const Y &) { /*lean_unreachable();*/ return false; } + static bool below_bound_numeric(const X &, const X &, const Y &) { /*lp_unreachable();*/ return false;} + static bool above_bound_numeric(const X &, const X &, const Y &) { /*lp_unreachable();*/ return false; } }; @@ -144,7 +144,7 @@ struct numeric_pair { } numeric_pair operator/(const numeric_pair &) const { - // lean_unreachable(); + // lp_unreachable(); } @@ -153,7 +153,7 @@ struct numeric_pair { } numeric_pair operator*(const numeric_pair & /*a*/) const { - // lean_unreachable(); + // lp_unreachable(); } numeric_pair& operator+=(const numeric_pair & a) { @@ -188,7 +188,7 @@ struct numeric_pair { return numeric_pair(-x, -y); } - static bool precize() { return lean::numeric_traits::precize();} + static bool precize() { return lp::numeric_traits::precize();} bool is_zero() const { return x.is_zero() && y.is_zero(); } @@ -199,6 +199,11 @@ struct numeric_pair { std::string to_string() const { return std::string("(") + T_to_string(x) + ", " + T_to_string(y) + ")"; } + + bool is_int() const { + return x.is_int() && y.is_zero(); + } + }; @@ -225,15 +230,15 @@ numeric_pair operator/(const numeric_pair & r, const X & a) { } // template bool precise() { return numeric_traits::precise();} -template double get_double(const lean::numeric_pair & ) { /* lean_unreachable(); */ return 0;} +template double get_double(const lp::numeric_pair & ) { /* lp_unreachable(); */ return 0;} template -class numeric_traits> { +class numeric_traits> { public: static bool precise() { return numeric_traits::precise();} - static lean::numeric_pair zero() { return lean::numeric_pair(numeric_traits::zero(), numeric_traits::zero()); } - static bool is_zero(const lean::numeric_pair & v) { return numeric_traits::is_zero(v.x) && numeric_traits::is_zero(v.y); } - static double get_double(const lean::numeric_pair & v){ return numeric_traits::get_double(v.x); } // just return the double of the first coordinate - static double one() { /*lean_unreachable();*/ return 0;} + static lp::numeric_pair zero() { return lp::numeric_pair(numeric_traits::zero(), numeric_traits::zero()); } + static bool is_zero(const lp::numeric_pair & v) { return numeric_traits::is_zero(v.x) && numeric_traits::is_zero(v.y); } + static double get_double(const lp::numeric_pair & v){ return numeric_traits::get_double(v.x); } // just return the double of the first coordinate + static double one() { /*lp_unreachable();*/ return 0;} static bool is_pos(const numeric_pair &p) { return numeric_traits::is_pos(p.x) || (numeric_traits::is_zero(p.x) && numeric_traits::is_pos(p.y)); @@ -263,11 +268,11 @@ struct convert_struct, double> { return convert_struct::is_epsilon_small(p.x, eps) && convert_struct::is_epsilon_small(p.y, eps); } static bool below_bound_numeric(const numeric_pair &, const numeric_pair &, const double &) { - // lean_unreachable(); + // lp_unreachable(); return false; } static bool above_bound_numeric(const numeric_pair &, const numeric_pair &, const double &) { - // lean_unreachable(); + // lp_unreachable(); return false; } }; @@ -324,4 +329,26 @@ struct convert_struct { template bool is_epsilon_small(const X & v, const double &eps) { return convert_struct::is_epsilon_small(v, eps);} template bool below_bound_numeric(const X & x, const X & bound, const double& eps) { return convert_struct::below_bound_numeric(x, bound, eps);} template bool above_bound_numeric(const X & x, const X & bound, const double& eps) { return convert_struct::above_bound_numeric(x, bound, eps);} +template T floor(const numeric_pair & r) { + if (r.x.is_int()) { + if (r.y.is_nonneg()) { + return r.x; + } + return r.x - mpq::one(); + } + + return floor(r.x); +} + +template T ceil(const numeric_pair & r) { + if (r.x.is_int()) { + if (r.y.is_nonpos()) { + return r.x; + } + return r.x + mpq::one(); + } + + return ceil(r.x); +} + } diff --git a/src/util/lp/permutation_matrix.h b/src/util/lp/permutation_matrix.h index 4bdd57f25..e0a3ac4c1 100644 --- a/src/util/lp/permutation_matrix.h +++ b/src/util/lp/permutation_matrix.h @@ -12,7 +12,7 @@ #include "util/lp/lp_settings.h" #include "util/lp/matrix.h" #include "util/lp/tail_matrix.h" -namespace lean { +namespace lp { #ifdef LEAN_DEBUG inline bool is_even(int k) { return (k/2)*2 == k; } #endif @@ -86,7 +86,7 @@ class permutation_matrix : public tail_matrix { void apply_reverse_from_right_to_X(vector & w); void set_val(unsigned i, unsigned pi) { - lean_assert(i < size() && pi < size()); m_permutation[i] = pi; m_rev[pi] = i; } + lp_assert(i < size() && pi < size()); m_permutation[i] = pi; m_rev[pi] = i; } void transpose_from_left(unsigned i, unsigned j); diff --git a/src/util/lp/permutation_matrix.hpp b/src/util/lp/permutation_matrix.hpp index ec9af5a50..a379e1ab2 100644 --- a/src/util/lp/permutation_matrix.hpp +++ b/src/util/lp/permutation_matrix.hpp @@ -4,7 +4,7 @@ */ #include "util/vector.h" #include "util/lp/permutation_matrix.h" -namespace lean { +namespace lp { template permutation_matrix::permutation_matrix(unsigned length): m_permutation(length), m_rev(length), m_T_buffer(length), m_X_buffer(length) { for (unsigned i = 0; i < length; i++) { // do not change the direction of the loop because of the vectorization bug in clang3.3 m_permutation[i] = m_rev[i] = i; @@ -50,7 +50,7 @@ void permutation_matrix::apply_from_left(vector & w, lp_settings & ) { // deb.apply_from_left(deb_w); #endif // std::cout << " apply_from_left " << std::endl; - lean_assert(m_X_buffer.size() == w.size()); + lp_assert(m_X_buffer.size() == w.size()); unsigned i = size(); while (i-- > 0) { m_X_buffer[i] = w[m_permutation[i]]; @@ -60,7 +60,7 @@ void permutation_matrix::apply_from_left(vector & w, lp_settings & ) { w[i] = m_X_buffer[i]; } #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w, row_count())); + // lp_assert(vectors_are_equal(deb_w, w, row_count())); // delete [] deb_w; #endif } @@ -86,7 +86,7 @@ template void permutation_matrix::apply_from_righ // T * deb_w = clone_vector(w, row_count()); // deb.apply_from_right(deb_w); #endif - lean_assert(m_T_buffer.size() == w.size()); + lp_assert(m_T_buffer.size() == w.size()); for (unsigned i = 0; i < size(); i++) { m_T_buffer[i] = w[m_rev[i]]; } @@ -95,7 +95,7 @@ template void permutation_matrix::apply_from_righ w[i] = m_T_buffer[i]; } #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w, row_count())); + // lp_assert(vectors_are_equal(deb_w, w, row_count())); // delete [] deb_w; #endif } @@ -117,9 +117,9 @@ template void permutation_matrix::apply_from_righ unsigned pj = m_permutation[j]; w.set_value(buffer[i], pj); } - lean_assert(w.is_OK()); + lp_assert(w.is_OK()); #ifdef LEAN_DEBUG - lean_assert(vectors_are_equal(wcopy, w.m_data)); + lp_assert(vectors_are_equal(wcopy, w.m_data)); #endif } @@ -166,7 +166,7 @@ void permutation_matrix::apply_reverse_from_left(indexed_vector & w) { w.m_index[i] = j; } #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w.m_data, row_count())); + // lp_assert(vectors_are_equal(deb_w, w.m_data, row_count())); // delete [] deb_w; #endif } @@ -174,7 +174,7 @@ void permutation_matrix::apply_reverse_from_left(indexed_vector & w) { template void permutation_matrix::apply_reverse_from_left_to_T(vector & w) { // the result will be w = p(-1) * w - lean_assert(m_T_buffer.size() == w.size()); + lp_assert(m_T_buffer.size() == w.size()); unsigned i = size(); while (i-- > 0) { m_T_buffer[m_permutation[i]] = w[i]; @@ -187,7 +187,7 @@ void permutation_matrix::apply_reverse_from_left_to_T(vector & w) { template void permutation_matrix::apply_reverse_from_left_to_X(vector & w) { // the result will be w = p(-1) * w - lean_assert(m_X_buffer.size() == w.size()); + lp_assert(m_X_buffer.size() == w.size()); unsigned i = size(); while (i-- > 0) { m_X_buffer[m_permutation[i]] = w[i]; @@ -201,7 +201,7 @@ void permutation_matrix::apply_reverse_from_left_to_X(vector & w) { template void permutation_matrix::apply_reverse_from_right_to_T(vector & w) { // the result will be w = w * p(-1) - lean_assert(m_T_buffer.size() == w.size()); + lp_assert(m_T_buffer.size() == w.size()); unsigned i = size(); while (i-- > 0) { m_T_buffer[i] = w[m_permutation[i]]; @@ -219,7 +219,7 @@ void permutation_matrix::apply_reverse_from_right_to_T(indexed_vector & // vector wcopy(w.m_data); // apply_reverse_from_right_to_T(wcopy); #endif - lean_assert(w.is_OK()); + lp_assert(w.is_OK()); vector tmp; vector tmp_index(w.m_index); for (auto i : w.m_index) { @@ -232,15 +232,15 @@ void permutation_matrix::apply_reverse_from_right_to_T(indexed_vector & w.set_value(tmp[k], m_rev[j]); } - // lean_assert(w.is_OK()); - // lean_assert(vectors_are_equal(w.m_data, wcopy)); + // lp_assert(w.is_OK()); + // lp_assert(vectors_are_equal(w.m_data, wcopy)); } template void permutation_matrix::apply_reverse_from_right_to_X(vector & w) { // the result will be w = w * p(-1) - lean_assert(m_X_buffer.size() == w.size()); + lp_assert(m_X_buffer.size() == w.size()); unsigned i = size(); while (i-- > 0) { m_X_buffer[i] = w[m_permutation[i]]; @@ -253,7 +253,7 @@ void permutation_matrix::apply_reverse_from_right_to_X(vector & w) { template void permutation_matrix::transpose_from_left(unsigned i, unsigned j) { // the result will be this = (i,j)*this - lean_assert(i < size() && j < size() && i != j); + lp_assert(i < size() && j < size() && i != j); auto pi = m_rev[i]; auto pj = m_rev[j]; set_val(pi, j); @@ -262,7 +262,7 @@ template void permutation_matrix::transpose_from_ template void permutation_matrix::transpose_from_right(unsigned i, unsigned j) { // the result will be this = this * (i,j) - lean_assert(i < size() && j < size() && i != j); + lp_assert(i < size() && j < size() && i != j); auto pi = m_permutation[i]; auto pj = m_permutation[j]; set_val(i, pj); @@ -271,7 +271,7 @@ template void permutation_matrix::transpose_from_ template void permutation_matrix::multiply_by_permutation_from_left(permutation_matrix & p) { m_work_array = m_permutation; - lean_assert(p.size() == size()); + lp_assert(p.size() == size()); unsigned i = size(); while (i-- > 0) { set_val(i, m_work_array[p[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation @@ -281,7 +281,7 @@ template void permutation_matrix::multiply_by_per // this is multiplication in the matrix sense template void permutation_matrix::multiply_by_permutation_from_right(permutation_matrix & p) { m_work_array = m_permutation; - lean_assert(p.size() == size()); + lp_assert(p.size() == size()); unsigned i = size(); while (i-- > 0) set_val(i, p[m_work_array[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation @@ -289,7 +289,7 @@ template void permutation_matrix::multiply_by_per } template void permutation_matrix::multiply_by_reverse_from_right(permutation_matrix & q){ // todo : condensed permutations ? - lean_assert(q.size() == size()); + lp_assert(q.size() == size()); m_work_array = m_permutation; // the result is this = this*q(-1) unsigned i = size(); diff --git a/src/util/lp/permutation_matrix_instances.cpp b/src/util/lp/permutation_matrix_instances.cpp index 91473fabc..756ce4325 100644 --- a/src/util/lp/permutation_matrix_instances.cpp +++ b/src/util/lp/permutation_matrix_instances.cpp @@ -6,50 +6,50 @@ #include "util/vector.h" #include "util/lp/permutation_matrix.hpp" #include "util/lp/numeric_pair.h" -template void lean::permutation_matrix::apply_from_right(vector&); -template void lean::permutation_matrix::init(unsigned int); -template void lean::permutation_matrix::init(unsigned int); -template void lean::permutation_matrix>::init(unsigned int); -template bool lean::permutation_matrix::is_identity() const; -template void lean::permutation_matrix::multiply_by_permutation_from_left(lean::permutation_matrix&); -template void lean::permutation_matrix::multiply_by_permutation_reverse_from_left(lean::permutation_matrix&); -template void lean::permutation_matrix::multiply_by_reverse_from_right(lean::permutation_matrix&); -template lean::permutation_matrix::permutation_matrix(unsigned int, vector const&); -template void lean::permutation_matrix::transpose_from_left(unsigned int, unsigned int); +template void lp::permutation_matrix::apply_from_right(vector&); +template void lp::permutation_matrix::init(unsigned int); +template void lp::permutation_matrix::init(unsigned int); +template void lp::permutation_matrix>::init(unsigned int); +template bool lp::permutation_matrix::is_identity() const; +template void lp::permutation_matrix::multiply_by_permutation_from_left(lp::permutation_matrix&); +template void lp::permutation_matrix::multiply_by_permutation_reverse_from_left(lp::permutation_matrix&); +template void lp::permutation_matrix::multiply_by_reverse_from_right(lp::permutation_matrix&); +template lp::permutation_matrix::permutation_matrix(unsigned int, vector const&); +template void lp::permutation_matrix::transpose_from_left(unsigned int, unsigned int); -template void lean::permutation_matrix::apply_from_right(vector&); -template bool lean::permutation_matrix::is_identity() const; -template void lean::permutation_matrix::multiply_by_permutation_from_left(lean::permutation_matrix&); -template void lean::permutation_matrix::multiply_by_permutation_from_right(lean::permutation_matrix&); -template void lean::permutation_matrix::multiply_by_permutation_reverse_from_left(lean::permutation_matrix&); -template void lean::permutation_matrix::multiply_by_reverse_from_right(lean::permutation_matrix&); -template lean::permutation_matrix::permutation_matrix(unsigned int); -template void lean::permutation_matrix::transpose_from_left(unsigned int, unsigned int); -template void lean::permutation_matrix::transpose_from_right(unsigned int, unsigned int); -template void lean::permutation_matrix >::apply_from_right(vector&); -template bool lean::permutation_matrix >::is_identity() const; -template void lean::permutation_matrix >::multiply_by_permutation_from_left(lean::permutation_matrix >&); -template void lean::permutation_matrix >::multiply_by_permutation_from_right(lean::permutation_matrix >&); -template void lean::permutation_matrix >::multiply_by_permutation_reverse_from_left(lean::permutation_matrix >&); -template void lean::permutation_matrix >::multiply_by_reverse_from_right(lean::permutation_matrix >&); -template lean::permutation_matrix >::permutation_matrix(unsigned int); -template void lean::permutation_matrix >::transpose_from_left(unsigned int, unsigned int); -template void lean::permutation_matrix >::transpose_from_right(unsigned int, unsigned int); -template void lean::permutation_matrix::apply_reverse_from_left(lean::indexed_vector&); -template void lean::permutation_matrix::apply_reverse_from_left_to_T(vector&); -template void lean::permutation_matrix::apply_reverse_from_right_to_T(vector&); -template void lean::permutation_matrix::transpose_from_right(unsigned int, unsigned int); -template void lean::permutation_matrix::apply_reverse_from_left(lean::indexed_vector&); -template void lean::permutation_matrix::apply_reverse_from_left_to_T(vector&); -template void lean::permutation_matrix::apply_reverse_from_right_to_T(vector&); -template void lean::permutation_matrix >::apply_reverse_from_left(lean::indexed_vector&); -template void lean::permutation_matrix >::apply_reverse_from_left_to_T(vector&); -template void lean::permutation_matrix >::apply_reverse_from_right_to_T(vector&); -template void lean::permutation_matrix::multiply_by_permutation_from_right(lean::permutation_matrix&); -template lean::permutation_matrix::permutation_matrix(unsigned int); -template void lean::permutation_matrix::apply_reverse_from_left_to_X(vector &); -template void lean::permutation_matrix< lean::mpq, lean::mpq>::apply_reverse_from_left_to_X(vector &); -template void lean::permutation_matrix< lean::mpq, lean::numeric_pair< lean::mpq> >::apply_reverse_from_left_to_X(vector> &); -template void lean::permutation_matrix::apply_reverse_from_right_to_T(lean::indexed_vector&); -template void lean::permutation_matrix::apply_reverse_from_right_to_T(lean::indexed_vector&); -template void lean::permutation_matrix >::apply_reverse_from_right_to_T(lean::indexed_vector&); +template void lp::permutation_matrix::apply_from_right(vector&); +template bool lp::permutation_matrix::is_identity() const; +template void lp::permutation_matrix::multiply_by_permutation_from_left(lp::permutation_matrix&); +template void lp::permutation_matrix::multiply_by_permutation_from_right(lp::permutation_matrix&); +template void lp::permutation_matrix::multiply_by_permutation_reverse_from_left(lp::permutation_matrix&); +template void lp::permutation_matrix::multiply_by_reverse_from_right(lp::permutation_matrix&); +template lp::permutation_matrix::permutation_matrix(unsigned int); +template void lp::permutation_matrix::transpose_from_left(unsigned int, unsigned int); +template void lp::permutation_matrix::transpose_from_right(unsigned int, unsigned int); +template void lp::permutation_matrix >::apply_from_right(vector&); +template bool lp::permutation_matrix >::is_identity() const; +template void lp::permutation_matrix >::multiply_by_permutation_from_left(lp::permutation_matrix >&); +template void lp::permutation_matrix >::multiply_by_permutation_from_right(lp::permutation_matrix >&); +template void lp::permutation_matrix >::multiply_by_permutation_reverse_from_left(lp::permutation_matrix >&); +template void lp::permutation_matrix >::multiply_by_reverse_from_right(lp::permutation_matrix >&); +template lp::permutation_matrix >::permutation_matrix(unsigned int); +template void lp::permutation_matrix >::transpose_from_left(unsigned int, unsigned int); +template void lp::permutation_matrix >::transpose_from_right(unsigned int, unsigned int); +template void lp::permutation_matrix::apply_reverse_from_left(lp::indexed_vector&); +template void lp::permutation_matrix::apply_reverse_from_left_to_T(vector&); +template void lp::permutation_matrix::apply_reverse_from_right_to_T(vector&); +template void lp::permutation_matrix::transpose_from_right(unsigned int, unsigned int); +template void lp::permutation_matrix::apply_reverse_from_left(lp::indexed_vector&); +template void lp::permutation_matrix::apply_reverse_from_left_to_T(vector&); +template void lp::permutation_matrix::apply_reverse_from_right_to_T(vector&); +template void lp::permutation_matrix >::apply_reverse_from_left(lp::indexed_vector&); +template void lp::permutation_matrix >::apply_reverse_from_left_to_T(vector&); +template void lp::permutation_matrix >::apply_reverse_from_right_to_T(vector&); +template void lp::permutation_matrix::multiply_by_permutation_from_right(lp::permutation_matrix&); +template lp::permutation_matrix::permutation_matrix(unsigned int); +template void lp::permutation_matrix::apply_reverse_from_left_to_X(vector &); +template void lp::permutation_matrix< lp::mpq, lp::mpq>::apply_reverse_from_left_to_X(vector &); +template void lp::permutation_matrix< lp::mpq, lp::numeric_pair< lp::mpq> >::apply_reverse_from_left_to_X(vector> &); +template void lp::permutation_matrix::apply_reverse_from_right_to_T(lp::indexed_vector&); +template void lp::permutation_matrix::apply_reverse_from_right_to_T(lp::indexed_vector&); +template void lp::permutation_matrix >::apply_reverse_from_right_to_T(lp::indexed_vector&); diff --git a/src/util/lp/quick_xplain.cpp b/src/util/lp/quick_xplain.cpp index df409240e..53c7ecfca 100644 --- a/src/util/lp/quick_xplain.cpp +++ b/src/util/lp/quick_xplain.cpp @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #include "util/lp/lar_solver.h" -namespace lean { +namespace lp { quick_xplain::quick_xplain(vector> & explanation, const lar_solver & ls, lar_solver & qsol) : m_explanation(explanation), m_parent_solver(ls), @@ -29,7 +29,7 @@ void quick_xplain::copy_constraint_and_add_constraint_vars(const lar_constraint& bool quick_xplain::infeasible() { m_qsol.solve(); - return m_qsol.get_status() == INFEASIBLE; + return m_qsol.get_status() == lp_status::INFEASIBLE; } // u - unexplored constraints @@ -56,7 +56,7 @@ void quick_xplain::minimize(const vector& u) { } } if (m > 0) { - lean_assert(m_qsol.constraint_stack_size() >= initial_stack_size); + lp_assert(m_qsol.constraint_stack_size() >= initial_stack_size); m_qsol.pop(m_qsol.constraint_stack_size() - initial_stack_size); for (auto j : m_x) add_constraint_to_qsol(j); @@ -73,7 +73,7 @@ void quick_xplain::minimize(const vector& u) { void quick_xplain::run(vector> & explanation, const lar_solver & ls){ if (explanation.size() <= 2) return; lar_solver qsol; - lean_assert(ls.explanation_is_correct(explanation)); + lp_assert(ls.explanation_is_correct(explanation)); quick_xplain q(explanation, ls, qsol); q.solve(); } @@ -100,7 +100,7 @@ bool quick_xplain::is_feasible(const vector & x, unsigned k) const { l.add_constraint(ls, c.m_kind, c.m_right_side); } l.solve(); - return l.get_status() != INFEASIBLE; + return l.get_status() != lp_status::INFEASIBLE; } bool quick_xplain::x_is_minimal() const { @@ -109,7 +109,7 @@ bool quick_xplain::x_is_minimal() const { x.push_back(j); for (unsigned k = 0; k < x.size(); k++) { - lean_assert(is_feasible(x, x[k])); + lp_assert(is_feasible(x, x[k])); } return true; } @@ -117,7 +117,7 @@ bool quick_xplain::x_is_minimal() const { void quick_xplain::solve() { copy_constraints_to_local_constraints(); m_qsol.push(); - lean_assert(m_qsol.constraint_count() == 0) + lp_assert(m_qsol.constraint_count() == 0) vector u; for (unsigned k = 0; k < m_constraints_in_local_vars.size(); k++) u.push_back(k); @@ -127,10 +127,10 @@ void quick_xplain::solve() { for (unsigned i : m_x) add_constraint_to_qsol(i); m_qsol.solve(); - lean_assert(m_qsol.get_status() == INFEASIBLE); + lp_assert(m_qsol.get_status() == lp_status::INFEASIBLE); m_qsol.get_infeasibility_explanation(m_explanation); - lean_assert(m_qsol.explanation_is_correct(m_explanation)); - lean_assert(x_is_minimal()); + lp_assert(m_qsol.explanation_is_correct(m_explanation)); + lp_assert(x_is_minimal()); for (auto & p : m_explanation) { p.second = this->m_local_constraint_offset_to_external_ci[m_local_ci_to_constraint_offsets[p.second]]; } diff --git a/src/util/lp/quick_xplain.h b/src/util/lp/quick_xplain.h index 9faa5f41c..952199f85 100644 --- a/src/util/lp/quick_xplain.h +++ b/src/util/lp/quick_xplain.h @@ -7,7 +7,7 @@ Author: Lev Nachmanson #include "util/vector.h" #include -namespace lean { +namespace lp { class lar_solver; // forward definition class quick_xplain { diff --git a/src/util/lp/random_updater.h b/src/util/lp/random_updater.h index 8cb9740ea..68b14c971 100644 --- a/src/util/lp/random_updater.h +++ b/src/util/lp/random_updater.h @@ -12,7 +12,7 @@ Author: Lev Nachmanson #include "util/lp/linear_combination_iterator.h" // see http://research.microsoft.com/projects/z3/smt07.pdf // The class searches for a feasible solution with as many different values of variables as it can find -namespace lean { +namespace lp { template struct numeric_pair; // forward definition class lar_core_solver; // forward definition class random_updater { diff --git a/src/util/lp/random_updater.hpp b/src/util/lp/random_updater.hpp index 7c6a0539f..ced6a3767 100644 --- a/src/util/lp/random_updater.hpp +++ b/src/util/lp/random_updater.hpp @@ -6,7 +6,7 @@ #include "util/lp/static_matrix.h" #include "util/lp/lar_solver.h" #include "util/vector.h" -namespace lean { +namespace lp { @@ -36,7 +36,7 @@ random_updater::interval random_updater::get_interval_of_non_basic_var(unsigned ret.set_upper_bound(m_core_solver.m_r_upper_bounds[j]); break; default: - lean_assert(false); + lp_assert(false); } return ret; } @@ -44,15 +44,15 @@ random_updater::interval random_updater::get_interval_of_non_basic_var(unsigned void random_updater::diminish_interval_for_basic_var(numeric_pair& nb_x, unsigned j, mpq & a, interval & r) { - lean_assert(m_core_solver.m_r_heading[j] >= 0); + lp_assert(m_core_solver.m_r_heading[j] >= 0); numeric_pair delta; - lean_assert(a != zero_of_type()); + lp_assert(a != zero_of_type()); switch (m_core_solver.get_column_type(j)) { case column_type::free_column: break; case column_type::low_bound: delta = m_core_solver.m_r_x[j] - m_core_solver.m_r_low_bounds[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); if (a > 0) { r.set_upper_bound(nb_x + delta / a); } else { @@ -61,7 +61,7 @@ void random_updater::diminish_interval_for_basic_var(numeric_pair& nb_x, un break; case column_type::upper_bound: delta = m_core_solver.m_r_upper_bounds()[j] - m_core_solver.m_r_x[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); if (a > 0) { r.set_low_bound(nb_x - delta / a); } else { @@ -71,17 +71,17 @@ void random_updater::diminish_interval_for_basic_var(numeric_pair& nb_x, un case column_type::boxed: if (a > 0) { delta = m_core_solver.m_r_x[j] - m_core_solver.m_r_low_bounds[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); r.set_upper_bound(nb_x + delta / a); delta = m_core_solver.m_r_upper_bounds()[j] - m_core_solver.m_r_x[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); r.set_low_bound(nb_x - delta / a); } else { // a < 0 delta = m_core_solver.m_r_upper_bounds()[j] - m_core_solver.m_r_x[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); r.set_upper_bound(nb_x - delta / a); delta = m_core_solver.m_r_x[j] - m_core_solver.m_r_low_bounds[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); r.set_low_bound(nb_x + delta / a); } break; @@ -90,7 +90,7 @@ void random_updater::diminish_interval_for_basic_var(numeric_pair& nb_x, un r.set_upper_bound(nb_x); break; default: - lean_assert(false); + lp_assert(false); } } @@ -113,15 +113,15 @@ random_updater::interval random_updater::find_shift_interval(unsigned j) { } void random_updater::shift_var(unsigned j, interval & r) { - lean_assert(r.contains(m_core_solver.m_r_x[j])); - lean_assert(m_core_solver.m_r_solver.column_is_feasible(j)); + lp_assert(r.contains(m_core_solver.m_r_x[j])); + lp_assert(m_core_solver.m_r_solver.column_is_feasible(j)); auto old_x = m_core_solver.m_r_x[j]; remove_value(old_x); auto new_val = m_core_solver.m_r_x[j] = get_random_from_interval(r); add_value(new_val); - lean_assert(r.contains(m_core_solver.m_r_x[j])); - lean_assert(m_core_solver.m_r_solver.column_is_feasible(j)); + lp_assert(r.contains(m_core_solver.m_r_x[j])); + lp_assert(m_core_solver.m_r_solver.column_is_feasible(j)); auto delta = m_core_solver.m_r_x[j] - old_x; unsigned i; @@ -130,9 +130,9 @@ void random_updater::shift_var(unsigned j, interval & r) { while(m_column_j->next(a, i)) { unsigned bj = m_core_solver.m_r_basis[i]; m_core_solver.m_r_x[bj] -= a * delta; - lean_assert(m_core_solver.m_r_solver.column_is_feasible(bj)); + lp_assert(m_core_solver.m_r_solver.column_is_feasible(bj)); } - lean_assert(m_core_solver.m_r_solver.A_mult_x_is_off() == false); + lp_assert(m_core_solver.m_r_solver.A_mult_x_is_off() == false); } numeric_pair random_updater::get_random_from_interval(interval & r) { @@ -143,7 +143,7 @@ numeric_pair random_updater::get_random_from_interval(interval & r) { return r.low_bound + numeric_pair(rand % range, 0); if ((!r.low_bound_is_set) && r.upper_bound_is_set) return r.upper_bound - numeric_pair(rand % range, 0); - lean_assert(r.low_bound_is_set && r.upper_bound_is_set); + lp_assert(r.low_bound_is_set && r.upper_bound_is_set); return r.low_bound + (rand % range) * (r.upper_bound - r.low_bound)/ range; } @@ -183,7 +183,7 @@ void random_updater::add_value(numeric_pair& v) { void random_updater::remove_value(numeric_pair& v) { std::unordered_map, unsigned>::iterator it = m_values.find(v); - lean_assert(it != m_values.end()); + lp_assert(it != m_values.end()); it->second--; if (it->second == 0) m_values.erase((std::unordered_map, unsigned>::const_iterator)it); diff --git a/src/util/lp/row_eta_matrix.h b/src/util/lp/row_eta_matrix.h index 90acb89f3..60adb23ae 100644 --- a/src/util/lp/row_eta_matrix.h +++ b/src/util/lp/row_eta_matrix.h @@ -10,7 +10,7 @@ #include "util/lp/sparse_vector.h" #include "util/lp/indexed_vector.h" #include "util/lp/permutation_matrix.h" -namespace lean { +namespace lp { // This is the sum of a unit matrix and a lower triangular matrix // with non-zero elements only in one row template @@ -55,7 +55,7 @@ public: } void push_back(unsigned row_index, T val ) { - lean_assert(row_index != m_row); + lp_assert(row_index != m_row); m_row_vector.push_back(row_index, val); } diff --git a/src/util/lp/row_eta_matrix.hpp b/src/util/lp/row_eta_matrix.hpp index 5758abeb8..11f8f4913 100644 --- a/src/util/lp/row_eta_matrix.hpp +++ b/src/util/lp/row_eta_matrix.hpp @@ -4,7 +4,7 @@ */ #include "util/vector.h" #include "util/lp/row_eta_matrix.h" -namespace lean { +namespace lp { template void row_eta_matrix::apply_from_left(vector & w, lp_settings &) { // #ifdef LEAN_DEBUG @@ -19,7 +19,7 @@ void row_eta_matrix::apply_from_left(vector & w, lp_settings &) { } // w[m_row] = w_at_row; // #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(clone_w, w, m_dimension)); + // lp_assert(vectors_are_equal(clone_w, w, m_dimension)); // delete [] clone_w; // #endif } @@ -43,7 +43,7 @@ void row_eta_matrix::apply_from_left_local_to_T(indexed_vector & w, lp_ auto it = std::find(w.m_index.begin(), w.m_index.end(), m_row); w.m_index.erase(it); } - // TBD: lean_assert(check_vector_for_small_values(w, settings)); + // TBD: lp_assert(check_vector_for_small_values(w, settings)); } template @@ -65,7 +65,7 @@ void row_eta_matrix::apply_from_left_local_to_X(indexed_vector & w, lp_ auto it = std::find(w.m_index.begin(), w.m_index.end(), m_row); w.m_index.erase(it); } - // TBD: does not compile lean_assert(check_vector_for_small_values(w, settings)); + // TBD: does not compile lp_assert(check_vector_for_small_values(w, settings)); } template @@ -81,14 +81,14 @@ void row_eta_matrix::apply_from_right(vector & w) { w[it.first] += w_row * it.second; } #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(clone_w, w, m_dimension)); + // lp_assert(vectors_are_equal(clone_w, w, m_dimension)); // delete clone_w; #endif } template void row_eta_matrix::apply_from_right(indexed_vector & w) { - lean_assert(w.is_OK()); + lp_assert(w.is_OK()); const T & w_row = w[m_row]; if (numeric_traits::is_zero(w_row)) return; #ifdef LEAN_DEBUG @@ -130,7 +130,7 @@ void row_eta_matrix::apply_from_right(indexed_vector & w) { } } #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(wcopy, w.m_data)); + // lp_assert(vectors_are_equal(wcopy, w.m_data)); #endif } @@ -151,7 +151,7 @@ void row_eta_matrix::conjugate_by_permutation(permutation_matrix & p for (unsigned i = static_cast(columns.size()); i-- > 0;) m_row_vector.m_data[i].first = p.get_rev(columns[i]); #ifdef LEAN_DEBUG - // lean_assert(deb == *this); + // lp_assert(deb == *this); #endif } #ifdef LEAN_DEBUG diff --git a/src/util/lp/row_eta_matrix_instances.cpp b/src/util/lp/row_eta_matrix_instances.cpp index c32023164..2278057c4 100644 --- a/src/util/lp/row_eta_matrix_instances.cpp +++ b/src/util/lp/row_eta_matrix_instances.cpp @@ -2,11 +2,11 @@ Copyright (c) 2017 Microsoft Corporation Author: Lev Nachmanson */ -#include "util/vector.h" #include +#include "util/vector.h" #include "util/lp/row_eta_matrix.hpp" #include "util/lp/lu.h" -namespace lean { +namespace lp { template void row_eta_matrix::conjugate_by_permutation(permutation_matrix&); template void row_eta_matrix >::conjugate_by_permutation(permutation_matrix >&); template void row_eta_matrix::conjugate_by_permutation(permutation_matrix&); diff --git a/src/util/lp/scaler.h b/src/util/lp/scaler.h index 33c5a6cc4..61869f082 100644 --- a/src/util/lp/scaler.h +++ b/src/util/lp/scaler.h @@ -11,7 +11,7 @@ #include /* exit, EXIT_FAILURE */ #include "util/lp/lp_utils.h" #include "util/lp/static_matrix.h" -namespace lean { +namespace lp { // for scaling an LP template class scaler { @@ -31,7 +31,7 @@ public: m_scaling_maximum(scaling_maximum), m_column_scale(column_scale), m_settings(settings) { - lean_assert(m_column_scale.size() == 0); + lp_assert(m_column_scale.size() == 0); m_column_scale.resize(m_A.column_count(), numeric_traits::one()); } diff --git a/src/util/lp/scaler.hpp b/src/util/lp/scaler.hpp index 69427eea0..482441d7f 100644 --- a/src/util/lp/scaler.hpp +++ b/src/util/lp/scaler.hpp @@ -5,7 +5,7 @@ #include #include "util/lp/scaler.h" #include "util/lp/numeric_pair.h" -namespace lean { +namespace lp { // for scaling an LP template T scaler::right_side_balance() { T ret = zero_of_type(); @@ -41,7 +41,7 @@ template T scaler::A_max() const { template T scaler::get_A_ratio() const { T min = A_min(); T max = A_max(); - lean_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(min)); + lp_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(min)); T ratio = max / min; return ratio; } @@ -51,7 +51,7 @@ template T scaler::get_max_ratio_on_rows() con unsigned i = m_A.row_count(); while (i--) { T den = m_A.get_min_abs_in_row(i); - lean_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(den)); + lp_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(den)); T t = m_A.get_max_abs_in_row(i)/ den; if (t > ret) ret = t; @@ -78,7 +78,7 @@ template void scaler::scale_rows_with_geometri while (i--) { T max = m_A.get_max_abs_in_row(i); T min = m_A.get_min_abs_in_row(i); - lean_assert(max > zero_of_type() && min > zero_of_type()); + lp_assert(max > zero_of_type() && min > zero_of_type()); if (is_zero(max) || is_zero(min)) continue; T gm = T(sqrt(numeric_traits::get_double(max*min))); diff --git a/src/util/lp/scaler_instances.cpp b/src/util/lp/scaler_instances.cpp index f97e8098f..de1c2b7aa 100644 --- a/src/util/lp/scaler_instances.cpp +++ b/src/util/lp/scaler_instances.cpp @@ -3,5 +3,5 @@ Author: Lev Nachmanson */ #include "util/lp/scaler.hpp" -template bool lean::scaler::scale(); -template bool lean::scaler::scale(); +template bool lp::scaler::scale(); +template bool lp::scaler::scale(); diff --git a/src/util/lp/signature_bound_evidence.h b/src/util/lp/signature_bound_evidence.h index a22c188b4..6a0b4115f 100644 --- a/src/util/lp/signature_bound_evidence.h +++ b/src/util/lp/signature_bound_evidence.h @@ -5,7 +5,7 @@ #pragma once #include "util/lp/lp_settings.h" #include "util/lp/lar_constraints.h" -namespace lean { +namespace lp { struct bound_signature { unsigned m_i; bool m_at_low; diff --git a/src/util/lp/sparse_matrix.h b/src/util/lp/sparse_matrix.h index 7256004da..17f9ed7e0 100644 --- a/src/util/lp/sparse_matrix.h +++ b/src/util/lp/sparse_matrix.h @@ -21,7 +21,7 @@ #include "util/lp/binary_heap_upair_queue.h" #include "util/lp/numeric_pair.h" #include "util/lp/int_set.h" -namespace lean { +namespace lp { // it is a square matrix template class sparse_matrix @@ -206,19 +206,19 @@ public: void multiply_from_right(permutation_matrix& p) { // m_dense = m_dense * p; m_column_permutation.multiply_by_permutation_from_right(p); - // lean_assert(*this == m_dense); + // lp_assert(*this == m_dense); } void multiply_from_left(permutation_matrix& p) { // m_dense = p * m_dense; m_row_permutation.multiply_by_permutation_from_left(p); - // lean_assert(*this == m_dense); + // lp_assert(*this == m_dense); } void multiply_from_left_with_reverse(permutation_matrix& p) { // m_dense = p * m_dense; m_row_permutation.multiply_by_permutation_reverse_from_left(p); - // lean_assert(*this == m_dense); + // lp_assert(*this == m_dense); } // adding delta columns at the end of the matrix @@ -231,13 +231,13 @@ public: // dense_matrix d(*this); m_column_permutation.transpose_from_left(a, b); // d.swap_columns(a, b); - // lean_assert(*this == d); + // lp_assert(*this == d); } void swap_rows(unsigned a, unsigned b) { m_row_permutation.transpose_from_right(a, b); // m_dense.swap_rows(a, b); - // lean_assert(*this == m_dense); + // lp_assert(*this == m_dense); } void divide_row_by_constant(unsigned i, const T & t, lp_settings & settings); @@ -393,7 +393,7 @@ public: void process_index_recursively_for_y_U(unsigned j, vector & sorted_rows); void resize(unsigned new_dim) { unsigned old_dim = dimension(); - lean_assert(new_dim >= old_dim); + lp_assert(new_dim >= old_dim); for (unsigned j = old_dim; j < new_dim; j++) { m_rows.push_back(vector>()); m_columns.push_back(col_header()); diff --git a/src/util/lp/sparse_matrix.hpp b/src/util/lp/sparse_matrix.hpp index 32bb8ed4e..a26f36ae9 100644 --- a/src/util/lp/sparse_matrix.hpp +++ b/src/util/lp/sparse_matrix.hpp @@ -7,7 +7,7 @@ #include "util/lp/sparse_matrix.h" #include #include -namespace lean { +namespace lp { template void sparse_matrix::copy_column_from_static_matrix(unsigned col, static_matrix const &A, unsigned col_index_in_the_new_matrix) { vector const & A_col_vector = A.m_columns[col]; @@ -82,12 +82,12 @@ void sparse_matrix::set_with_no_adjusting(unsigned row, unsigned col, T va template void sparse_matrix::set(unsigned row, unsigned col, T val) { // should not be used in efficient code - lean_assert(row < dimension() && col < dimension()); + lp_assert(row < dimension() && col < dimension()); // m_dense.set_elem(row, col, val); row = adjust_row(row); col = adjust_column(col); set_with_no_adjusting(row, col, val); - // lean_assert(*this == m_dense); + // lp_assert(*this == m_dense); } template @@ -261,8 +261,8 @@ vector sparse_matrix::get_full_row(unsigned i) const { // Returns false if the resulting row is all zeroes, and true otherwise template bool sparse_matrix::pivot_row_to_row(unsigned i, const T& alpha, unsigned i0, lp_settings & settings ) { - lean_assert(i < dimension() && i0 < dimension()); - lean_assert(i != i0); + lp_assert(i < dimension() && i0 < dimension()); + lp_assert(i != i0); unsigned pivot_col = adjust_column(i); i = adjust_row(i); i0 = adjust_row(i0); @@ -327,7 +327,7 @@ bool sparse_matrix::set_row_from_work_vector_and_clean_work_vector_not_adj if (numeric_traits::is_zero(work_vec[j])) { continue; } - lean_assert(!settings.abs_val_is_smaller_than_drop_tolerance(work_vec[j])); + lp_assert(!settings.abs_val_is_smaller_than_drop_tolerance(work_vec[j])); add_new_element(i0, adjust_column(j), work_vec[j]); work_vec[j] = numeric_traits::zero(); } @@ -372,7 +372,7 @@ void sparse_matrix::remove_zero_elements_and_set_data_on_existing_elements T val = work_vec[rj]; if (settings.abs_val_is_smaller_than_drop_tolerance(val)) { remove_element(row_vals, row_el_iv); - lean_assert(numeric_traits::is_zero(val)); + lp_assert(numeric_traits::is_zero(val)); } else { m_columns[j].m_values[row_el_iv.m_other].set_value(row_el_iv.m_value = val); work_vec[rj] = numeric_traits::zero(); @@ -393,7 +393,7 @@ void sparse_matrix::add_columns_at_the_end(unsigned delta) { template void sparse_matrix::delete_column(int i) { - lean_assert(i < dimension()); + lp_assert(i < dimension()); for (auto cell = m_columns[i].m_head; cell != nullptr;) { auto next_cell = cell->m_down; kill_cell(cell); @@ -403,7 +403,7 @@ void sparse_matrix::delete_column(int i) { template void sparse_matrix::divide_row_by_constant(unsigned i, const T & t, lp_settings & settings) { - lean_assert(!settings.abs_val_is_smaller_than_zero_tolerance(t)); + lp_assert(!settings.abs_val_is_smaller_than_zero_tolerance(t)); i = adjust_row(i); for (auto & iv : m_rows[i]) { T &v = iv.m_value; @@ -440,7 +440,7 @@ void sparse_matrix::solve_y_U(vector & y) const { // works by rows // dense_matrix deb(*this); // T * clone_y = clone_vector(y, dimension()); // deb.apply_from_right(clone_y); - // lean_assert(vectors_are_equal(rs, clone_y, dimension())); + // lp_assert(vectors_are_equal(rs, clone_y, dimension())); // delete [] clone_y; // delete [] rs; #endif @@ -474,10 +474,10 @@ void sparse_matrix::solve_y_U_indexed(indexed_vector & y, const lp_sett y.m_data[j] = zero_of_type(); } - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); #if 0 && LEAN_DEBUG if (numeric_traits::precise() == false) - lean_assert(vectors_are_equal(ycopy, y.m_data)); + lp_assert(vectors_are_equal(ycopy, y.m_data)); #endif } @@ -537,8 +537,8 @@ void sparse_matrix::add_delta_to_solution(const vector& del, vector template template void sparse_matrix::add_delta_to_solution(const indexed_vector& del, indexed_vector & y) { -// lean_assert(del.is_OK()); - // lean_assert(y.is_OK()); +// lp_assert(del.is_OK()); + // lp_assert(y.is_OK()); for (auto i : del.m_index) { y.add_value_at_index(i, del[i]); } @@ -546,11 +546,11 @@ void sparse_matrix::add_delta_to_solution(const indexed_vector& del, in template template void sparse_matrix::double_solve_U_y(indexed_vector& y, const lp_settings & settings){ - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); indexed_vector y_orig(y); // copy y aside vector active_rows; solve_U_y_indexed_only(y, settings, active_rows); - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); find_error_in_solution_U_y_indexed(y_orig, y, active_rows); // y_orig contains the error now if (y_orig.m_index.size() * ratio_of_index_size_to_all_size() < 32 * dimension()) { @@ -563,7 +563,7 @@ void sparse_matrix::double_solve_U_y(indexed_vector& y, const lp_settin add_delta_to_solution(y_orig.m_data, y.m_data); y.restore_index_and_clean_from_data(); } - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); } template template @@ -599,12 +599,12 @@ void sparse_matrix::solve_U_y(vector & y) { // it is a column wise vers // dense_matrix deb(*this); // T * clone_y = clone_vector(y, dimension()); // deb.apply_from_left(clone_y); - // lean_assert(vectors_are_equal(rs, clone_y, dimension())); + // lp_assert(vectors_are_equal(rs, clone_y, dimension())); #endif } template void sparse_matrix::process_index_recursively_for_y_U(unsigned j, vector & sorted_active_rows) { - lean_assert(m_processed[j] == false); + lp_assert(m_processed[j] == false); m_processed[j]=true; auto & row = m_rows[adjust_row(j)]; for (auto & c : row) { @@ -619,7 +619,7 @@ void sparse_matrix::process_index_recursively_for_y_U(unsigned j, vector void sparse_matrix::process_column_recursively(unsigned j, vector & sorted_active_rows) { - lean_assert(m_processed[j] == false); + lp_assert(m_processed[j] == false); auto & mc = m_columns[adjust_column(j)].m_values; for (auto & iv : mc) { unsigned i = adjust_row_inverse(iv.m_index); @@ -684,12 +684,12 @@ void sparse_matrix::solve_U_y_indexed_only(indexed_vector & y, const lp y[j] = zero_of_type(); } - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); #ifdef LEAN_DEBUG // dense_matrix deb(this); // vector clone_y(y.m_data); // deb.apply_from_left(clone_y); - // lean_assert(vectors_are_equal(rs, clone_y)); + // lp_assert(vectors_are_equal(rs, clone_y)); #endif } @@ -802,7 +802,7 @@ void sparse_matrix::add_new_elements_of_w_and_clear_w(unsigned column_to_r unsigned ai = adjust_row(i); add_new_element(ai, column_to_replace, w_at_i); auto & row_chunk = m_rows[ai]; - lean_assert(row_chunk.size() > 0); + lp_assert(row_chunk.size() > 0); if (abs(w_at_i) > abs(row_chunk[0].m_value)) put_max_index_to_0(row_chunk, static_cast(row_chunk.size()) - 1); } @@ -833,7 +833,7 @@ unsigned sparse_matrix::pivot_score(unsigned i, unsigned j) { template void sparse_matrix::enqueue_domain_into_pivot_queue() { - lean_assert(m_pivot_queue.size() == 0); + lp_assert(m_pivot_queue.size() == 0); for (unsigned i = 0; i < dimension(); i++) { auto & rh = m_rows[i]; unsigned rnz = static_cast(rh.size()); @@ -919,7 +919,7 @@ void sparse_matrix::update_active_pivots(unsigned row) { for (const auto & iv : m_rows[arow]) { col_header & ch = m_columns[iv.m_index]; int cols = static_cast(ch.m_values.size()) - ch.m_shortened_markovitz - 1; - lean_assert(cols >= 0); + lp_assert(cols >= 0); for (const auto &ivc : ch.m_values) { unsigned i = ivc.m_index; if (adjust_row_inverse(i) <= row) continue; // the i is not an active row @@ -945,7 +945,7 @@ bool sparse_matrix::shorten_active_matrix(unsigned row, eta_matrix * for (auto & iv : row_values) { const col_header& ch = m_columns[iv.m_index]; int cnz = static_cast(ch.m_values.size()) - ch.m_shortened_markovitz - 1; - lean_assert(cnz >= 0); + lp_assert(cnz >= 0); m_pivot_queue.enqueue(row, iv.m_index, rnz * cnz); } } @@ -961,7 +961,7 @@ unsigned sparse_matrix::pivot_score_without_shortened_counters(unsigned i, if (adjust_row_inverse(iv.m_index) < k) cnz--; } - lean_assert(cnz > 0); + lp_assert(cnz > 0); return m_rows[i].m_values.size() * (cnz - 1); } #ifdef LEAN_DEBUG @@ -971,15 +971,15 @@ bool sparse_matrix::can_improve_score_for_row(unsigned row, unsigned score auto & row_vals = m_rows[arow].m_values; auto & begin_iv = row_vals[0]; T row_max = abs(begin_iv.m_value); - lean_assert(adjust_column_inverse(begin_iv.m_index) >= k); + lp_assert(adjust_column_inverse(begin_iv.m_index) >= k); if (pivot_score_without_shortened_counters(arow, begin_iv.m_index, k) < score) { print_active_matrix(k); return true; } for (unsigned jj = 1; jj < row_vals.size(); jj++) { auto & iv = row_vals[jj]; - lean_assert(adjust_column_inverse(iv.m_index) >= k); - lean_assert(abs(iv.m_value) <= row_max); + lp_assert(adjust_column_inverse(iv.m_index) >= k); + lp_assert(abs(iv.m_value) <= row_max); if (c_partial_pivoting * abs(iv.m_value) < row_max) continue; if (pivot_score_without_shortened_counters(arow, iv.m_index, k) < score) { print_active_matrix(k); @@ -993,7 +993,7 @@ template bool sparse_matrix::really_best_pivot(unsigned i, unsigned j, T const & c_partial_pivoting, unsigned k) { unsigned queue_pivot_score = pivot_score_without_shortened_counters(i, j, k); for (unsigned ii = k; ii < dimension(); ii++) { - lean_assert(!can_improve_score_for_row(ii, queue_pivot_score, c_partial_pivoting, k)); + lp_assert(!can_improve_score_for_row(ii, queue_pivot_score, c_partial_pivoting, k)); } return true; } @@ -1026,7 +1026,7 @@ template bool sparse_matrix::pivot_queue_is_correct_for_row(unsigned i, unsigned k) { unsigned arow = adjust_row(i); for (auto & iv : m_rows[arow].m_values) { - lean_assert(pivot_score_without_shortened_counters(arow, iv.m_index, k + 1) == + lp_assert(pivot_score_without_shortened_counters(arow, iv.m_index, k + 1) == m_pivot_queue.get_priority(arow, iv.m_index)); } return true; @@ -1035,8 +1035,8 @@ bool sparse_matrix::pivot_queue_is_correct_for_row(unsigned i, unsigned k) template bool sparse_matrix::pivot_queue_is_correct_after_pivoting(int k) { for (unsigned i = k + 1; i < dimension(); i++ ) - lean_assert(pivot_queue_is_correct_for_row(i, k)); - lean_assert(m_pivot_queue.is_correct()); + lp_assert(pivot_queue_is_correct_for_row(i, k)); + lp_assert(m_pivot_queue.is_correct()); return true; } #endif @@ -1055,7 +1055,7 @@ bool sparse_matrix::get_pivot_for_column(unsigned &i, unsigned &j, int c_p #ifdef LEAN_DEBUG // if (!really_best_pivot(i, j, c_partial_pivoting, k)) { // print_active_matrix(k); - // lean_assert(false); + // lp_assert(false); // } #endif recover_pivot_queue(pivots_candidates_that_are_too_small); @@ -1088,7 +1088,7 @@ bool sparse_matrix::shorten_columns_by_pivot_row(unsigned i, unsigned pivo for (indexed_value & iv : row_chunk) { unsigned j = iv.m_index; if (j == pivot_column) { - lean_assert(!col_is_active(j)); + lp_assert(!col_is_active(j)); continue; } m_columns[j].shorten_markovich_by_one(); @@ -1151,11 +1151,11 @@ template bool sparse_matrix::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings & settings) const { for (unsigned i = 0; i < dimension(); i++) { vector> const & row_chunk = get_row_values(i); - lean_assert(row_chunk.size()); + lp_assert(row_chunk.size()); T const & max = abs(row_chunk[0].m_value); unsigned ai = adjust_row_inverse(i); for (auto & iv : row_chunk) { - lean_assert(abs(iv.m_value) <= max); + lp_assert(abs(iv.m_value) <= max); unsigned aj = adjust_column_inverse(iv.m_index); if (!(ai <= aj || numeric_traits::is_zero(iv.m_value))) return false; @@ -1193,18 +1193,18 @@ void sparse_matrix::check_column_vs_rows(unsigned col) { indexed_value & row_iv = column_iv_other(column_iv); if (row_iv.m_index != col) { // std::cout << "m_other in row does not belong to column " << col << ", but to column " << row_iv.m_index << std::endl; - lean_assert(false); + lp_assert(false); } if (& row_iv_other(row_iv) != &column_iv) { // std::cout << "row and col do not point to each other" << std::endl; - lean_assert(false); + lp_assert(false); } if (row_iv.m_value != column_iv.m_value) { // std::cout << "the data from col " << col << " for row " << column_iv.m_index << " is different in the column " << std::endl; // std::cout << "in the col it is " << column_iv.m_value << ", but in the row it is " << row_iv.m_value << std::endl; - lean_assert(false); + lp_assert(false); } } } @@ -1217,18 +1217,18 @@ void sparse_matrix::check_row_vs_columns(unsigned row) { if (column_iv.m_index != row) { // std::cout << "col_iv does not point to correct row " << row << " but to " << column_iv.m_index << std::endl; - lean_assert(false); + lp_assert(false); } if (& row_iv != & column_iv_other(column_iv)) { // std::cout << "row and col do not point to each other" << std::endl; - lean_assert(false); + lp_assert(false); } if (row_iv.m_value != column_iv.m_value) { // std::cout << "the data from col " << column_iv.m_index << " for row " << row << " is different in the column " << std::endl; // std::cout << "in the col it is " << column_iv.m_value << ", but in the row it is " << row_iv.m_value << std::endl; - lean_assert(false); + lp_assert(false); } } } diff --git a/src/util/lp/sparse_matrix_instances.cpp b/src/util/lp/sparse_matrix_instances.cpp index f80b60365..80a9b8ef5 100644 --- a/src/util/lp/sparse_matrix_instances.cpp +++ b/src/util/lp/sparse_matrix_instances.cpp @@ -2,13 +2,13 @@ Copyright (c) 2017 Microsoft Corporation Author: Lev Nachmanson */ -#include "util/vector.h" #include +#include "util/vector.h" #include "util/lp/lp_settings.h" #include "util/lp/lu.h" #include "util/lp/sparse_matrix.hpp" #include "util/lp/dense_matrix.h" -namespace lean { +namespace lp { template double sparse_matrix::dot_product_with_row(unsigned int, vector const&) const; template void sparse_matrix::add_new_element(unsigned int, unsigned int, const double&); template void sparse_matrix::divide_row_by_constant(unsigned int, const double&, lp_settings&); @@ -65,37 +65,37 @@ template void sparse_matrix::double_solve_U_y(indexed_ve template void sparse_matrix::double_solve_U_y(indexed_vector&, const lp_settings&); template void sparse_matrix>::double_solve_U_y(indexed_vector&, const lp_settings&); template void sparse_matrix >::double_solve_U_y >(indexed_vector>&, const lp_settings&); -template void lean::sparse_matrix::solve_U_y_indexed_only(lean::indexed_vector&, const lp_settings&, vector &); -template void lean::sparse_matrix::solve_U_y_indexed_only(lean::indexed_vector&, const lp_settings &, vector &); +template void lp::sparse_matrix::solve_U_y_indexed_only(lp::indexed_vector&, const lp_settings&, vector &); +template void lp::sparse_matrix::solve_U_y_indexed_only(lp::indexed_vector&, const lp_settings &, vector &); #ifdef LEAN_DEBUG template bool sparse_matrix::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const; template bool sparse_matrix::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const; template bool sparse_matrix >::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const; #endif } -template void lean::sparse_matrix >::solve_U_y_indexed_only(lean::indexed_vector&, const lp_settings &, vector &); -template void lean::sparse_matrix::solve_U_y(vector&); -template void lean::sparse_matrix::double_solve_U_y(vector&); -template void lean::sparse_matrix::solve_U_y(vector&); -template void lean::sparse_matrix::double_solve_U_y(vector&); -template void lean::sparse_matrix >::solve_U_y >(vector >&); -template void lean::sparse_matrix >::double_solve_U_y >(vector >&); -template void lean::sparse_matrix::find_error_in_solution_U_y_indexed(lean::indexed_vector&, lean::indexed_vector&, const vector &); -template double lean::sparse_matrix::dot_product_with_row(unsigned int, lean::indexed_vector const&) const; -template void lean::sparse_matrix::find_error_in_solution_U_y_indexed(lean::indexed_vector&, lean::indexed_vector&, const vector &); -template lean::mpq lean::sparse_matrix::dot_product_with_row(unsigned int, lean::indexed_vector const&) const; -template void lean::sparse_matrix >::find_error_in_solution_U_y_indexed(lean::indexed_vector&, lean::indexed_vector&, const vector &); -template lean::mpq lean::sparse_matrix >::dot_product_with_row(unsigned int, lean::indexed_vector const&) const; -template void lean::sparse_matrix >::find_error_in_solution_U_y_indexed >(lean::indexed_vector >&, lean::indexed_vector >&, const vector &); -template lean::numeric_pair lean::sparse_matrix >::dot_product_with_row >(unsigned int, lean::indexed_vector > const&) const; -template void lean::sparse_matrix::extend_and_sort_active_rows(vector const&, vector&); +template void lp::sparse_matrix >::solve_U_y_indexed_only(lp::indexed_vector&, const lp_settings &, vector &); +template void lp::sparse_matrix::solve_U_y(vector&); +template void lp::sparse_matrix::double_solve_U_y(vector&); +template void lp::sparse_matrix::solve_U_y(vector&); +template void lp::sparse_matrix::double_solve_U_y(vector&); +template void lp::sparse_matrix >::solve_U_y >(vector >&); +template void lp::sparse_matrix >::double_solve_U_y >(vector >&); +template void lp::sparse_matrix::find_error_in_solution_U_y_indexed(lp::indexed_vector&, lp::indexed_vector&, const vector &); +template double lp::sparse_matrix::dot_product_with_row(unsigned int, lp::indexed_vector const&) const; +template void lp::sparse_matrix::find_error_in_solution_U_y_indexed(lp::indexed_vector&, lp::indexed_vector&, const vector &); +template lp::mpq lp::sparse_matrix::dot_product_with_row(unsigned int, lp::indexed_vector const&) const; +template void lp::sparse_matrix >::find_error_in_solution_U_y_indexed(lp::indexed_vector&, lp::indexed_vector&, const vector &); +template lp::mpq lp::sparse_matrix >::dot_product_with_row(unsigned int, lp::indexed_vector const&) const; +template void lp::sparse_matrix >::find_error_in_solution_U_y_indexed >(lp::indexed_vector >&, lp::indexed_vector >&, const vector &); +template lp::numeric_pair lp::sparse_matrix >::dot_product_with_row >(unsigned int, lp::indexed_vector > const&) const; +template void lp::sparse_matrix::extend_and_sort_active_rows(vector const&, vector&); -template void lean::sparse_matrix >::extend_and_sort_active_rows(vector const&, vector&); +template void lp::sparse_matrix >::extend_and_sort_active_rows(vector const&, vector&); -template void lean::sparse_matrix >::solve_U_y(vector&); -template void lean::sparse_matrix >::double_solve_U_y(vector&); -template void lean::sparse_matrix< lean::mpq,lean::numeric_pair< lean::mpq> >::set(unsigned int,unsigned int, lean::mpq); -template void lean::sparse_matrix::solve_y_U_indexed(lean::indexed_vector&, const lp_settings & ); -template void lean::sparse_matrix::solve_y_U_indexed(lean::indexed_vector&, const lp_settings &); -template void lean::sparse_matrix >::solve_y_U_indexed(lean::indexed_vector&, const lp_settings &); +template void lp::sparse_matrix >::solve_U_y(vector&); +template void lp::sparse_matrix >::double_solve_U_y(vector&); +template void lp::sparse_matrix< lp::mpq,lp::numeric_pair< lp::mpq> >::set(unsigned int,unsigned int, lp::mpq); +template void lp::sparse_matrix::solve_y_U_indexed(lp::indexed_vector&, const lp_settings & ); +template void lp::sparse_matrix::solve_y_U_indexed(lp::indexed_vector&, const lp_settings &); +template void lp::sparse_matrix >::solve_y_U_indexed(lp::indexed_vector&, const lp_settings &); diff --git a/src/util/lp/sparse_vector.h b/src/util/lp/sparse_vector.h index 975cb7f28..65bd6d3f3 100644 --- a/src/util/lp/sparse_vector.h +++ b/src/util/lp/sparse_vector.h @@ -9,7 +9,7 @@ #include "util/debug.h" #include "util/lp/lp_utils.h" #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { template class sparse_vector { @@ -27,7 +27,7 @@ public: } #endif void divide(T const & a) { - lean_assert(!lp_settings::is_eps_small_general(a, 1e-12)); + lp_assert(!lp_settings::is_eps_small_general(a, 1e-12)); for (auto & t : m_data) { t.second /= a; } } diff --git a/src/util/lp/square_dense_submatrix.h b/src/util/lp/square_dense_submatrix.h index 019497aa5..c5aa1fa97 100644 --- a/src/util/lp/square_dense_submatrix.h +++ b/src/util/lp/square_dense_submatrix.h @@ -20,7 +20,7 @@ #include "util/lp/eta_matrix.h" #include "util/lp/binary_heap_upair_queue.h" #include "util/lp/sparse_matrix.h" -namespace lean { +namespace lp { template class square_dense_submatrix : public tail_matrix { // the submatrix uses the permutations of the parent matrix to access the elements @@ -30,11 +30,11 @@ class square_dense_submatrix : public tail_matrix { ref(unsigned i, square_dense_submatrix & s) : m_i_offset((i - s.m_index_start) * s.m_dim), m_s(s){} T & operator[] (unsigned j) { - lean_assert(j >= m_s.m_index_start); + lp_assert(j >= m_s.m_index_start); return m_s.m_v[m_i_offset + m_s.adjust_column(j) - m_s.m_index_start]; } const T & operator[] (unsigned j) const { - lean_assert(j >= m_s.m_index_start); + lp_assert(j >= m_s.m_index_start); return m_s.m_v[m_i_offset + m_s.adjust_column(j) - m_s.m_index_start]; } }; @@ -58,8 +58,8 @@ public: bool is_dense() const { return true; } ref operator[] (unsigned i) { - lean_assert(i >= m_index_start); - lean_assert(i < m_parent->dimension()); + lp_assert(i >= m_index_start); + lp_assert(i < m_parent->dimension()); return ref(i, *this); } @@ -148,7 +148,7 @@ public: } } } - lean_assert(wcopy.is_OK()); + lp_assert(wcopy.is_OK()); apply_from_right(w.m_data); w.m_index.clear(); if (numeric_traits::precise()) { @@ -167,11 +167,11 @@ public: } } #else - lean_assert(w.is_OK()); - lean_assert(m_work_vector.is_OK()); + lp_assert(w.is_OK()); + lp_assert(m_work_vector.is_OK()); m_work_vector.resize(w.data_size()); m_work_vector.clear(); - lean_assert(m_work_vector.is_OK()); + lp_assert(m_work_vector.is_OK()); unsigned end = m_index_start + m_dim; for (unsigned k : w.m_index) { // find j such that k = adjust_row_inverse(j) @@ -188,7 +188,7 @@ public: } } m_work_vector.clean_up(); - lean_assert(m_work_vector.is_OK()); + lp_assert(m_work_vector.is_OK()); w = m_work_vector; #endif } diff --git a/src/util/lp/square_dense_submatrix.hpp b/src/util/lp/square_dense_submatrix.hpp index 365c9d7f0..809d5c5a6 100644 --- a/src/util/lp/square_dense_submatrix.hpp +++ b/src/util/lp/square_dense_submatrix.hpp @@ -4,7 +4,7 @@ */ #include "util/vector.h" #include "util/lp/square_dense_submatrix.h" -namespace lean { +namespace lp { template square_dense_submatrix::square_dense_submatrix (sparse_matrix *parent_matrix, unsigned index_start) : m_index_start(index_start), @@ -18,7 +18,7 @@ square_dense_submatrix::square_dense_submatrix (sparse_matrix *paren unsigned row = parent_matrix->adjust_row(i); for (auto & iv : parent_matrix->get_row_values(row)) { unsigned j = parent_matrix->adjust_column_inverse(iv.m_index); - lean_assert(j>= m_index_start); + lp_assert(j>= m_index_start); m_v[row_offset + j] = iv.m_value; } row_offset += m_dim; @@ -43,7 +43,7 @@ template void square_dense_submatrix::init(sparse template int square_dense_submatrix::find_pivot_column_in_row(unsigned i) const { int j = -1; T max = zero_of_type(); - lean_assert(i >= m_index_start); + lp_assert(i >= m_index_start); unsigned row_start = (i - m_index_start) * m_dim; for (unsigned k = i; k < m_parent->dimension(); k++) { unsigned col = adjust_column(k); // this is where the column is in the row @@ -64,14 +64,14 @@ template void square_dense_submatrix::pivot(un } template void square_dense_submatrix::pivot_row_to_row(unsigned i, unsigned row, lp_settings & settings) { - lean_assert(i < row); + lp_assert(i < row); unsigned pj = adjust_column(i); // the pivot column unsigned pjd = pj - m_index_start; unsigned pivot_row_offset = (i-m_index_start)*m_dim; T pivot = m_v[pivot_row_offset + pjd]; unsigned row_offset= (row-m_index_start)*m_dim; T m = m_v[row_offset + pjd]; - lean_assert(!is_zero(pivot)); + lp_assert(!is_zero(pivot)); m_v[row_offset + pjd] = -m * pivot; // creating L matrix for (unsigned j = m_index_start; j < m_parent->dimension(); j++) { if (j == pj) { @@ -94,7 +94,7 @@ template void square_dense_submatrix::divide_r unsigned pj = adjust_column(i); // the pivot column unsigned irow_offset = (i - m_index_start) * m_dim; T pivot = m_v[irow_offset + pj - m_index_start]; - lean_assert(!is_zero(pivot)); + lp_assert(!is_zero(pivot)); for (unsigned k = m_index_start; k < m_parent->dimension(); k++) { if (k == pj){ m_v[irow_offset++] = one_of_type() / pivot; // creating the L matrix diagonal @@ -158,7 +158,7 @@ template void square_dense_submatrix::push_new template template L square_dense_submatrix::row_by_vector_product(unsigned i, const vector & v) { - lean_assert(i >= m_index_start); + lp_assert(i >= m_index_start); unsigned row_in_subm = i - m_index_start; unsigned row_offset = row_in_subm * m_dim; @@ -171,7 +171,7 @@ L square_dense_submatrix::row_by_vector_product(unsigned i, const vector template L square_dense_submatrix::column_by_vector_product(unsigned j, const vector & v) { - lean_assert(j >= m_index_start); + lp_assert(j >= m_index_start); unsigned offset = j - m_index_start; L r = zero_of_type(); @@ -182,7 +182,7 @@ L square_dense_submatrix::column_by_vector_product(unsigned j, const vecto template template L square_dense_submatrix::row_by_indexed_vector_product(unsigned i, const indexed_vector & v) { - lean_assert(i >= m_index_start); + lp_assert(i >= m_index_start); unsigned row_in_subm = i - m_index_start; unsigned row_offset = row_in_subm * m_dim; @@ -249,8 +249,8 @@ void square_dense_submatrix::apply_from_left_local(indexed_vector & w, #ifdef LEAN_DEBUG // cout << "w final" << endl; // print_vector(w.m_data); - // lean_assert(vectors_are_equal(deb_w, w.m_data)); - // lean_assert(w.is_OK()); + // lp_assert(vectors_are_equal(deb_w, w.m_data)); + // lp_assert(w.is_OK()); #endif } @@ -280,16 +280,16 @@ void square_dense_submatrix::apply_from_left_to_vector(vector & w) { #ifdef LEAN_DEBUG // cout << "w final" << endl; // print_vector(w.m_data); - // lean_assert(vectors_are_equal(deb_w, w)); + // lp_assert(vectors_are_equal(deb_w, w)); #endif } template bool square_dense_submatrix::is_L_matrix() const { #ifdef LEAN_DEBUG - lean_assert(m_row_permutation.is_identity()); + lp_assert(m_row_permutation.is_identity()); for (unsigned i = 0; i < m_parent->dimension(); i++) { if (i < m_index_start) { - lean_assert(m_column_permutation[i] == i); + lp_assert(m_column_permutation[i] == i); continue; } unsigned row_offs = (i-m_index_start)*m_dim; @@ -297,9 +297,9 @@ template bool square_dense_submatrix::is_L_mat unsigned j = m_index_start + k; unsigned jex = adjust_column_inverse(j); if (jex > i) { - lean_assert(is_zero(m_v[row_offs + k])); + lp_assert(is_zero(m_v[row_offs + k])); } else if (jex == i) { - lean_assert(!is_zero(m_v[row_offs + k])); + lp_assert(!is_zero(m_v[row_offs + k])); } } } @@ -327,7 +327,7 @@ template void square_dense_submatrix::apply_from_ } w = t; #ifdef LEAN_DEBUG - // lean_assert(vector_are_equal(deb_w, w)); + // lp_assert(vector_are_equal(deb_w, w)); #endif } diff --git a/src/util/lp/square_dense_submatrix_instances.cpp b/src/util/lp/square_dense_submatrix_instances.cpp index 7d45aaaa1..7283bb3da 100644 --- a/src/util/lp/square_dense_submatrix_instances.cpp +++ b/src/util/lp/square_dense_submatrix_instances.cpp @@ -5,29 +5,29 @@ #include #include "util/vector.h" #include "util/lp/square_dense_submatrix.hpp" -template void lean::square_dense_submatrix::init(lean::sparse_matrix*, unsigned int); -template lean::square_dense_submatrix::square_dense_submatrix(lean::sparse_matrix*, unsigned int); -template void lean::square_dense_submatrix::update_parent_matrix(lean::lp_settings&); -template bool lean::square_dense_submatrix::is_L_matrix() const; -template void lean::square_dense_submatrix::conjugate_by_permutation(lean::permutation_matrix&); -template int lean::square_dense_submatrix::find_pivot_column_in_row(unsigned int) const; -template void lean::square_dense_submatrix::pivot(unsigned int, lean::lp_settings&); -template lean::square_dense_submatrix >::square_dense_submatrix(lean::sparse_matrix >*, unsigned int); -template void lean::square_dense_submatrix >::update_parent_matrix(lean::lp_settings&); -template bool lean::square_dense_submatrix >::is_L_matrix() const; -template void lean::square_dense_submatrix >::conjugate_by_permutation(lean::permutation_matrix >&); -template int lean::square_dense_submatrix >::find_pivot_column_in_row(unsigned int) const; -template void lean::square_dense_submatrix >::pivot(unsigned int, lean::lp_settings&); +template void lp::square_dense_submatrix::init(lp::sparse_matrix*, unsigned int); +template lp::square_dense_submatrix::square_dense_submatrix(lp::sparse_matrix*, unsigned int); +template void lp::square_dense_submatrix::update_parent_matrix(lp::lp_settings&); +template bool lp::square_dense_submatrix::is_L_matrix() const; +template void lp::square_dense_submatrix::conjugate_by_permutation(lp::permutation_matrix&); +template int lp::square_dense_submatrix::find_pivot_column_in_row(unsigned int) const; +template void lp::square_dense_submatrix::pivot(unsigned int, lp::lp_settings&); +template lp::square_dense_submatrix >::square_dense_submatrix(lp::sparse_matrix >*, unsigned int); +template void lp::square_dense_submatrix >::update_parent_matrix(lp::lp_settings&); +template bool lp::square_dense_submatrix >::is_L_matrix() const; +template void lp::square_dense_submatrix >::conjugate_by_permutation(lp::permutation_matrix >&); +template int lp::square_dense_submatrix >::find_pivot_column_in_row(unsigned int) const; +template void lp::square_dense_submatrix >::pivot(unsigned int, lp::lp_settings&); #ifdef LEAN_DEBUG -template double lean::square_dense_submatrix::get_elem(unsigned int, unsigned int) const; +template double lp::square_dense_submatrix::get_elem(unsigned int, unsigned int) const; #endif -template void lean::square_dense_submatrix::apply_from_right(vector&); +template void lp::square_dense_submatrix::apply_from_right(vector&); -template void lean::square_dense_submatrix::apply_from_left_local(lean::indexed_vector&, lean::lp_settings&); -template void lean::square_dense_submatrix::apply_from_left_to_vector(vector&); -template lean::square_dense_submatrix::square_dense_submatrix(lean::sparse_matrix*, unsigned int); -template void lean::square_dense_submatrix::update_parent_matrix(lean::lp_settings&); -template bool lean::square_dense_submatrix::is_L_matrix() const; -template void lean::square_dense_submatrix::conjugate_by_permutation(lean::permutation_matrix&); -template int lean::square_dense_submatrix::find_pivot_column_in_row(unsigned int) const; -template void lean::square_dense_submatrix::pivot(unsigned int, lean::lp_settings&); +template void lp::square_dense_submatrix::apply_from_left_local(lp::indexed_vector&, lp::lp_settings&); +template void lp::square_dense_submatrix::apply_from_left_to_vector(vector&); +template lp::square_dense_submatrix::square_dense_submatrix(lp::sparse_matrix*, unsigned int); +template void lp::square_dense_submatrix::update_parent_matrix(lp::lp_settings&); +template bool lp::square_dense_submatrix::is_L_matrix() const; +template void lp::square_dense_submatrix::conjugate_by_permutation(lp::permutation_matrix&); +template int lp::square_dense_submatrix::find_pivot_column_in_row(unsigned int) const; +template void lp::square_dense_submatrix::pivot(unsigned int, lp::lp_settings&); diff --git a/src/util/lp/stacked_map.h b/src/util/lp/stacked_map.h index 4692540dd..1c55b9f9f 100644 --- a/src/util/lp/stacked_map.h +++ b/src/util/lp/stacked_map.h @@ -8,7 +8,7 @@ #include #include #include -namespace lean { +namespace lp { template second; } }; @@ -73,7 +73,7 @@ public: const B & operator[]( const A & a) const { auto it = m_map.find(a); if (it == m_map.end()) { - lean_assert(false); + lp_assert(false); } return it->second; @@ -128,7 +128,7 @@ public: for (auto & t: d.m_original_changed) { m_map[t.first] = t.second; } - // lean_assert(d.m_deb_copy == m_map); + // lp_assert(d.m_deb_copy == m_map); m_stack.pop(); } } @@ -142,7 +142,7 @@ public: delta & d = m_stack.top(); auto it = m_map.find(key); if (it == m_map.end()) { - lean_assert(d.m_new.find(key) == d.m_new.end()); + lp_assert(d.m_new.find(key) == d.m_new.end()); return; } auto &orig_changed = d.m_original_changed; @@ -151,7 +151,7 @@ public: if (orig_changed.find(key) == orig_changed.end()) orig_changed.emplace(it->first, it->second); // need to restore } else { // k is new - lean_assert(orig_changed.find(key) == orig_changed.end()); + lp_assert(orig_changed.find(key) == orig_changed.end()); d.m_new.erase(nit); } diff --git a/src/util/lp/stacked_unordered_set.h b/src/util/lp/stacked_unordered_set.h index 69c4cf03b..88bb3160c 100644 --- a/src/util/lp/stacked_unordered_set.h +++ b/src/util/lp/stacked_unordered_set.h @@ -8,7 +8,7 @@ #include #include #include -namespace lean { +namespace lp { template , @@ -81,7 +81,7 @@ public: for (auto & t : d.m_erased) { m_set.insert(t); } - lean_assert(d.m_deb_copy == m_set); + lp_assert(d.m_deb_copy == m_set); m_stack.pop(); } } diff --git a/src/util/lp/stacked_value.h b/src/util/lp/stacked_value.h index 2a1e85be7..8cd43afce 100644 --- a/src/util/lp/stacked_value.h +++ b/src/util/lp/stacked_value.h @@ -6,7 +6,7 @@ #pragma once // add to value the stack semantics #include -namespace lean { +namespace lp { template class stacked_value { T m_value; std::stack m_stack; diff --git a/src/util/lp/stacked_vector.h b/src/util/lp/stacked_vector.h index 3f39dd346..4ed6f44d9 100644 --- a/src/util/lp/stacked_vector.h +++ b/src/util/lp/stacked_vector.h @@ -7,7 +7,7 @@ Author: Lev Nachmanson #include #include #include "util/vector.h" -namespace lean { +namespace lp { template < typename B> class stacked_vector { vector m_stack_of_vector_sizes; vector m_stack_of_change_sizes; @@ -19,7 +19,7 @@ public: unsigned m_i; public: ref(stacked_vector &m, unsigned key) :m_vec(m), m_i(key) { - lean_assert(key < m.size()); + lp_assert(key < m.size()); } ref & operator=(const B & b) { m_vec.emplace_replace(m_i, b); @@ -32,7 +32,10 @@ public: operator const B&() const { return m_vec.m_vector[m_i]; } - + + bool operator==(B const& other) const { + return m_vec.m_vector[m_i] == other; + } }; class ref_const { @@ -40,7 +43,7 @@ public: unsigned m_i; public: ref_const(const stacked_vector &m, unsigned key) :m_vec(m), m_i(key) { - lean_assert(key < m.size()); + lp_assert(key < m.size()); } operator const B&() const { @@ -68,7 +71,7 @@ public: /* const B & operator[](unsigned a) const { - lean_assert(a < m_vector.size()); + lp_assert(a < m_vector.size()); return m_vector[a]; } */ @@ -88,7 +91,7 @@ public: template void pop_tail(vector & v, unsigned k) { - lean_assert(v.size() >= k); + lp_assert(v.size() >= k); v.resize(v.size() - k); } @@ -98,8 +101,8 @@ public: } void pop(unsigned k) { - lean_assert(m_stack_of_vector_sizes.size() >= k); - lean_assert(k > 0); + lp_assert(m_stack_of_vector_sizes.size() >= k); + lp_assert(k > 0); resize(m_vector, m_stack_of_vector_sizes[m_stack_of_vector_sizes.size() - k]); pop_tail(m_stack_of_vector_sizes, k); unsigned first_change = m_stack_of_change_sizes[m_stack_of_change_sizes.size() - k]; @@ -119,15 +122,15 @@ public: return; delta & d = m_stack.back(); - lean_assert(m_vector.size() >= d.m_size); + lp_assert(m_vector.size() >= d.m_size); while (m_vector.size() > d.m_size) m_vector.pop_back(); for (auto & t : d.m_original_changed) { - lean_assert(t.first < m_vector.size()); + lp_assert(t.first < m_vector.size()); m_vector[t.first] = t.second; } - // lean_assert(d.m_deb_copy == m_vector); + // lp_assert(d.m_deb_copy == m_vector); m_stack.pop_back();*/ } @@ -157,7 +160,7 @@ public: } unsigned peek_size(unsigned k) const { - lean_assert(k > 0 && k <= m_stack_of_vector_sizes.size()); + lp_assert(k > 0 && k <= m_stack_of_vector_sizes.size()); return m_stack_of_vector_sizes[m_stack_of_vector_sizes.size() - k]; } diff --git a/src/util/lp/static_matrix.h b/src/util/lp/static_matrix.h index 5ef4b449f..74bcf17cf 100644 --- a/src/util/lp/static_matrix.h +++ b/src/util/lp/static_matrix.h @@ -13,7 +13,7 @@ #include "util/lp/permutation_matrix.h" #include "util/lp/linear_combination_iterator.h" #include -namespace lean { +namespace lp { struct column_cell { unsigned m_i; // points to the row @@ -203,7 +203,7 @@ public: virtual void set_number_of_columns(unsigned /*n*/) { } #endif - T get_max_val_in_row(unsigned /* i */) const { lean_unreachable(); } + T get_max_val_in_row(unsigned /* i */) const { lp_unreachable(); } T get_balance() const; @@ -219,7 +219,7 @@ public: for (auto & c : row) { unsigned j = c.m_j; auto & col = m_columns[j]; - lean_assert(col[col.size() - 1].m_i == m_rows.size() -1 ); // todo : start here!!!! + lp_assert(col[col.size() - 1].m_i == m_rows.size() -1 ); // todo : start here!!!! col.pop_back(); } } @@ -246,7 +246,7 @@ public: m_columns.pop_back(); // delete the last column m_stack.pop(); } - lean_assert(is_correct()); + lp_assert(is_correct()); } void multiply_row(unsigned row, T const & alpha) { @@ -262,7 +262,7 @@ public: } T dot_product_with_column(const vector & y, unsigned j) const { - lean_assert(j < column_count()); + lp_assert(j < column_count()); T ret = numeric_traits::zero(); for (auto & it : m_columns[j]) { ret += y[it.m_i] * get_val(it); // get_value_of_column_cell(it); @@ -281,20 +281,20 @@ public: // now fix the columns for (auto & rc : m_rows[i]) { column_cell & cc = m_columns[rc.m_j][rc.m_offset]; - lean_assert(cc.m_i == ii); + lp_assert(cc.m_i == ii); cc.m_i = i; } for (auto & rc : m_rows[ii]) { column_cell & cc = m_columns[rc.m_j][rc.m_offset]; - lean_assert(cc.m_i == i); + lp_assert(cc.m_i == i); cc.m_i = ii; } } void fill_last_row_with_pivoting(linear_combination_iterator & it, const vector & basis_heading) { - lean_assert(numeric_traits::precise()); - lean_assert(row_count() > 0); + lp_assert(numeric_traits::precise()); + lp_assert(row_count() > 0); m_work_vector.resize(column_count()); T a; unsigned j; @@ -332,13 +332,13 @@ public: alpha = zero_of_type(); m_work_vector.erase_from_index(j); } - lean_assert(m_work_vector.is_OK()); + lp_assert(m_work_vector.is_OK()); unsigned last_row = row_count() - 1; for (unsigned j : m_work_vector.m_index) { set (last_row, j, m_work_vector.m_data[j]); } - lean_assert(column_count() > 0); + lp_assert(column_count() > 0); set(last_row, column_count() - 1, one_of_type()); } @@ -354,7 +354,7 @@ public: template L dot_product_with_row(unsigned row, const vector & w) const { L ret = zero_of_type(); - lean_assert(row < m_rows.size()); + lp_assert(row < m_rows.size()); for (auto & it : m_rows[row]) { ret += w[it.m_j] * it.get_val(); } diff --git a/src/util/lp/static_matrix.hpp b/src/util/lp/static_matrix.hpp index fb12da8c4..1a88b567d 100644 --- a/src/util/lp/static_matrix.hpp +++ b/src/util/lp/static_matrix.hpp @@ -6,11 +6,11 @@ #include #include #include "util/lp/static_matrix.h" -namespace lean { +namespace lp { // each assignment for this matrix should be issued only once!!! template void static_matrix::init_row_columns(unsigned m, unsigned n) { - lean_assert(m_rows.size() == 0 && m_columns.size() == 0); + lp_assert(m_rows.size() == 0 && m_columns.size() == 0); for (unsigned i = 0; i < m; i++){ m_rows.push_back(row_strip()); } @@ -30,23 +30,23 @@ template void static_matrix::scan_row_ii_to_offse template bool static_matrix::pivot_row_to_row_given_cell(unsigned i, column_cell & c, unsigned pivot_col) { unsigned ii = c.m_i; - lean_assert(i < row_count() && ii < column_count()); - lean_assert(i != ii); + lp_assert(i < row_count() && ii < column_count()); + lp_assert(i != ii); m_became_zeros.reset(); T alpha = -get_val(c); - lean_assert(!is_zero(alpha)); + lp_assert(!is_zero(alpha)); auto & ii_row_vals = m_rows[ii]; remove_element(ii_row_vals, ii_row_vals[c.m_offset]); scan_row_ii_to_offset_vector(ii); - lean_assert(!is_zero(alpha)); + lp_assert(!is_zero(alpha)); unsigned prev_size_ii = ii_row_vals.size(); // run over the pivot row and update row ii for (const auto & iv : m_rows[i]) { unsigned j = iv.m_j; if (j == pivot_col) continue; T alv = alpha * iv.m_value; - lean_assert(!is_zero(iv.m_value)); + lp_assert(!is_zero(iv.m_value)); int j_offs = m_vector_of_row_offsets[j]; if (j_offs == -1) { // it is a new element add_new_element(ii, j, alv); @@ -104,9 +104,9 @@ template void static_matrix::init_empty_matrix } template unsigned static_matrix::lowest_row_in_column(unsigned col) { - lean_assert(col < column_count()); + lp_assert(col < column_count()); column_strip & colstrip = m_columns[col]; - lean_assert(colstrip.size() > 0); + lp_assert(colstrip.size() > 0); unsigned ret = 0; for (auto & t : colstrip) { if (t.m_i > ret) { @@ -122,7 +122,7 @@ template void static_matrix::add_columns_at_th } template void static_matrix::forget_last_columns(unsigned how_many_to_forget) { - lean_assert(m_columns.size() >= how_many_to_forget); + lp_assert(m_columns.size() >= how_many_to_forget); unsigned j = column_count() - 1; for (; how_many_to_forget > 0; how_many_to_forget--) { remove_last_column(j --); @@ -151,7 +151,7 @@ template void static_matrix::remove_last_column(u template void static_matrix::set(unsigned row, unsigned col, T const & val) { if (numeric_traits::is_zero(val)) return; - lean_assert(row < row_count() && col < column_count()); + lp_assert(row < row_count() && col < column_count()); auto & r = m_rows[row]; unsigned offs_in_cols = static_cast(m_columns[col].size()); m_columns[col].push_back(make_column_cell(row, static_cast(r.size()))); @@ -171,7 +171,7 @@ std::set> static_matrix::get_domain() { template void static_matrix::copy_column_to_indexed_vector (unsigned j, indexed_vector & v) const { - lean_assert(j < m_columns.size()); + lp_assert(j < m_columns.size()); for (auto & it : m_columns[j]) { const T& val = get_val(it); if (!is_zero(val)) @@ -240,7 +240,7 @@ template void static_matrix::check_consistency for (int i = 0; i < m_rows.size(); i++){ for (auto & t : m_rows[i]) { std::pair p(i, t.m_j); - lean_assert(by_rows.find(p) == by_rows.end()); + lp_assert(by_rows.find(p) == by_rows.end()); by_rows[p] = t.get_val(); } } @@ -248,11 +248,11 @@ template void static_matrix::check_consistency for (int i = 0; i < m_columns.size(); i++){ for (auto & t : m_columns[i]) { std::pair p(t.m_i, i); - lean_assert(by_cols.find(p) == by_cols.end()); + lp_assert(by_cols.find(p) == by_cols.end()); by_cols[p] = get_val(t); } } - lean_assert(by_rows.size() == by_cols.size()); + lp_assert(by_rows.size() == by_cols.size()); for (auto & t : by_rows) { auto ic = by_cols.find(t.first); @@ -260,8 +260,8 @@ template void static_matrix::check_consistency //std::cout << "rows have pair (" << t.first.first <<"," << t.first.second // << "), but columns don't " << std::endl; } - lean_assert(ic != by_cols.end()); - lean_assert(t.second == ic->second); + lp_assert(ic != by_cols.end()); + lp_assert(t.second == ic->second); } } #endif diff --git a/src/util/lp/static_matrix_instances.cpp b/src/util/lp/static_matrix_instances.cpp index d0e2045c0..85b547149 100644 --- a/src/util/lp/static_matrix_instances.cpp +++ b/src/util/lp/static_matrix_instances.cpp @@ -2,10 +2,11 @@ Copyright (c) 2017 Microsoft Corporation Author: Lev Nachmanson */ -#include "util/vector.h" #include +#include "util/vector.h" #include #include +#include "util/vector.h" #include "util/lp/static_matrix.hpp" #include "util/lp/lp_core_solver_base.h" #include "util/lp/lp_dual_core_solver.h" @@ -13,7 +14,7 @@ #include "util/lp/lp_primal_core_solver.h" #include "util/lp/scaler.h" #include "util/lp/lar_solver.h" -namespace lean { +namespace lp { template void static_matrix::add_columns_at_the_end(unsigned int); template void static_matrix::clear(); #ifdef LEAN_DEBUG @@ -23,8 +24,8 @@ template void static_matrix::copy_column_to_indexed_vector(unsig template double static_matrix::get_balance() const; template std::set> static_matrix::get_domain(); -template std::set> lean::static_matrix::get_domain(); -template std::set> lean::static_matrix >::get_domain(); +template std::set> lp::static_matrix::get_domain(); +template std::set> lp::static_matrix >::get_domain(); template double static_matrix::get_elem(unsigned int, unsigned int) const; template double static_matrix::get_max_abs_in_column(unsigned int) const; template double static_matrix::get_min_abs_in_column(unsigned int) const; @@ -60,10 +61,10 @@ template void static_matrix >::init_empty_matrix(unsigned template void static_matrix >::set(unsigned int, unsigned int, mpq const&); -template bool lean::static_matrix::pivot_row_to_row_given_cell(unsigned int, column_cell &, unsigned int); -template bool lean::static_matrix::pivot_row_to_row_given_cell(unsigned int, column_cell& , unsigned int); -template bool lean::static_matrix >::pivot_row_to_row_given_cell(unsigned int, column_cell&, unsigned int); -template void lean::static_matrix >::remove_element(vector, true, unsigned int>&, lean::row_cell&); +template bool lp::static_matrix::pivot_row_to_row_given_cell(unsigned int, column_cell &, unsigned int); +template bool lp::static_matrix::pivot_row_to_row_given_cell(unsigned int, column_cell& , unsigned int); +template bool lp::static_matrix >::pivot_row_to_row_given_cell(unsigned int, column_cell&, unsigned int); +template void lp::static_matrix >::remove_element(vector, true, unsigned int>&, lp::row_cell&); } diff --git a/src/util/lp/tail_matrix.h b/src/util/lp/tail_matrix.h index c337b0933..0e9c6320a 100644 --- a/src/util/lp/tail_matrix.h +++ b/src/util/lp/tail_matrix.h @@ -10,7 +10,7 @@ #include "util/lp/lp_settings.h" // These matrices appear at the end of the list -namespace lean { +namespace lp { template class tail_matrix #ifdef LEAN_DEBUG diff --git a/src/util/lp/test_bound_analyzer.h b/src/util/lp/test_bound_analyzer.h index 262c610c7..43ba244dc 100644 --- a/src/util/lp/test_bound_analyzer.h +++ b/src/util/lp/test_bound_analyzer.h @@ -16,7 +16,7 @@ // In the same loop trying to pin variables by pushing the partial sum up, denoting the variable related to it by _l // here in addition we assume that all coefficient in the row are positive -namespace lean { +namespace lp { class test_bound_analyzer { linear_combination_iterator & m_it; @@ -74,7 +74,7 @@ public : void analyze_i_for_upper(unsigned i) { mpq l; bool strict = false; - lean_assert(is_zero(l)); + lp_assert(is_zero(l)); for (unsigned k = 0; k < m_index.size(); k++) { if (k == i) continue; @@ -165,7 +165,7 @@ public : void analyze_i_for_lower(unsigned i) { mpq l; - lean_assert(is_zero(l)); + lp_assert(is_zero(l)); bool strict = false; for (unsigned k = 0; k < m_index.size(); k++) { if (k == i) diff --git a/src/util/lp/ul_pair.h b/src/util/lp/ul_pair.h index 2e77a7db0..1df20aa56 100644 --- a/src/util/lp/ul_pair.h +++ b/src/util/lp/ul_pair.h @@ -10,7 +10,7 @@ #include #include "util/lp/column_info.h" -namespace lean { +namespace lp { enum lconstraint_kind { LE = -2, LT = -1 , GE = 2, GT = 1, EQ = 0 diff --git a/src/util/mpq.h b/src/util/mpq.h index 474d38802..11e17bbf9 100644 --- a/src/util/mpq.h +++ b/src/util/mpq.h @@ -176,7 +176,7 @@ public: static bool is_small(mpz const & a) { return mpz_manager::is_small(a); } - static bool is_small(mpq const & a) { return is_small(a.m_num) && is_small(a.m_den); } + static bool is_small(mpq const & a) { return is_small(a.m_num) && is_small(a.m_den); } static mpq mk_q(int v) { return mpq(v); } @@ -786,6 +786,8 @@ public: unsigned bitsize(mpz const & a) { return mpz_manager::bitsize(a); } unsigned bitsize(mpq const & a) { return is_int(a) ? bitsize(a.m_num) : bitsize(a.m_num) + bitsize(a.m_den); } + unsigned storage_size(mpz const & a) { return mpz_manager::size_info(a); } + unsigned storage_size(mpq const & a) { return mpz_manager::size_info(a.m_num) + mpz_manager::size_info(a.m_den); } /** \brief Return true if the number is a perfect square, and diff --git a/src/util/mpz.h b/src/util/mpz.h index 67947b602..c02ac7c36 100644 --- a/src/util/mpz.h +++ b/src/util/mpz.h @@ -316,11 +316,11 @@ class mpz_manager { void big_rem(mpz const & a, mpz const & b, mpz & c); int big_compare(mpz const & a, mpz const & b); - + +public: unsigned size_info(mpz const & a); struct sz_lt; -public: static bool precise() { return true; } static bool field() { return false; } diff --git a/src/util/obj_hashtable.h b/src/util/obj_hashtable.h index 383ecaeb3..2720f1b00 100644 --- a/src/util/obj_hashtable.h +++ b/src/util/obj_hashtable.h @@ -70,6 +70,7 @@ public: m_value(v) { } Value const & get_value() const { return m_value; } + Key & get_key () const { return *m_key; } unsigned hash() const { return m_key->hash(); } bool operator==(key_data const & other) const { return m_key == other.m_key; } }; @@ -100,6 +101,8 @@ public: m_table(DEFAULT_HASHTABLE_INITIAL_CAPACITY) {} typedef typename table::iterator iterator; + typedef typename table::data data; + typedef typename table::entry entry; typedef Key key; typedef Value value; diff --git a/src/util/rational.h b/src/util/rational.h index 4fa3382ec..26ef7dbb1 100644 --- a/src/util/rational.h +++ b/src/util/rational.h @@ -68,6 +68,8 @@ public: mpq const & to_mpq() const { return m_val; } unsigned bitsize() const { return m().bitsize(m_val); } + + unsigned storage_size() const { return m().storage_size(m_val); } void reset() { m().reset(m_val); } diff --git a/src/util/scoped_vector.h b/src/util/scoped_vector.h index bacfbac89..f62fbc8a6 100644 --- a/src/util/scoped_vector.h +++ b/src/util/scoped_vector.h @@ -91,6 +91,31 @@ public: SASSERT(invariant()); } + class iterator { + scoped_vector const& m_vec; + unsigned m_index; + public: + iterator(scoped_vector const& v, unsigned idx): m_vec(v), m_index(idx) {} + + bool operator==(iterator const& other) const { return &other.m_vec == &m_vec && other.m_index == m_index; } + bool operator!=(iterator const& other) const { return &other.m_vec != &m_vec || other.m_index != m_index; } + T const& operator*() { return m_vec[m_index]; } + + iterator & operator++() { + ++m_index; + return *this; + } + + iterator operator++(int) { + iterator r = *this; + ++m_index; + return r; + } + }; + + iterator begin() { return iterator(*this, 0); } + iterator end() { return iterator(*this, m_size); } + void push_back(T const& t) { set_index(m_size, m_elems.size()); m_elems.push_back(t); diff --git a/src/util/stopwatch.h b/src/util/stopwatch.h index b1f6bba03..7a9066030 100644 --- a/src/util/stopwatch.h +++ b/src/util/stopwatch.h @@ -43,6 +43,8 @@ public: } ~stopwatch() {}; + + void add (const stopwatch &s) {/* TODO */} void reset() { m_elapsed.QuadPart = 0; } @@ -90,6 +92,8 @@ public: ~stopwatch() {} + void add (const stopwatch &s) {m_time += s.m_time;} + void reset() { m_time = 0ull; } @@ -141,6 +145,8 @@ public: ~stopwatch() {} + void add (const stopwatch &s) {m_time += s.m_time;} + void reset() { m_time = 0ull; } diff --git a/src/util/total_order.h b/src/util/total_order.h index 7238a5ef9..6fda88110 100644 --- a/src/util/total_order.h +++ b/src/util/total_order.h @@ -79,12 +79,7 @@ class total_order { } cell * to_cell(T const & a) const { - void * r; -#ifdef Z3DEBUG - bool ok = -#endif - m_map.find(a, r); - SASSERT(ok); + void * r = m_map.find(a); return reinterpret_cast(r); } diff --git a/src/util/uint_map.h b/src/util/uint_map.h index 13e0a9db3..0344de322 100644 --- a/src/util/uint_map.h +++ b/src/util/uint_map.h @@ -38,6 +38,11 @@ public: return v != 0; } } + + T * find(unsigned k) const { + SASSERT(k < m_map.size() && m_map[k] != 0); + return m_map[k]; + } void insert(unsigned k, T * v) { m_map.reserve(k+1);