diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000..e85dae524ad --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +**/*.swp +**/*.pyc +.git +**/*.Dockerfile diff --git a/.gitignore b/.gitignore index cc1c2a754ef..b7e4a0186b8 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 00000000000..e8e20746632 --- /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 b25139c1b38..c8ecb529521 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 ################################################################################ @@ -107,7 +109,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() @@ -120,7 +122,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() @@ -274,18 +276,6 @@ else() message(STATUS "Not using libgmp") endif() -################################################################################ -# FOCI2 support -################################################################################ -# FIXME: What is this? -option(USE_FOCI2 "Use FOCI2" OFF) -if (USE_FOCI2) - message(FATAL_ERROR "TODO") - message(STATUS "Using FOCI2") -else() - message(STATUS "Not using FOCI2") -endif() - ################################################################################ # OpenMP support ################################################################################ @@ -318,6 +308,23 @@ else() set(USE_OPENMP OFF CACHE BOOL "Use OpenMP" FORCE) endif() +################################################################################ +# API Log sync +################################################################################ +option(API_LOG_SYNC + "Use locking when logging Z3 API calls (experimental)" + OFF +) +if (API_LOG_SYNC) + if (NOT USE_OPENMP) + message(FATAL_ERROR "API_LOG_SYNC feature requires OpenMP") + endif() + list(APPEND Z3_COMPONENT_CXX_DEFINES "-DZ3_LOG_SYNC") + message(STATUS "Using API_LOG_SYNC") +else() + message(STATUS "Not using API_LOG_SYNC") +endif() + ################################################################################ # FP math ################################################################################ @@ -517,10 +524,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++") @@ -533,7 +548,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 abd2d3c8796..715cacad20f 100644 --- a/README-CMake.md +++ b/README-CMake.md @@ -1,4 +1,4 @@ - # Z3's CMake build system +# Z3's CMake build system [CMake](https://cmake.org/) is a "meta build system" that reads a description of the project written in the ``CMakeLists.txt`` files and emits a build @@ -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,6 +265,9 @@ 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. +* ``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. @@ -327,44 +302,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 @@ -446,3 +383,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 f92a5389a3f..197928877bd 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 357c17e782e..ec05160da34 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 00000000000..183f490dd9d --- /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 aa7f38825b4..f98aca2059c 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 100% rename from contrib/cmake/cmake/msvc_legacy_quirks.cmake rename to cmake/msvc_legacy_quirks.cmake 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 b90aa2fe7d2..b70838750fb 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 8bffd7de393..d2624d8908c 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 00000000000..d8a32edeabf --- /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 00000000000..c28e59e9705 --- /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 00000000000..98a5a3e097b --- /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 00000000000..2d16d539473 --- /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 00000000000..2e117c8b111 --- /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 00000000000..caa6798c66d --- /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 00000000000..76fd0fb841f --- /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 00000000000..5abc910e8ec --- /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 00000000000..7efdecdac9d --- /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 00000000000..0ef7b76aa74 --- /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 00000000000..6a65ffedd60 --- /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 00000000000..2eda3de7b88 --- /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 00000000000..804158f6f9d --- /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 00000000000..dfb1084a4e6 --- /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 00000000000..0d8e59b0fe4 --- /dev/null +++ b/contrib/ci/scripts/test_z3_unit_tests_cmake.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +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[@]}" +./test-z3 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 00000000000..41bde72301f --- /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 00000000000..84b2dd40037 --- /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 00000000000..03be8164760 --- /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 a3c81fb250c..dac08b38368 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 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 e02b28b2c59..00000000000 --- 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 17a8552d115..f8659ec0b2f 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 9e946aa7fc7..9c4b464c2e2 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 3fa49f9e037..ba7f6ee5909 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 20bb012b16a..64149a553cc 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -2152,6 +2152,31 @@ public static void FloatingPointExample2(Context ctx) 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 @@ static void Main(string[] args) 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 5810dab37f9..25076e27cbd 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -281,7 +281,7 @@ void prove(Context ctx, BoolExpr f, boolean useMBQI, } void disprove(Context ctx, BoolExpr f, boolean useMBQI) - throws TestFailedException + throws TestFailedException { BoolExpr[] a = {}; disprove(ctx, f, useMBQI, a); @@ -2279,6 +2279,29 @@ public void optimizeExample(Context ctx) 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 @@ public static void main(String[] args) 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 @@ public static void main(String[] args) 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 00000000000..b48e167eaf4 --- /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 eaf01482cae..a312e79ada0 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 fdbb7891f29..9bd45df41e1 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 d55017a5654..2169414516d 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 467d76c5596..3623b5f1e90 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 @@ def __pow__(self, k): 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 @@ def __div__(self, other): 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 @@ def evaluate_cexpr(m, e): 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 fd2d209dad1..c7b44c8a4d3 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 @@ def grow(self): 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 9255c6a8085..504e2acc835 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 @@ def visitor(e, seen): 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 98346f99f48..21771cc0490 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 ADD_PROBE(name, descr, cmd): '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 ADD_PROBE(name, descr, cmd): 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 ADD_PROBE(name, descr, cmd): # 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 cf6e8da9649..9614768ca8e 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 21e66b3ab04..a152eff148c 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 b56fcbcedd0..238595fa387 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 112e1f5ad0b..a5f75fd1cd7 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -96,8 +96,6 @@ def getenv(name, default): VER_REVISION=None PREFIX=sys.prefix GMP=False -FOCI2=False -FOCI2LIB='' VS_PAR=False VS_PAR_NUM=8 GPROF=False @@ -106,6 +104,8 @@ def getenv(name, default): SLOW_OPTIMIZE=False USE_OMP=True LOG_SYNC=False +GUARD_CF=False +ALWAYS_DYNAMIC_BASE=False FPMATH="Default" FPMATH_FLAGS="-mfpmath=sse -msse -msse2" @@ -257,13 +257,6 @@ def test_gmp(cc): t.commit() return exec_compiler_cmd([cc, CPPFLAGS, 'tstgmp.cpp', LDFLAGS, '-lgmp']) == 0 -def test_foci2(cc,foci2lib): - if is_verbose(): - print("Testing FOCI2...") - t = TempFile('tstfoci2.cpp') - t.add('#include\nint main() { foci2 *f = foci2::create("lia"); return 0; }\n') - t.commit() - return exec_compiler_cmd([cc, CPPFLAGS, '-Isrc/interp', 'tstfoci2.cpp', LDFLAGS, foci2lib]) == 0 def test_openmp(cc): if not USE_OMP: @@ -632,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 .") @@ -650,7 +643,6 @@ def display_help(exit_code): if not IS_WINDOWS: print(" -g, --gmp use GMP.") print(" --gprof enable gprof") - print(" -f --foci2= use foci2 library at path") print(" --noomp disable OpenMP and all features that require it.") print(" --log-sync synchronize access to API log files to enable multi-thread API logging.") print("") @@ -678,13 +670,14 @@ def display_help(exit_code): # Parse configuration option for mk_make script 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, FOCI2, FOCI2LIB, PYTHON_PACKAGE_DIR, GPROF, GIT_HASH, GIT_DESCRIBE, PYTHON_INSTALL_ENABLED, PYTHON_ENABLED + 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', - 'trace', 'dotnet', 'dotnet-key=', 'staticlib', 'prefix=', 'gmp', 'foci2=', 'java', 'parallel=', 'gprof', + ['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: print("ERROR: Invalid command line option") @@ -735,9 +728,6 @@ def parse_options(): VS_PAR_NUM = int(arg) elif opt in ('-g', '--gmp'): GMP = True - elif opt in ('-f', '--foci2'): - FOCI2 = True - FOCI2LIB = arg elif opt in ('-j', '--java'): JAVA_ENABLED = True elif opt == '--gprof': @@ -755,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) @@ -1181,7 +1174,6 @@ def mk_makefile(self, out): for dep in deps: c_dep = get_component(dep) out.write(' ' + c_dep.get_link_name()) - out.write(' ' + FOCI2LIB) out.write(' $(LINK_EXTRA_FLAGS)\n') out.write('%s: %s\n\n' % (self.name, exefile)) @@ -1307,7 +1299,6 @@ def mk_makefile(self, out): if dep not in self.reexports: c_dep = get_component(dep) out.write(' ' + c_dep.get_link_name()) - out.write(' ' + FOCI2LIB) out.write(' $(SLINK_EXTRA_FLAGS)') if IS_WINDOWS: out.write(' /DEF:%s.def' % os.path.join(self.to_src_dir, self.name)) @@ -2307,7 +2298,7 @@ def mk_config(): if ONLY_MAKEFILES: return config = open(os.path.join(BUILD_DIR, 'config.mk'), 'w') - global CXX, CC, GMP, FOCI2, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG, FPMATH_FLAGS, HAS_OMP, LOG_SYNC + global CXX, CC, GMP, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG, FPMATH_FLAGS, HAS_OMP, LOG_SYNC if IS_WINDOWS: config.write( 'CC=cl\n' @@ -2325,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' @@ -2334,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( @@ -2348,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) @@ -2357,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 '' @@ -2373,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) @@ -2382,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)) @@ -2417,14 +2413,6 @@ def mk_config(): SLIBEXTRAFLAGS = '%s -lgmp' % SLIBEXTRAFLAGS else: CPPFLAGS = '%s -D_MP_INTERNAL' % CPPFLAGS - if FOCI2: - if test_foci2(CXX,FOCI2LIB): - LDFLAGS = '%s %s' % (LDFLAGS,FOCI2LIB) - SLIBEXTRAFLAGS = '%s %s' % (SLIBEXTRAFLAGS,FOCI2LIB) - CPPFLAGS = '%s -D_FOCI2' % CPPFLAGS - else: - print("FAILED\n") - FOCI2 = False if GIT_HASH: CPPFLAGS = '%s -DZ3GITHASH=%s' % (CPPFLAGS, GIT_HASH) CXXFLAGS = '%s -std=c++11' % CXXFLAGS @@ -2735,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)) @@ -2758,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)) @@ -2776,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/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 93529ae1286..3ce7f97cc4b 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 8e796168f40..79c5fc1c955 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 c9cdc6ab34b..d34cad2f487 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; @@ -1124,6 +1129,20 @@ extern "C" { case OP_SEQ_TO_RE: return Z3_OP_SEQ_TO_RE; case OP_SEQ_IN_RE: return Z3_OP_SEQ_IN_RE; + case _OP_STRING_STRREPL: return Z3_OP_SEQ_REPLACE; + case _OP_STRING_CONCAT: return Z3_OP_SEQ_CONCAT; + case _OP_STRING_LENGTH: return Z3_OP_SEQ_LENGTH; + case _OP_STRING_STRCTN: return Z3_OP_SEQ_CONTAINS; + case _OP_STRING_PREFIX: return Z3_OP_SEQ_PREFIX; + case _OP_STRING_SUFFIX: return Z3_OP_SEQ_SUFFIX; + case _OP_STRING_IN_REGEXP: return Z3_OP_SEQ_IN_RE; + case _OP_STRING_TO_REGEXP: return Z3_OP_SEQ_TO_RE; + case _OP_STRING_CHARAT: return Z3_OP_SEQ_AT; + case _OP_STRING_SUBSTR: return Z3_OP_SEQ_EXTRACT; + case _OP_STRING_STRIDOF: return Z3_OP_SEQ_INDEX; + case _OP_REGEXP_EMPTY: return Z3_OP_RE_EMPTY_SET; + case _OP_REGEXP_FULL: return Z3_OP_RE_FULL_SET; + case OP_STRING_STOI: return Z3_OP_STR_TO_INT; case OP_STRING_ITOS: return Z3_OP_INT_TO_STR; diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index 9d998252388..42db6f35254 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 2ffaaa66107..c7ca1851ebd 100644 --- a/src/api/dotnet/AST.cs +++ b/src/api/dotnet/AST.cs @@ -14,7 +14,7 @@ Christoph Wintersteiger (cwinter) 2012-03-16 Notes: - + --*/ using System; @@ -25,7 +25,7 @@ Christoph Wintersteiger (cwinter) 2012-03-16 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 @@ public class AST : Z3Object, IComparable /// /// 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 @@ public class AST : Z3Object, IComparable /// /// 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 @@ public AST Translate(Context ctx) 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 @@ internal override void DecRef(Context ctx, IntPtr obj) { 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 cac62d2f0db..6c52b83c86c 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -163,13 +163,7 @@ public Expr SubstituteVars(Expr[] to) /// 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); } /// @@ -797,6 +791,77 @@ public bool IsBV public bool IsLabelLit { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_LABEL_LIT; } } #endregion + #region Sequences and Strings + + /// + /// Check whether expression is a string constant. + /// + /// a Boolean + public bool IsString { get { return IsApp && 0 != Native.Z3_is_string(Context.nCtx, NativeObject); } } + + /// + /// 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); } } + + /// + /// 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 + #region Proof Terms /// /// Indicates whether the term is a binary equivalence modulo namings. diff --git a/src/api/dotnet/FuncDecl.cs b/src/api/dotnet/FuncDecl.cs index 2f5cd0ce84c..0587a2276e1 100644 --- a/src/api/dotnet/FuncDecl.cs +++ b/src/api/dotnet/FuncDecl.cs @@ -14,7 +14,7 @@ Christoph Wintersteiger (cwinter) 2012-03-16 Notes: - + --*/ using System; @@ -23,7 +23,7 @@ Christoph Wintersteiger (cwinter) 2012-03-16 namespace Microsoft.Z3 { /// - /// Function declarations. + /// Function declarations. /// [ContractVerification(true)] public class FuncDecl : AST @@ -62,7 +62,7 @@ public override bool Equals(object o) /// /// A hash code. - /// + /// public override int GetHashCode() { return base.GetHashCode(); @@ -205,7 +205,7 @@ public Parameter[] Parameters } /// - /// Function declarations can have Parameters associated with them. + /// Function declarations can have Parameters associated with them. /// public class Parameter { @@ -315,6 +315,17 @@ internal override void CheckNativeObject(IntPtr obj) #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 @@ public Expr Apply(params Expr[] args) Context.CheckContextMatch(args); return Expr.Create(Context, this, args); } - } } diff --git a/src/api/dotnet/Model.cs b/src/api/dotnet/Model.cs index a7f62e6e8ba..12992fa8adf 100644 --- a/src/api/dotnet/Model.cs +++ b/src/api/dotnet/Model.cs @@ -19,6 +19,7 @@ Christoph Wintersteiger (cwinter) 2012-03-21 using System; using System.Diagnostics.Contracts; +using System.Collections.Generic; namespace Microsoft.Z3 { @@ -131,6 +132,24 @@ public FuncDecl[] ConstDecls } } + /// + /// Enumerate constants in model. + /// + public IEnumerable> Consts + { + get + { + uint nc = NumConsts; + for (uint i = 0; i < nc; ++i) + { + var f = new FuncDecl(Context, Native.Z3_model_get_const_decl(Context.nCtx, NativeObject, i)); + IntPtr n = Native.Z3_model_get_const_interp(Context.nCtx, NativeObject, f.NativeObject); + if (n == IntPtr.Zero) continue; + yield return new KeyValuePair(f, Expr.Create(Context, n)); + } + } + } + /// /// The number of function interpretations in the model. /// diff --git a/src/api/dotnet/Quantifier.cs b/src/api/dotnet/Quantifier.cs index eb21ed2b995..eca4e3c7ee4 100644 --- a/src/api/dotnet/Quantifier.cs +++ b/src/api/dotnet/Quantifier.cs @@ -14,7 +14,7 @@ Christoph Wintersteiger (cwinter) 2012-03-19 Notes: - + --*/ using System; @@ -157,6 +157,16 @@ public BoolExpr Body } } + /// + /// 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 e1b8ca1b7f2..e6f19543425 100644 --- a/src/api/dotnet/Sort.cs +++ b/src/api/dotnet/Sort.cs @@ -14,7 +14,7 @@ Christoph Wintersteiger (cwinter) 2012-03-15 Notes: - + --*/ using System; @@ -33,7 +33,7 @@ public class Sort : AST /// /// 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 @@ public class Sort : AST /// /// 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 @@ public override string ToString() 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 @@ internal override void CheckNativeObject(IntPtr obj) } } #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 e1cde837f5e..350830443f3 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -87,12 +87,10 @@ public int getId() **/ 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 db7a0871184..2609dbb297a 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -25,6 +25,12 @@ /** * 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 ea3fd2147e6..6cabbb1b8c7 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -126,7 +126,7 @@ public Expr update(Expr[] args) if (isApp() && args.length != getNumArgs()) { throw new Z3Exception("Number of arguments does not match"); } - return new Expr(getContext(), Native.updateTerm(getContext().nCtx(), getNativeObject(), + return Expr.create(getContext(), Native.updateTerm(getContext().nCtx(), getNativeObject(), args.length, Expr.arrayToNative(args))); } @@ -194,14 +194,7 @@ public Expr substituteVars(Expr[] to) **/ 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); } /** @@ -1277,6 +1270,35 @@ public boolean isLabelLit() return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_LABEL_LIT; } + /** + * Check whether expression is a string constant. + * @return a boolean + */ + public boolean isString() + { + return isApp() && Native.isString(getContext().nCtx(), getNativeObject()); + } + + /** + * Retrieve string corresponding to string constant. + * Remark: the expression should be a string constant, (isString() should return true). + * @throws Z3Exception on error + * @return a string + */ + public String getString() + { + 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 ad6d5a65842..7bb0fda58ef 100644 --- a/src/api/java/Fixedpoint.java +++ b/src/api/java/Fixedpoint.java @@ -88,6 +88,7 @@ public void registerRelation(FuncDecl f) /** * 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 void pop() { /** * 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 273e853c007..255bc2c4a1d 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 Christoph Wintersteiger (cwinter) 2012-03-15 Notes: - -**/ + +**/ package com.microsoft.z3; @@ -59,6 +59,18 @@ public int getId() 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 int getArity() } /** - * 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 Z3_parameter_kind getParameterKind() } 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 Z3_parameter_kind getParameterKind() } 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 @@ void checkNativeObject(long obj) } /** - * 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 bc253710768..ce2adce2123 100644 --- a/src/api/java/Quantifier.java +++ b/src/api/java/Quantifier.java @@ -145,6 +145,19 @@ public BoolExpr getBody() .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 0763a69a311..e7a186ad289 100644 --- a/src/api/java/Sort.java +++ b/src/api/java/Sort.java @@ -87,6 +87,19 @@ public String toString() { 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 b4cdf834b82..a16c1b92bd8 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 @@ import sys import io import math +import copy if sys.version < '3': def _is_int(v): @@ -288,6 +289,9 @@ def __del__(self): 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 @@ def __bool__(self): 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() @@ -1300,8 +1304,10 @@ def cast(self, val): if isinstance(val, bool): return BoolVal(val, self.ctx) if __debug__: - _z3_assert(is_expr(val), "True, False or Z3 Boolean expression expected. Received %s" % val) - _z3_assert(self.eq(val.sort()), "Value cannot be converted into a Z3 Boolean value") + if not is_expr(val): + _z3_assert(is_expr(val), "True, False or Z3 Boolean expression expected. Received %s" % val) + if not self.eq(val.sort()): + _z3_assert(self.eq(val.sort()), "Value cannot be converted into a Z3 Boolean value") return val def subsort(self, other): @@ -4355,6 +4361,11 @@ def __init__(self, name, ctx=None): 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") @@ -4645,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) @@ -4709,6 +4726,9 @@ def __init__(self, descr, ctx=None): 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) @@ -4770,6 +4790,9 @@ def __init__(self, models=True, unsat_cores=False, proofs=False, ctx=None, goal= 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) @@ -5032,6 +5055,9 @@ def __init__(self, v=None, ctx=None): 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) @@ -5167,6 +5193,9 @@ def __init__(self, m=None, ctx=None): 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) @@ -5282,6 +5311,9 @@ def __init__(self, entry, ctx): 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) @@ -5388,6 +5420,9 @@ def __init__(self, f, ctx): 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) @@ -5498,6 +5533,9 @@ def __init__(self, m, ctx): 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) @@ -5774,6 +5812,9 @@ def __init__(self, stats, ctx): 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) @@ -5908,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 @@ -5947,6 +5991,9 @@ def __init__(self, solver=None, ctx=None): 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) @@ -6007,6 +6054,24 @@ def pop(self, num=1): """ 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()`. @@ -6367,6 +6432,9 @@ def __init__(self, fixedpoint=None, ctx=None): 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) @@ -6741,6 +6809,9 @@ def __init__(self, ctx=None): 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) @@ -6893,6 +6964,9 @@ def __init__(self, result, ctx): 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) @@ -7021,6 +7095,9 @@ def __init__(self, tactic, ctx=None): 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) @@ -7293,6 +7370,9 @@ def __init__(self, probe, ctx=None): 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 45065f85658..8d53c925505 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 795b4b8fdfb..f49e1b9ceb5 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 beb227c33ff..6d6da9ed5e7 100644 --- a/src/ast/arith_decl_plugin.h +++ b/src/ast/arith_decl_plugin.h @@ -275,7 +275,9 @@ class arith_recognizers { 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 6bb3b01c9e7..f71d5135ce7 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -667,6 +667,8 @@ class app : public expr { 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 @@ class ast_manager { 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 @@ class ast_manager { 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_pp_util.cpp b/src/ast/ast_pp_util.cpp index f953dbf0e0e..3021b702ba6 100644 --- a/src/ast/ast_pp_util.cpp +++ b/src/ast/ast_pp_util.cpp @@ -44,8 +44,11 @@ void ast_pp_util::display_decls(std::ostream& out) { } n = coll.get_num_decls(); for (unsigned i = 0; i < n; ++i) { - ast_smt2_pp(out, coll.get_func_decls()[i], env); - out << "\n"; + func_decl* f = coll.get_func_decls()[i]; + if (f->get_family_id() == null_family_id) { + ast_smt2_pp(out, f, env); + out << "\n"; + } } } diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index 89af8bd3ef3..d5e46548a69 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -557,7 +557,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 +891,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/bv_decl_plugin.cpp b/src/ast/bv_decl_plugin.cpp index 03b4fe637f7..321943c729e 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 8ad33d6fc7d..4d531d2db36 100644 --- a/src/ast/datatype_decl_plugin.cpp +++ b/src/ast/datatype_decl_plugin.cpp @@ -935,9 +935,9 @@ bool datatype_util::is_recursive(sort * ty) { bool datatype_util::is_enum_sort(sort* s) { - if (!is_datatype(s)) { - return false; - } + if (!is_datatype(s)) { + return false; + } bool r = false; if (m_is_enum.find(s, r)) return r; diff --git a/src/ast/expr_map.h b/src/ast/expr_map.h index ddd94ea1376..2b49a4a3099 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 @@ class expr_map { 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 2c0ba1ce15a..99b8c5ac805 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/src/ast/fpa/fpa2bv_rewriter.cpp b/src/ast/fpa/fpa2bv_rewriter.cpp index 725c0b043ef..32b62342b43 100644 --- a/src/ast/fpa/fpa2bv_rewriter.cpp +++ b/src/ast/fpa/fpa2bv_rewriter.cpp @@ -143,11 +143,11 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co case OP_FPA_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE; case OP_FPA_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE; case OP_FPA_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE; - case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED: m_conv.mk_to_ubv_unspecified(f, num, args, result); return BR_DONE; + case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED: m_conv.mk_to_ubv_unspecified(f, num, args, result); return BR_DONE; case OP_FPA_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE; - case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: m_conv.mk_to_sbv_unspecified(f, num, args, result); return BR_DONE; + case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: m_conv.mk_to_sbv_unspecified(f, num, args, result); return BR_DONE; case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE; - case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED: m_conv.mk_to_real_unspecified(f, num, args, result); return BR_DONE; + case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED: m_conv.mk_to_real_unspecified(f, num, args, result); return BR_DONE; case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED: m_conv.mk_to_ieee_bv_unspecified(f, num, args, result); return BR_DONE; 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 30702cd8c0f..69288d92bf4 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 59e0545a1d1..6e8301afc2c 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.cpp b/src/ast/pb_decl_plugin.cpp index 09f020ca6b2..28f8897390a 100644 --- a/src/ast/pb_decl_plugin.cpp +++ b/src/ast/pb_decl_plugin.cpp @@ -91,7 +91,7 @@ func_decl * pb_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p } void pb_decl_plugin::get_op_names(svector & op_names, symbol const & logic) { - if (logic == symbol::null || logic == "QF_FD") { + if (logic == symbol::null || logic == "QF_FD" || logic == "ALL") { op_names.push_back(builtin_name(m_at_most_sym.bare_str(), OP_AT_MOST_K)); op_names.push_back(builtin_name(m_at_least_sym.bare_str(), OP_AT_LEAST_K)); op_names.push_back(builtin_name(m_pble_sym.bare_str(), OP_PB_LE)); diff --git a/src/ast/pb_decl_plugin.h b/src/ast/pb_decl_plugin.h index 0750dcac7a5..36b1a951230 100644 --- a/src/ast/pb_decl_plugin.h +++ b/src/ast/pb_decl_plugin.h @@ -109,6 +109,7 @@ class pb_util { 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 97% rename from contrib/cmake/src/ast/rewriter/CMakeLists.txt rename to src/ast/rewriter/CMakeLists.txt index 74fddd2bb2c..abf09ff0c4c 100644 --- a/contrib/cmake/src/ast/rewriter/CMakeLists.txt +++ b/src/ast/rewriter/CMakeLists.txt @@ -8,6 +8,7 @@ z3_add_component(rewriter bv_rewriter.cpp datatype_rewriter.cpp der.cpp + distribute_forall.cpp dl_rewriter.cpp enum2bv_rewriter.cpp expr_replacer.cpp diff --git a/src/ast/rewriter/arith_rewriter.cpp b/src/ast/rewriter/arith_rewriter.cpp index fa3d6960291..b00e1eb6db2 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/simplifier/distribute_forall.cpp b/src/ast/rewriter/distribute_forall.cpp similarity index 92% rename from src/ast/simplifier/distribute_forall.cpp rename to src/ast/rewriter/distribute_forall.cpp index 78e5d5ded88..c64c0f08972 100644 --- a/src/ast/simplifier/distribute_forall.cpp +++ b/src/ast/rewriter/distribute_forall.cpp @@ -20,12 +20,12 @@ Revision History: --*/ #include"var_subst.h" #include"ast_ll_pp.h" - +#include"ast_util.h" #include"distribute_forall.h" +#include"bool_rewriter.h" -distribute_forall::distribute_forall(ast_manager & m, basic_simplifier_plugin & p) : +distribute_forall::distribute_forall(ast_manager & m) : m_manager(m), - m_bsimp(p), m_cache(m) { } @@ -109,6 +109,8 @@ void distribute_forall::reduce1_quantifier(quantifier * q) { expr * e = get_cached(q->get_expr()); if (m_manager.is_not(e) && m_manager.is_or(to_app(e)->get_arg(0))) { + bool_rewriter br(m_manager); + // found target for simplification // (forall X (not (or F1 ... Fn))) // --> @@ -121,8 +123,7 @@ void distribute_forall::reduce1_quantifier(quantifier * q) { for (unsigned i = 0; i < num_args; i++) { expr * arg = or_e->get_arg(i); expr_ref not_arg(m_manager); - // m_bsimp.mk_not applies basic simplifications. For example, if arg is of the form (not a), then it will return a. - m_bsimp.mk_not(arg, not_arg); + br.mk_not(arg, not_arg); quantifier_ref tmp_q(m_manager); tmp_q = m_manager.update_quantifier(q, not_arg); expr_ref new_q(m_manager); @@ -132,7 +133,7 @@ void distribute_forall::reduce1_quantifier(quantifier * q) { expr_ref result(m_manager); // m_bsimp.mk_and actually constructs a (not (or ...)) formula, // it will also apply basic simplifications. - m_bsimp.mk_and(new_args.size(), new_args.c_ptr(), result); + br.mk_and(new_args.size(), new_args.c_ptr(), result); cache_result(q, result); } else { diff --git a/src/ast/simplifier/distribute_forall.h b/src/ast/rewriter/distribute_forall.h similarity index 90% rename from src/ast/simplifier/distribute_forall.h rename to src/ast/rewriter/distribute_forall.h index 4c2eefb56d5..b2c239239de 100644 --- a/src/ast/simplifier/distribute_forall.h +++ b/src/ast/rewriter/distribute_forall.h @@ -22,7 +22,6 @@ Revision History: #define DISTRIBUTE_FORALL_H_ #include"ast.h" -#include"basic_simplifier_plugin.h" #include"act_cache.h" /** @@ -47,7 +46,6 @@ Revision History: class distribute_forall { typedef act_cache expr_map; ast_manager & m_manager; - basic_simplifier_plugin & m_bsimp; // useful for constructing formulas and/or/not in simplified form. ptr_vector m_todo; expr_map m_cache; ptr_vector m_new_args; @@ -57,7 +55,7 @@ class distribute_forall { public: - distribute_forall(ast_manager & m, basic_simplifier_plugin & p); + distribute_forall(ast_manager & m); /** \brief Apply the distribute_forall transformation (when possible) to all universal quantifiers in \c f. diff --git a/src/ast/rewriter/pb_rewriter.cpp b/src/ast/rewriter/pb_rewriter.cpp index 0fdbc858d9e..b14d350b16e 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/src/ast/rewriter/seq_rewriter.cpp b/src/ast/rewriter/seq_rewriter.cpp index dc1931bac22..ce707b1080a 100644 --- a/src/ast/rewriter/seq_rewriter.cpp +++ b/src/ast/rewriter/seq_rewriter.cpp @@ -92,25 +92,25 @@ class sym_expr_boolean_algebra : public boolean_algebra { expr_ref fml(m.mk_true(), m); return sym_expr::mk_pred(fml, m.mk_bool_sort()); } - virtual T mk_and(T x, T y) { - if (x->is_char() && y->is_char()) { - if (x->get_char() == y->get_char()) { - return x; - } - if (m.are_distinct(x->get_char(), y->get_char())) { - expr_ref fml(m.mk_false(), m); - return sym_expr::mk_pred(fml, x->get_sort()); - } - } - - sort* s = x->get_sort(); - if (m.is_bool(s)) s = y->get_sort(); - var_ref v(m.mk_var(0, s), m); - expr_ref fml1 = x->accept(v); - expr_ref fml2 = y->accept(v); - if (m.is_true(fml1)) { - return y; - } + virtual T mk_and(T x, T y) { + if (x->is_char() && y->is_char()) { + if (x->get_char() == y->get_char()) { + return x; + } + if (m.are_distinct(x->get_char(), y->get_char())) { + expr_ref fml(m.mk_false(), m); + return sym_expr::mk_pred(fml, x->get_sort()); + } + } + + sort* s = x->get_sort(); + if (m.is_bool(s)) s = y->get_sort(); + var_ref v(m.mk_var(0, s), m); + expr_ref fml1 = x->accept(v); + expr_ref fml2 = y->accept(v); + if (m.is_true(fml1)) { + return y; + } if (m.is_true(fml2)) return x; expr_ref fml(m.mk_and(fml1, fml2), m); return sym_expr::mk_pred(fml, x->get_sort()); @@ -178,10 +178,10 @@ class sym_expr_boolean_algebra : public boolean_algebra { return sym_expr::mk_pred(fml, x->get_sort()); } - /*virtual vector, T>> generate_min_terms(vector constraints){ - - return 0; - }*/ + /*virtual vector, T>> generate_min_terms(vector constraints){ + + return 0; + }*/ }; re2automaton::re2automaton(ast_manager& m): m(m), u(m), bv(m), m_ba(0), m_sa(0) {} diff --git a/contrib/cmake/src/ast/simplifier/CMakeLists.txt b/src/ast/simplifier/CMakeLists.txt similarity index 96% rename from contrib/cmake/src/ast/simplifier/CMakeLists.txt rename to src/ast/simplifier/CMakeLists.txt index 7597374a614..9575c5c89c9 100644 --- a/contrib/cmake/src/ast/simplifier/CMakeLists.txt +++ b/src/ast/simplifier/CMakeLists.txt @@ -10,7 +10,6 @@ z3_add_component(simplifier bv_simplifier_params.cpp bv_simplifier_plugin.cpp datatype_simplifier_plugin.cpp - distribute_forall.cpp elim_bounds.cpp fpa_simplifier_plugin.cpp inj_axiom.cpp diff --git a/src/ast/static_features.cpp b/src/ast/static_features.cpp index daf20e09578..a3ad7fd075e 100644 --- a/src/ast/static_features.cpp +++ b/src/ast/static_features.cpp @@ -391,7 +391,7 @@ void static_features::process(expr * e, bool form_ctx, bool or_and_ctx, bool ite if (is_marked(e)) { m_num_sharing++; return; - } + } if (stack_depth > m_max_stack_depth) { return; } 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 eea1938a6ad..f741d3fd4e6 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 8b2d10eec0e..f7b88834346 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 f09d351580a..ea6d1c23212 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 @@ class help_cmd : public cmd { } 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 @@ class get_model_cmd : public cmd { 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); @@ -198,20 +205,21 @@ ATOMIC_CMD(get_proof_cmd, "get-proof", "retrieve proof", { } }); -#define PRINT_CORE() \ - 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; \ +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; +} ATOMIC_CMD(get_unsat_core_cmd, "get-unsat-core", "retrieve unsat core", { if (!ctx.produce_unsat_cores()) @@ -219,7 +227,7 @@ ATOMIC_CMD(get_unsat_core_cmd, "get-unsat-core", "retrieve unsat core", { if (!ctx.has_manager() || ctx.cs_state() != cmd_context::css_unsat) throw cmd_exception("unsat core is not available"); - PRINT_CORE(); + print_core(ctx); }); ATOMIC_CMD(get_unsat_assumptions_cmd, "get-unsat-assumptions", "retrieve subset of assumptions sufficient for unsatisfiability", { @@ -228,7 +236,7 @@ ATOMIC_CMD(get_unsat_assumptions_cmd, "get-unsat-assumptions", "retrieve subset if (!ctx.has_manager() || ctx.cs_state() != cmd_context::css_unsat) { throw cmd_exception("unsat assumptions is not available"); } - PRINT_CORE(); + print_core(ctx); }); @@ -250,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 { @@ -261,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 { @@ -297,18 +307,18 @@ class set_get_option_cmd : public cmd { 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"), @@ -340,7 +350,7 @@ class set_get_option_cmd : public cmd { 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"); @@ -361,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); @@ -458,11 +468,11 @@ class set_option_cmd : public set_get_option_cmd { 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; } @@ -517,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; } @@ -534,11 +544,11 @@ class get_option_cmd : public set_get_option_cmd { 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, ); // } @@ -622,13 +632,13 @@ class get_info_cmd : public cmd { m_status(":status"), m_reason_unknown(":reason-unknown"), m_all_statistics(":all-statistics"), - m_assertion_stack_levels("assertion-stack-levels") { + m_assertion_stack_levels(":assertion-stack-levels") { } virtual char const * get_usage() const { return ""; } 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; @@ -652,7 +662,7 @@ class get_info_cmd : public cmd { ctx.regular_stream() << "(:status " << ctx.get_status() << ")" << std::endl; } else if (opt == m_reason_unknown) { - ctx.regular_stream() << "(:reason-unknown \"" << ctx.reason_unknown() << "\")" << std::endl; + ctx.regular_stream() << "(:reason-unknown \"" << escaped(ctx.reason_unknown().c_str()) << "\")" << std::endl; } else if (opt == m_all_statistics) { ctx.display_statistics(); @@ -684,12 +694,12 @@ class set_info_cmd : public cmd { 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; } @@ -737,7 +747,7 @@ class declare_map_cmd : public cmd { 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; @@ -748,10 +758,10 @@ class declare_map_cmd : public cmd { 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; @@ -790,7 +800,7 @@ class get_consequences_cmd : public cmd { 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; @@ -850,11 +860,9 @@ 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(builtin_cmd, "define-fun-rec", "hfun-defi", "define a function satisfying recursive equations")); - // ctx.insert(alloc(builtin_cmd, "define-funs-rec", "( hfun_decin+1 ) ( htermin+1 )", "define multiple mutually recursive functions")); - // ctx.insert(alloc(get_unsat_assumptions_cmd)); + 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 f590725a7cb..a053fc8e6fa 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -15,6 +15,7 @@ Module Name: 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) { @@ -325,6 +334,7 @@ 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_processing_pareto(false), m_exit_on_error(false), m_manager(m), m_own_manager(m == 0), @@ -529,10 +539,6 @@ bool cmd_context::logic_has_fpa() const { return !has_logic() || smt_logics::logic_has_fpa(m_logic); } -bool cmd_context::logic_has_str() const { - return !has_logic() || m_logic == "QF_S"; -} - bool cmd_context::logic_has_array() const { return !has_logic() || smt_logics::logic_has_array(m_logic); } @@ -637,7 +643,7 @@ bool cmd_context::set_logic(symbol const & s) { std::string cmd_context::reason_unknown() const { if (m_check_sat_result.get() == 0) - throw cmd_exception("state of the most recent check-sat command is not known"); + return "state of the most recent check-sat command is not known"; return m_check_sat_result->reason_unknown(); } @@ -1130,6 +1136,7 @@ void cmd_context::insert_aux_pdecl(pdecl * p) { } void cmd_context::reset(bool finalize) { + m_processing_pareto = false; m_logic = symbol::null; m_check_sat_result = 0; m_numeral_as_real = false; @@ -1174,6 +1181,7 @@ void cmd_context::reset(bool finalize) { } void cmd_context::assert_expr(expr * t) { + m_processing_pareto = false; if (!m_check_logic(t)) throw cmd_exception(m_check_logic.get_last_error()); m_check_sat_result = 0; @@ -1186,6 +1194,7 @@ void cmd_context::assert_expr(expr * t) { } void cmd_context::assert_expr(symbol const & name, expr * t) { + m_processing_pareto = false; if (!m_check_logic(t)) throw cmd_exception(m_check_logic.get_last_error()); if (!produce_unsat_cores() || name == symbol::null) { @@ -1286,6 +1295,7 @@ static void restore(ast_manager & m, ptr_vector & c, unsigned old_sz) { } void cmd_context::restore_assertions(unsigned old_sz) { + m_processing_pareto = false; if (!has_manager()) { // restore_assertions invokes m(), so if cmd_context does not have a manager, it will try to create one. SASSERT(old_sz == m_assertions.size()); @@ -1303,6 +1313,7 @@ void cmd_context::restore_assertions(unsigned old_sz) { void cmd_context::pop(unsigned n) { m_check_sat_result = 0; + m_processing_pareto = false; if (n == 0) return; unsigned lvl = m_scopes.size(); @@ -1333,7 +1344,7 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions unsigned rlimit = m_params.m_rlimit; scoped_watch sw(*this); lbool r; - bool was_pareto = false, was_opt = false; + bool was_opt = false; if (m_opt && !m_opt->empty()) { was_opt = true; @@ -1342,32 +1353,25 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions scoped_ctrl_c ctrlc(eh); scoped_timer timer(timeout, &eh); scoped_rlimit _rlimit(m().limit(), rlimit); - ptr_vector cnstr(m_assertions); - cnstr.append(num_assumptions, assumptions); - get_opt()->set_hard_constraints(cnstr); + if (!m_processing_pareto) { + ptr_vector cnstr(m_assertions); + cnstr.append(num_assumptions, assumptions); + get_opt()->set_hard_constraints(cnstr); + } try { r = get_opt()->optimize(); - while (r == l_true && get_opt()->is_pareto()) { - was_pareto = true; - get_opt()->display_assignment(regular_stream()); - regular_stream() << "\n"; - if (get_opt()->print_model()) { - model_ref mdl; - get_opt()->get_model(mdl); - display_model(mdl); - } - r = get_opt()->optimize(); + if (r == l_true && get_opt()->is_pareto()) { + m_processing_pareto = true; } } catch (z3_error & ex) { throw ex; } catch (z3_exception & ex) { - get_opt()->display_assignment(regular_stream()); throw cmd_exception(ex.msg()); } - if (was_pareto && r == l_false) { - r = l_true; + if (m_processing_pareto && r != l_true) { + m_processing_pareto = false; } get_opt()->set_status(r); } @@ -1400,8 +1404,8 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions validate_model(); } validate_check_sat_result(r); - if (was_opt && r != l_false && !was_pareto) { - get_opt()->display_assignment(regular_stream()); + if (was_opt && r != l_false && !m_processing_pareto) { + // get_opt()->display_assignment(regular_stream()); } if (r == l_true && m_params.m_dump_models) { diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 8885bc5d6b4..74b2f3fbcbc 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -42,6 +42,7 @@ Module Name: 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); @@ -123,7 +124,6 @@ class opt_wrapper : public check_sat_result { virtual void display_assignment(std::ostream& out) = 0; virtual bool is_pareto() = 0; virtual void set_logic(symbol const& s) = 0; - virtual bool print_model() const = 0; virtual void get_box_model(model_ref& mdl, unsigned index) = 0; virtual void updt_params(params_ref const& p) = 0; }; @@ -160,7 +160,8 @@ class cmd_context : public progress_callback, public tactic_manager, public ast_ 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; static std::ostringstream g_error_stream; @@ -257,7 +258,6 @@ class cmd_context : public progress_callback, public tactic_manager, public ast_ bool logic_has_array() const; bool logic_has_datatype() const; bool logic_has_fpa() const; - bool logic_has_str() const; void print_unsupported_msg() { regular_stream() << "unsupported" << std::endl; } void print_unsupported_info(symbol const& s, int line, int pos) { if (s != symbol::null) diagnostic_stream() << "; " << s << " line: " << line << " position: " << pos << std::endl;} 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/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 1d320d75182..8c7d9ec0241 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/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 eedb0ed4da1..8873a102123 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 61da4b3a0cd..805ed8e5de4 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 ffb964f479e..27d62538e1b 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 f7dc18b5ecf..85681453199 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 e9b383b56cd..229db4d2722 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 619f88e3b49..247519d639a 100644 --- a/src/muz/base/rule_properties.cpp +++ b/src/muz/base/rule_properties.cpp @@ -50,7 +50,9 @@ 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); - if (!m.is_bool(d) && !m_dl.is_finite_sort(d) && !m_bv.is_bv_sort(d)) { + sort_size sz = d->get_num_elements(); + 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/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 239c4df124b..4a7c4d0184d 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/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/src/muz/pdr/pdr_context.cpp b/src/muz/pdr/pdr_context.cpp index 7484a77fa2f..05bb5489a81 100644 --- a/src/muz/pdr/pdr_context.cpp +++ b/src/muz/pdr/pdr_context.cpp @@ -1728,7 +1728,7 @@ namespace pdr { void context::validate_search() { expr_ref tr = m_search.get_trace(*this); - TRACE("pdr", tout << tr << "\n";); + TRACE("pdr", tout << tr << "\n";); smt::kernel solver(m, get_fparams()); solver.assert_expr(tr); lbool res = solver.check(); 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 75caba6ae89..b65ed455ca4 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 e428fdd2ef1..a8e54085d3f 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 74206a1f6f7..5bb47c5c3a6 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 b112f4c9903..0d118a58904 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 455b06d3db9..1ed847e8950 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 048decaf9a7..19dccf417bf 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 caff79d2ee7..a22a67416ab 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 5d36d26ccb3..586c52cd6dd 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 7dabece2f8d..c6b3e8be700 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 2f7d0d475b1..cefda74e874 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 1967fdc93b2..8fae4ee357c 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 41b18145004..78133aab716 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_solver.cpp b/src/nlsat/nlsat_solver.cpp index 7582c83896c..7ffb1b0a547 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 9ea26a0c586..3be3bcfb768 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 571c26e2d56..0264a6a24c7 100644 --- a/src/opt/opt_cmds.cpp +++ b/src/opt/opt_cmds.cpp @@ -100,6 +100,7 @@ class assert_soft_cmd : public parametric_cmd { 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 @@ class min_maximize_cmd : public cmd { 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 @@ class min_maximize_cmd : public cmd { } }; +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 1310727aa93..0e1c150c0e8 100644 --- a/src/opt/opt_context.cpp +++ b/src/opt/opt_context.cpp @@ -319,11 +319,6 @@ namespace opt { return r; } - bool context::print_model() const { - opt_params optp(m_params); - return optp.print_model(); - } - void context::get_base_model(model_ref& mdl) { mdl = m_model; } @@ -1318,17 +1313,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()); @@ -1336,7 +1332,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/opt_context.h b/src/opt/opt_context.h index 53bfc19c539..66f0ef015f2 100644 --- a/src/opt/opt_context.h +++ b/src/opt/opt_context.h @@ -183,7 +183,6 @@ namespace opt { virtual bool empty() { return m_scoped_state.m_objectives.empty(); } virtual void set_hard_constraints(ptr_vector & hard); virtual lbool optimize(); - virtual bool print_model() const; virtual void set_model(model_ref& _m) { m_model = _m; } virtual void get_model(model_ref& _m); virtual void get_box_model(model_ref& _m, unsigned index); diff --git a/src/opt/opt_params.pyg b/src/opt/opt_params.pyg index 51f58396cd3..13bf5131336 100644 --- a/src/opt/opt_params.pyg +++ b/src/opt/opt_params.pyg @@ -7,7 +7,6 @@ def_module_params('opt', ('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'), ('timeout', UINT, UINT_MAX, 'timeout (in milliseconds) (UINT_MAX and 0 mean no timeout)'), ('rlimit', UINT, 0, 'resource limit (0 means no limit)'), - ('print_model', BOOL, False, 'display model for satisfiable constraints'), ('enable_sls', BOOL, False, 'enable SLS tuning during weighted maxsast'), ('enable_sat', BOOL, True, 'enable the new SAT core for propositional constraints'), ('elim_01', BOOL, True, 'eliminate 01 variables'), diff --git a/src/opt/wmax.cpp b/src/opt/wmax.cpp index 58d319a6365..15b723c8c91 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/smt2scanner.cpp b/src/parsers/smt2/smt2scanner.cpp index fb2f9f34a7c..1763a4fa5cc 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 6e82e2c968c..2d2cf957912 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_plugin.cpp b/src/qe/qe_arith_plugin.cpp index 4281ec9098d..d8ae75256eb 100644 --- a/src/qe/qe_arith_plugin.cpp +++ b/src/qe/qe_arith_plugin.cpp @@ -2503,7 +2503,7 @@ namespace qe { } 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 eccc2d0c790..ce182a97b72 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 00000000000..b2b4be6493a --- /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/sat_model_converter.cpp b/src/sat/sat_model_converter.cpp index 8901c276f81..525d084dc18 100644 --- a/src/sat/sat_model_converter.cpp +++ b/src/sat/sat_model_converter.cpp @@ -32,7 +32,7 @@ namespace sat { void model_converter::reset() { m_entries.finalize(); } - + void model_converter::operator()(model & m) const { vector::const_iterator begin = m_entries.begin(); vector::const_iterator it = m_entries.end(); @@ -46,7 +46,7 @@ namespace sat { literal_vector::const_iterator it2 = it->m_clauses.begin(); literal_vector::const_iterator end2 = it->m_clauses.end(); for (; it2 != end2; ++it2) { - literal l = *it2; + literal l = *it2; if (l == null_literal) { // end of clause if (!sat) { @@ -56,6 +56,7 @@ namespace sat { sat = false; continue; } + if (sat) continue; bool sign = l.sign(); @@ -125,7 +126,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(); @@ -218,7 +219,7 @@ namespace sat { out << *it2; } out << ")"; - } + } out << ")\n"; } @@ -237,4 +238,22 @@ namespace sat { } } + 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 b89e6e78444..eb22377074c 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: @@ -74,8 +74,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 7f2b7583053..fbfa0ec6b27 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -2628,7 +2628,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); } @@ -2684,6 +2684,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(); } @@ -3150,9 +3151,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; @@ -3176,7 +3177,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++) { @@ -3375,7 +3376,7 @@ namespace sat { if (check_inconsistent()) return l_false; 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() > 1) { @@ -3390,7 +3391,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) { @@ -3445,8 +3446,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 83c31715dc1..baac9f37bb9 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -130,17 +130,40 @@ class inc_sat_solver : public solver { m_solver.display_wcnf(out, m_asms.size(), m_asms.c_ptr(), nweights.c_ptr()); } + bool is_literal(expr* e) const { + return + is_uninterp_const(e) || + (m.is_not(e, e) && is_uninterp_const(e)); + } + virtual lbool check_sat(unsigned sz, expr * const * assumptions) { m_solver.pop_to_base_level(); + expr_ref_vector _assumptions(m); + obj_map asm2fml; + for (unsigned i = 0; i < sz; ++i) { + if (!is_literal(assumptions[i])) { + expr_ref a(m.mk_fresh_const("s", m.mk_bool_sort()), m); + expr_ref fml(m.mk_eq(a, assumptions[i]), m); + assert_expr(fml); + _assumptions.push_back(a); + asm2fml.insert(a, assumptions[i]); + } + else { + _assumptions.push_back(assumptions[i]); + asm2fml.insert(assumptions[i], assumptions[i]); + } + } + + TRACE("sat", tout << _assumptions << "\n";); dep2asm_t dep2asm; m_model = 0; lbool r = internalize_formulas(); if (r != l_true) return r; - r = internalize_assumptions(sz, assumptions, dep2asm); + r = internalize_assumptions(sz, _assumptions.c_ptr(), dep2asm); if (r != l_true) return r; r = m_solver.check(m_asms.size(), m_asms.c_ptr()); - + switch (r) { case l_true: if (sz > 0) { @@ -150,7 +173,7 @@ class inc_sat_solver : public solver { case l_false: // TBD: expr_dependency core is not accounted for. if (!m_asms.empty()) { - extract_core(dep2asm); + extract_core(dep2asm, asm2fml); } break; default: @@ -241,6 +264,7 @@ class inc_sat_solver : public solver { sat::bool_var_vector bvars; vector lconseq; dep2asm_t dep2asm; + obj_map asm2fml; m_solver.pop_to_base_level(); lbool r = internalize_formulas(); if (r != l_true) return r; @@ -251,19 +275,19 @@ class inc_sat_solver : public solver { r = m_solver.get_consequences(m_asms, bvars, lconseq); if (r == l_false) { if (!m_asms.empty()) { - extract_core(dep2asm); + extract_core(dep2asm, asm2fml); } 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); @@ -302,7 +326,6 @@ class inc_sat_solver : public solver { return l_true; } - virtual std::string reason_unknown() const { return m_unknown; } @@ -418,7 +441,7 @@ class inc_sat_solver : public solver { 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; } @@ -430,7 +453,7 @@ class inc_sat_solver : public solver { 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; @@ -456,7 +479,7 @@ class inc_sat_solver : public solver { 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; } @@ -483,7 +506,7 @@ class inc_sat_solver : public solver { } 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)); @@ -569,27 +592,28 @@ class inc_sat_solver : public solver { } } - void extract_core(dep2asm_t& dep2asm) { + void extract_core(dep2asm_t& dep2asm, obj_map const& asm2fml) { u_map asm2dep; 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(); for (unsigned i = 0; i < core.size(); ++i) { expr* e = 0; VERIFY(asm2dep.find(core[i].index(), e)); + if (asm2fml.contains(e)) { + e = asm2fml.find(e); + } m_core.push_back(e); } } 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 74aeba8b962..fed6a89c8c1 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 8bed24c830f..83f5e9e2eb6 100644 --- a/src/shell/lp_frontend.cpp +++ b/src/shell/lp_frontend.cpp @@ -17,7 +17,7 @@ Copyright (c) 2016 Microsoft Corporation #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/asserted_formulas.cpp b/src/smt/asserted_formulas.cpp index 26395f9ab57..5c7ed33f849 100644 --- a/src/smt/asserted_formulas.cpp +++ b/src/smt/asserted_formulas.cpp @@ -43,7 +43,7 @@ Revision History: #include"quasi_macros.h" asserted_formulas::asserted_formulas(ast_manager & m, smt_params & p): - m_manager(m), + m(m), m_params(p), m_pre_simplifier(m), m_simplifier(m), @@ -63,7 +63,7 @@ asserted_formulas::asserted_formulas(ast_manager & m, smt_params & p): setup_simplifier_plugins(m_simplifier, m_bsimp, arith_simp, m_bvsimp); SASSERT(m_bsimp != 0); SASSERT(arith_simp != 0); - m_macro_finder = alloc(macro_finder, m_manager, m_macro_manager); + m_macro_finder = alloc(macro_finder, m, m_macro_manager); basic_simplifier_plugin * basic_simp = 0; bv_simplifier_plugin * bv_simp = 0; @@ -90,16 +90,16 @@ void asserted_formulas::setup() { } void asserted_formulas::setup_simplifier_plugins(simplifier & s, basic_simplifier_plugin * & bsimp, arith_simplifier_plugin * & asimp, bv_simplifier_plugin * & bvsimp) { - bsimp = alloc(basic_simplifier_plugin, m_manager); + bsimp = alloc(basic_simplifier_plugin, m); s.register_plugin(bsimp); - asimp = alloc(arith_simplifier_plugin, m_manager, *bsimp, m_params); + asimp = alloc(arith_simplifier_plugin, m, *bsimp, m_params); s.register_plugin(asimp); - s.register_plugin(alloc(array_simplifier_plugin, m_manager, *bsimp, s, m_params)); - bvsimp = alloc(bv_simplifier_plugin, m_manager, *bsimp, m_params); + s.register_plugin(alloc(array_simplifier_plugin, m, *bsimp, s, m_params)); + bvsimp = alloc(bv_simplifier_plugin, m, *bsimp, m_params); s.register_plugin(bvsimp); - s.register_plugin(alloc(datatype_simplifier_plugin, m_manager, *bsimp)); - s.register_plugin(alloc(fpa_simplifier_plugin, m_manager, *bsimp)); - s.register_plugin(alloc(seq_simplifier_plugin, m_manager, *bsimp)); + s.register_plugin(alloc(datatype_simplifier_plugin, m, *bsimp)); + s.register_plugin(alloc(fpa_simplifier_plugin, m, *bsimp)); + s.register_plugin(alloc(seq_simplifier_plugin, m, *bsimp)); } void asserted_formulas::init(unsigned num_formulas, expr * const * formulas, proof * const * prs) { @@ -108,7 +108,7 @@ void asserted_formulas::init(unsigned num_formulas, expr * const * formulas, pro SASSERT(!m_inconsistent); SASSERT(m_scopes.empty()); m_asserted_formulas.append(num_formulas, formulas); - if (m_manager.proofs_enabled()) + if (m.proofs_enabled()) m_asserted_formula_prs.append(num_formulas, prs); } @@ -125,9 +125,9 @@ void asserted_formulas::push_assertion(expr * e, proof * pr, expr_ref_vector & r SASSERT(!result.empty()); return; } - if (m_manager.is_false(e)) + if (m.is_false(e)) m_inconsistent = true; - ::push_assertion(m_manager, e, pr, result, result_prs); + ::push_assertion(m, e, pr, result, result_prs); } void asserted_formulas::set_eliminate_and(bool flag) { @@ -145,13 +145,13 @@ void asserted_formulas::assert_expr(expr * e, proof * _in_pr) { push_assertion(e, _in_pr, m_asserted_formulas, m_asserted_formula_prs); return; } - proof_ref in_pr(_in_pr, m_manager); - expr_ref r1(m_manager); - proof_ref pr1(m_manager); - expr_ref r2(m_manager); - proof_ref pr2(m_manager); - TRACE("assert_expr_before_simp", tout << mk_ll_pp(e, m_manager) << "\n";); - TRACE("assert_expr_bug", tout << mk_pp(e, m_manager) << "\n";); + proof_ref in_pr(_in_pr, m); + expr_ref r1(m); + proof_ref pr1(m); + expr_ref r2(m); + proof_ref pr2(m); + TRACE("assert_expr_before_simp", tout << mk_ll_pp(e, m) << "\n";); + TRACE("assert_expr_bug", tout << mk_pp(e, m) << "\n";); if (m_params.m_pre_simplifier) { m_pre_simplifier(e, r1, pr1); } @@ -161,14 +161,14 @@ void asserted_formulas::assert_expr(expr * e, proof * _in_pr) { } set_eliminate_and(false); // do not eliminate and before nnf. m_simplifier(r1, r2, pr2); - TRACE("assert_expr_bug", tout << "after...\n" << mk_pp(r1, m_manager) << "\n";); - if (m_manager.proofs_enabled()) { + TRACE("assert_expr_bug", tout << "after...\n" << mk_pp(r1, m) << "\n";); + if (m.proofs_enabled()) { if (e == r2) pr2 = in_pr; else - pr2 = m_manager.mk_modus_ponens(in_pr, m_manager.mk_transitivity(pr1, pr2)); + pr2 = m.mk_modus_ponens(in_pr, m.mk_transitivity(pr1, pr2)); } - TRACE("assert_expr_after_simp", tout << mk_ll_pp(r1, m_manager) << "\n";); + TRACE("assert_expr_after_simp", tout << mk_ll_pp(r1, m) << "\n";); push_assertion(r2, pr2, m_asserted_formulas, m_asserted_formula_prs); TRACE("asserted_formulas_bug", tout << "after assert_expr\n"; display(tout);); } @@ -176,7 +176,7 @@ void asserted_formulas::assert_expr(expr * e, proof * _in_pr) { void asserted_formulas::assert_expr(expr * e) { if (inconsistent()) return; - assert_expr(e, m_manager.mk_asserted(e)); + assert_expr(e, m.mk_asserted(e)); } void asserted_formulas::get_assertions(ptr_vector & result) { @@ -184,13 +184,13 @@ void asserted_formulas::get_assertions(ptr_vector & result) { } void asserted_formulas::push_scope() { - SASSERT(inconsistent() || m_asserted_qhead == m_asserted_formulas.size() || m_manager.canceled()); + SASSERT(inconsistent() || m_asserted_qhead == m_asserted_formulas.size() || m.canceled()); TRACE("asserted_formulas_scopes", tout << "push:\n"; display(tout);); m_scopes.push_back(scope()); m_macro_manager.push_scope(); scope & s = m_scopes.back(); s.m_asserted_formulas_lim = m_asserted_formulas.size(); - SASSERT(inconsistent() || s.m_asserted_formulas_lim == m_asserted_qhead || m_manager.canceled()); + SASSERT(inconsistent() || s.m_asserted_formulas_lim == m_asserted_qhead || m.canceled()); s.m_inconsistent_old = m_inconsistent; m_defined_names.push(); m_bv_sharing.push_scope(); @@ -206,7 +206,7 @@ void asserted_formulas::pop_scope(unsigned num_scopes) { m_inconsistent = s.m_inconsistent_old; m_defined_names.pop(num_scopes); m_asserted_formulas.shrink(s.m_asserted_formulas_lim); - if (m_manager.proofs_enabled()) + if (m.proofs_enabled()) m_asserted_formula_prs.shrink(s.m_asserted_formulas_lim); m_asserted_qhead = s.m_asserted_formulas_lim; m_scopes.shrink(new_lvl); @@ -228,7 +228,7 @@ void asserted_formulas::reset() { #ifdef Z3DEBUG bool asserted_formulas::check_well_sorted() const { for (unsigned i = 0; i < m_asserted_formulas.size(); i++) { - if (!is_well_sorted(m_manager, m_asserted_formulas.get(i))) return false; + if (!is_well_sorted(m, m_asserted_formulas.get(i))) return false; } return true; } @@ -322,7 +322,7 @@ void asserted_formulas::display(std::ostream & out) const { for (unsigned i = 0; i < m_asserted_formulas.size(); i++) { if (i == m_asserted_qhead) out << "[HEAD] ==>\n"; - out << mk_pp(m_asserted_formulas.get(i), m_manager) << "\n"; + out << mk_pp(m_asserted_formulas.get(i), m) << "\n"; } out << "inconsistent: " << inconsistent() << "\n"; } @@ -331,7 +331,7 @@ void asserted_formulas::display_ll(std::ostream & out, ast_mark & pp_visited) co if (!m_asserted_formulas.empty()) { unsigned sz = m_asserted_formulas.size(); for (unsigned i = 0; i < sz; i++) - ast_def_ll_pp(out, m_manager, m_asserted_formulas.get(i), pp_visited, true, false); + ast_def_ll_pp(out, m, m_asserted_formulas.get(i), pp_visited, true, false); out << "asserted formulas:\n"; for (unsigned i = 0; i < sz; i++) out << "#" << m_asserted_formulas[i]->get_id() << " "; @@ -346,23 +346,23 @@ void asserted_formulas::reduce_asserted_formulas() { if (inconsistent()) { return; } - expr_ref_vector new_exprs(m_manager); - proof_ref_vector new_prs(m_manager); + expr_ref_vector new_exprs(m); + proof_ref_vector new_prs(m); unsigned i = m_asserted_qhead; unsigned sz = m_asserted_formulas.size(); for (; i < sz && !inconsistent(); i++) { expr * n = m_asserted_formulas.get(i); SASSERT(n != 0); proof * pr = m_asserted_formula_prs.get(i, 0); - expr_ref new_n(m_manager); - proof_ref new_pr(m_manager); + expr_ref new_n(m); + proof_ref new_pr(m); m_simplifier(n, new_n, new_pr); - TRACE("reduce_asserted_formulas", tout << mk_pp(n, m_manager) << " -> " << mk_pp(new_n, m_manager) << "\n";); + TRACE("reduce_asserted_formulas", tout << mk_pp(n, m) << " -> " << mk_pp(new_n, m) << "\n";); if (n == new_n.get()) { push_assertion(n, pr, new_exprs, new_prs); } else { - new_pr = m_manager.mk_modus_ponens(pr, new_pr); + new_pr = m.mk_modus_ponens(pr, new_pr); push_assertion(new_n, new_pr, new_exprs, new_prs); } if (canceled()) { @@ -376,15 +376,15 @@ void asserted_formulas::swap_asserted_formulas(expr_ref_vector & new_exprs, proo SASSERT(!inconsistent() || !new_exprs.empty()); m_asserted_formulas.shrink(m_asserted_qhead); m_asserted_formulas.append(new_exprs); - if (m_manager.proofs_enabled()) { + if (m.proofs_enabled()) { m_asserted_formula_prs.shrink(m_asserted_qhead); m_asserted_formula_prs.append(new_prs); } } void asserted_formulas::find_macros_core() { - expr_ref_vector new_exprs(m_manager); - proof_ref_vector new_prs(m_manager); + expr_ref_vector new_exprs(m); + proof_ref_vector new_prs(m); unsigned sz = m_asserted_formulas.size(); m_macro_finder->operator()(sz - m_asserted_qhead, m_asserted_formulas.c_ptr() + m_asserted_qhead, m_asserted_formula_prs.c_ptr() + m_asserted_qhead, new_exprs, new_prs); @@ -407,9 +407,9 @@ void asserted_formulas::expand_macros() { void asserted_formulas::apply_quasi_macros() { IF_IVERBOSE(10, verbose_stream() << "(smt.find-quasi-macros)\n";); TRACE("before_quasi_macros", display(tout);); - expr_ref_vector new_exprs(m_manager); - proof_ref_vector new_prs(m_manager); - quasi_macros proc(m_manager, m_macro_manager, m_simplifier); + expr_ref_vector new_exprs(m); + proof_ref_vector new_prs(m); + quasi_macros proc(m, m_macro_manager, m_simplifier); while (proc(m_asserted_formulas.size() - m_asserted_qhead, m_asserted_formulas.c_ptr() + m_asserted_qhead, m_asserted_formula_prs.c_ptr() + m_asserted_qhead, @@ -424,27 +424,27 @@ void asserted_formulas::apply_quasi_macros() { void asserted_formulas::nnf_cnf() { IF_IVERBOSE(10, verbose_stream() << "(smt.nnf)\n";); - nnf apply_nnf(m_manager, m_defined_names); - expr_ref_vector new_exprs(m_manager); - proof_ref_vector new_prs(m_manager); - expr_ref_vector push_todo(m_manager); - proof_ref_vector push_todo_prs(m_manager); + nnf apply_nnf(m, m_defined_names); + expr_ref_vector new_exprs(m); + proof_ref_vector new_prs(m); + expr_ref_vector push_todo(m); + proof_ref_vector push_todo_prs(m); unsigned i = m_asserted_qhead; unsigned sz = m_asserted_formulas.size(); TRACE("nnf_bug", tout << "i: " << i << " sz: " << sz << "\n";); for (; i < sz; i++) { expr * n = m_asserted_formulas.get(i); - TRACE("nnf_bug", tout << "processing:\n" << mk_pp(n, m_manager) << "\n";); + TRACE("nnf_bug", tout << "processing:\n" << mk_pp(n, m) << "\n";); proof * pr = m_asserted_formula_prs.get(i, 0); - expr_ref r1(m_manager); - proof_ref pr1(m_manager); - CASSERT("well_sorted",is_well_sorted(m_manager, n)); + expr_ref r1(m); + proof_ref pr1(m); + CASSERT("well_sorted",is_well_sorted(m, n)); push_todo.reset(); push_todo_prs.reset(); apply_nnf(n, push_todo, push_todo_prs, r1, pr1); - CASSERT("well_sorted",is_well_sorted(m_manager, r1)); - pr = m_manager.mk_modus_ponens(pr, pr1); + CASSERT("well_sorted",is_well_sorted(m, r1)); + pr = m.mk_modus_ponens(pr, pr1); push_todo.push_back(r1); push_todo_prs.push_back(pr); @@ -456,13 +456,13 @@ void asserted_formulas::nnf_cnf() { expr * n = push_todo.get(k); proof * pr = 0; m_simplifier(n, r1, pr1); - CASSERT("well_sorted",is_well_sorted(m_manager, r1)); + CASSERT("well_sorted",is_well_sorted(m, r1)); if (canceled()) { return; } - if (m_manager.proofs_enabled()) - pr = m_manager.mk_modus_ponens(push_todo_prs.get(k), pr1); + if (m.proofs_enabled()) + pr = m.mk_modus_ponens(push_todo_prs.get(k), pr1); else pr = 0; push_assertion(r1, pr, new_exprs, new_prs); @@ -476,23 +476,23 @@ void asserted_formulas::NAME() { IF_IVERBOSE(10, verbose_stream() << "(smt." << MSG << ")\n";); \ TRACE(LABEL, tout << "before:\n"; display(tout);); \ FUNCTOR_DEF; \ - expr_ref_vector new_exprs(m_manager); \ - proof_ref_vector new_prs(m_manager); \ + expr_ref_vector new_exprs(m); \ + proof_ref_vector new_prs(m); \ unsigned i = m_asserted_qhead; \ unsigned sz = m_asserted_formulas.size(); \ for (; i < sz; i++) { \ expr * n = m_asserted_formulas.get(i); \ proof * pr = m_asserted_formula_prs.get(i, 0); \ - expr_ref new_n(m_manager); \ + expr_ref new_n(m); \ functor(n, new_n); \ - TRACE("simplifier_simple_step", tout << mk_pp(n, m_manager) << "\n" << mk_pp(new_n, m_manager) << "\n";); \ + TRACE("simplifier_simple_step", tout << mk_pp(n, m) << "\n" << mk_pp(new_n, m) << "\n";); \ if (n == new_n.get()) { \ push_assertion(n, pr, new_exprs, new_prs); \ } \ - else if (m_manager.proofs_enabled()) { \ - proof_ref new_pr(m_manager); \ - new_pr = m_manager.mk_rewrite_star(n, new_n, 0, 0); \ - new_pr = m_manager.mk_modus_ponens(pr, new_pr); \ + else if (m.proofs_enabled()) { \ + proof_ref new_pr(m); \ + new_pr = m.mk_rewrite_star(n, new_n, 0, 0); \ + new_pr = m.mk_modus_ponens(pr, new_pr); \ push_assertion(new_n, new_pr, new_exprs, new_prs); \ } \ else { \ @@ -505,7 +505,7 @@ void asserted_formulas::NAME() { TRACE(LABEL, display(tout);); \ } -MK_SIMPLE_SIMPLIFIER(apply_distribute_forall, distribute_forall functor(m_manager, *m_bsimp), "distribute_forall", "distribute-forall"); +MK_SIMPLE_SIMPLIFIER(apply_distribute_forall, distribute_forall functor(m), "distribute_forall", "distribute-forall"); void asserted_formulas::reduce_and_solve() { IF_IVERBOSE(10, verbose_stream() << "(smt.reducing)\n";); @@ -516,22 +516,22 @@ void asserted_formulas::reduce_and_solve() { void asserted_formulas::infer_patterns() { IF_IVERBOSE(10, verbose_stream() << "(smt.pattern-inference)\n";); TRACE("before_pattern_inference", display(tout);); - pattern_inference infer(m_manager, m_params); - expr_ref_vector new_exprs(m_manager); - proof_ref_vector new_prs(m_manager); + pattern_inference infer(m, m_params); + expr_ref_vector new_exprs(m); + proof_ref_vector new_prs(m); unsigned i = m_asserted_qhead; unsigned sz = m_asserted_formulas.size(); for (; i < sz; i++) { expr * n = m_asserted_formulas.get(i); proof * pr = m_asserted_formula_prs.get(i, 0); - expr_ref new_n(m_manager); - proof_ref new_pr(m_manager); + expr_ref new_n(m); + proof_ref new_pr(m); infer(n, new_n, new_pr); if (n == new_n.get()) { push_assertion(n, pr, new_exprs, new_prs); } - else if (m_manager.proofs_enabled()) { - new_pr = m_manager.mk_modus_ponens(pr, new_pr); + else if (m.proofs_enabled()) { + new_pr = m.mk_modus_ponens(pr, new_pr); push_assertion(new_n, new_pr, new_exprs, new_prs); } else { @@ -554,16 +554,16 @@ void asserted_formulas::commit(unsigned new_qhead) { void asserted_formulas::eliminate_term_ite() { IF_IVERBOSE(10, verbose_stream() << "(smt.eliminating-ite-term)\n";); TRACE("before_elim_term_ite", display(tout);); - elim_term_ite elim(m_manager, m_defined_names); - expr_ref_vector new_exprs(m_manager); - proof_ref_vector new_prs(m_manager); + elim_term_ite elim(m, m_defined_names); + expr_ref_vector new_exprs(m); + proof_ref_vector new_prs(m); unsigned i = m_asserted_qhead; unsigned sz = m_asserted_formulas.size(); for (; i < sz; i++) { expr * n = m_asserted_formulas.get(i); proof * pr = m_asserted_formula_prs.get(i, 0); - expr_ref new_n(m_manager); - proof_ref new_pr(m_manager); + expr_ref new_n(m); + proof_ref new_pr(m); elim(n, new_exprs, new_prs, new_n, new_pr); SASSERT(new_n.get() != 0); DEBUG_CODE({ @@ -574,8 +574,8 @@ void asserted_formulas::eliminate_term_ite() { if (n == new_n.get()) { push_assertion(n, pr, new_exprs, new_prs); } - else if (m_manager.proofs_enabled()) { - new_pr = m_manager.mk_modus_ponens(pr, new_pr); + else if (m.proofs_enabled()) { + new_pr = m.mk_modus_ponens(pr, new_pr); push_assertion(new_n, new_pr, new_exprs, new_prs); } else { @@ -602,31 +602,31 @@ void asserted_formulas::propagate_values() { // - new_exprs2 is the set R // // The loop also updates the m_cache. It adds the entries x -> n to it. - expr_ref_vector new_exprs1(m_manager); - proof_ref_vector new_prs1(m_manager); - expr_ref_vector new_exprs2(m_manager); - proof_ref_vector new_prs2(m_manager); + expr_ref_vector new_exprs1(m); + proof_ref_vector new_prs1(m); + expr_ref_vector new_exprs2(m); + proof_ref_vector new_prs2(m); unsigned sz = m_asserted_formulas.size(); for (unsigned i = 0; i < sz; i++) { - expr_ref n(m_asserted_formulas.get(i), m_manager); - proof_ref pr(m_asserted_formula_prs.get(i, 0), m_manager); - TRACE("simplifier", tout << mk_pp(n, m_manager) << "\n";); + expr_ref n(m_asserted_formulas.get(i), m); + proof_ref pr(m_asserted_formula_prs.get(i, 0), m); + TRACE("simplifier", tout << mk_pp(n, m) << "\n";); expr* lhs, *rhs; - if (m_manager.is_eq(n, lhs, rhs) && - (m_manager.is_value(lhs) || m_manager.is_value(rhs))) { - if (m_manager.is_value(lhs)) { + if (m.is_eq(n, lhs, rhs) && + (m.is_value(lhs) || m.is_value(rhs))) { + if (m.is_value(lhs)) { std::swap(lhs, rhs); - n = m_manager.mk_eq(lhs, rhs); - pr = m_manager.mk_symmetry(pr); + n = m.mk_eq(lhs, rhs); + pr = m.mk_symmetry(pr); } - if (!m_manager.is_value(lhs) && !m_simplifier.is_cached(lhs)) { + if (!m.is_value(lhs) && !m_simplifier.is_cached(lhs)) { if (i >= m_asserted_qhead) { new_exprs1.push_back(n); - if (m_manager.proofs_enabled()) + if (m.proofs_enabled()) new_prs1.push_back(pr); } - TRACE("propagate_values", tout << "found:\n" << mk_pp(lhs, m_manager) << "\n->\n" << mk_pp(rhs, m_manager) << "\n"; - if (pr) tout << "proof: " << mk_pp(pr, m_manager) << "\n";); + TRACE("propagate_values", tout << "found:\n" << mk_pp(lhs, m) << "\n->\n" << mk_pp(rhs, m) << "\n"; + if (pr) tout << "proof: " << mk_pp(pr, m) << "\n";); m_simplifier.cache_result(lhs, rhs, pr); found = true; continue; @@ -634,7 +634,7 @@ void asserted_formulas::propagate_values() { } if (i >= m_asserted_qhead) { new_exprs2.push_back(n); - if (m_manager.proofs_enabled()) + if (m.proofs_enabled()) new_prs2.push_back(pr); } } @@ -646,14 +646,14 @@ void asserted_formulas::propagate_values() { for (unsigned i = 0; i < sz; i++) { expr * n = new_exprs2.get(i); proof * pr = new_prs2.get(i, 0); - expr_ref new_n(m_manager); - proof_ref new_pr(m_manager); + expr_ref new_n(m); + proof_ref new_pr(m); m_simplifier(n, new_n, new_pr); if (n == new_n.get()) { push_assertion(n, pr, new_exprs1, new_prs1); } else { - new_pr = m_manager.mk_modus_ponens(pr, new_pr); + new_pr = m.mk_modus_ponens(pr, new_pr); push_assertion(new_n, new_pr, new_exprs1, new_prs1); } } @@ -677,25 +677,25 @@ void asserted_formulas::propagate_booleans() { cont = false; unsigned i = m_asserted_qhead; unsigned sz = m_asserted_formulas.size(); -#define PROCESS() { \ - expr * n = m_asserted_formulas.get(i); \ - proof * pr = m_asserted_formula_prs.get(i, 0); \ - expr_ref new_n(m_manager); \ - proof_ref new_pr(m_manager); \ - m_simplifier(n, new_n, new_pr); \ - m_asserted_formulas.set(i, new_n); \ - if (m_manager.proofs_enabled()) { \ - new_pr = m_manager.mk_modus_ponens(pr, new_pr); \ - m_asserted_formula_prs.set(i, new_pr); \ - } \ - if (n != new_n) { \ - cont = true; \ - modified = true; \ - } \ - if (m_manager.is_not(new_n)) \ - m_simplifier.cache_result(to_app(new_n)->get_arg(0), m_manager.mk_false(), m_manager.mk_iff_false(new_pr)); \ - else \ - m_simplifier.cache_result(new_n, m_manager.mk_true(), m_manager.mk_iff_true(new_pr)); \ +#define PROCESS() { \ + expr * n = m_asserted_formulas.get(i); \ + proof * pr = m_asserted_formula_prs.get(i, 0); \ + expr_ref new_n(m); \ + proof_ref new_pr(m); \ + m_simplifier(n, new_n, new_pr); \ + m_asserted_formulas.set(i, new_n); \ + if (m.proofs_enabled()) { \ + new_pr = m.mk_modus_ponens(pr, new_pr); \ + m_asserted_formula_prs.set(i, new_pr); \ + } \ + if (n != new_n) { \ + cont = true; \ + modified = true; \ + } \ + if (m.is_not(new_n)) \ + m_simplifier.cache_result(to_app(new_n)->get_arg(0), m.mk_false(), m.mk_iff_false(new_pr)); \ + else \ + m_simplifier.cache_result(new_n, m.mk_true(), m.mk_iff_true(new_pr)); \ } for (; i < sz; i++) { PROCESS(); @@ -715,57 +715,57 @@ void asserted_formulas::propagate_booleans() { } #define MK_SIMPLIFIER(NAME, FUNCTOR, TAG, MSG, REDUCE) \ -bool asserted_formulas::NAME() { \ - IF_IVERBOSE(10, verbose_stream() << "(smt." << MSG << ")\n";); \ - TRACE(TAG, ast_mark visited; display_ll(tout, visited);); \ - FUNCTOR; \ - bool changed = false; \ - expr_ref_vector new_exprs(m_manager); \ - proof_ref_vector new_prs(m_manager); \ - unsigned i = m_asserted_qhead; \ - unsigned sz = m_asserted_formulas.size(); \ - for (; i < sz; i++) { \ - expr * n = m_asserted_formulas.get(i); \ - proof * pr = m_asserted_formula_prs.get(i, 0); \ - expr_ref new_n(m_manager); \ - proof_ref new_pr(m_manager); \ - functor(n, new_n, new_pr); \ - if (n == new_n.get()) { \ - push_assertion(n, pr, new_exprs, new_prs); \ - } \ - else if (m_manager.proofs_enabled()) { \ - changed = true; \ - if (!new_pr) new_pr = m_manager.mk_rewrite(n, new_n); \ - new_pr = m_manager.mk_modus_ponens(pr, new_pr); \ - push_assertion(new_n, new_pr, new_exprs, new_prs); \ - } \ - else { \ - changed = true; \ - push_assertion(new_n, 0, new_exprs, new_prs); \ + bool asserted_formulas::NAME() { \ + IF_IVERBOSE(10, verbose_stream() << "(smt." << MSG << ")\n";); \ + TRACE(TAG, ast_mark visited; display_ll(tout, visited);); \ + FUNCTOR; \ + bool changed = false; \ + expr_ref_vector new_exprs(m); \ + proof_ref_vector new_prs(m); \ + unsigned i = m_asserted_qhead; \ + unsigned sz = m_asserted_formulas.size(); \ + for (; i < sz; i++) { \ + expr * n = m_asserted_formulas.get(i); \ + proof * pr = m_asserted_formula_prs.get(i, 0); \ + expr_ref new_n(m); \ + proof_ref new_pr(m); \ + functor(n, new_n, new_pr); \ + if (n == new_n.get()) { \ + push_assertion(n, pr, new_exprs, new_prs); \ + } \ + else if (m.proofs_enabled()) { \ + changed = true; \ + if (!new_pr) new_pr = m.mk_rewrite(n, new_n); \ + new_pr = m.mk_modus_ponens(pr, new_pr); \ + push_assertion(new_n, new_pr, new_exprs, new_prs); \ + } \ + else { \ + changed = true; \ + push_assertion(new_n, 0, new_exprs, new_prs); \ + } \ } \ - } \ - swap_asserted_formulas(new_exprs, new_prs); \ - TRACE(TAG, ast_mark visited; display_ll(tout, visited);); \ - if (changed && REDUCE) { \ - reduce_and_solve(); \ + swap_asserted_formulas(new_exprs, new_prs); \ TRACE(TAG, ast_mark visited; display_ll(tout, visited);); \ - } \ - return changed; \ -} + if (changed && REDUCE) { \ + reduce_and_solve(); \ + TRACE(TAG, ast_mark visited; display_ll(tout, visited);); \ + } \ + return changed; \ + } -MK_SIMPLIFIER(pull_cheap_ite_trees, pull_cheap_ite_tree_star functor(m_manager, m_simplifier), "pull_cheap_ite_trees", "pull-cheap-ite-trees", false); +MK_SIMPLIFIER(pull_cheap_ite_trees, pull_cheap_ite_tree_star functor(m, m_simplifier), "pull_cheap_ite_trees", "pull-cheap-ite-trees", false); -MK_SIMPLIFIER(pull_nested_quantifiers, pull_nested_quant functor(m_manager), "pull_nested_quantifiers", "pull-nested-quantifiers", false); +MK_SIMPLIFIER(pull_nested_quantifiers, pull_nested_quant functor(m), "pull_nested_quantifiers", "pull-nested-quantifiers", false); proof * asserted_formulas::get_inconsistency_proof() const { if (!inconsistent()) return 0; - if (!m_manager.proofs_enabled()) + if (!m.proofs_enabled()) return 0; unsigned sz = m_asserted_formulas.size(); for (unsigned i = 0; i < sz; i++) { expr * f = m_asserted_formulas.get(i); - if (m_manager.is_false(f)) + if (m.is_false(f)) return m_asserted_formula_prs.get(i); } UNREACHABLE(); @@ -780,14 +780,14 @@ void asserted_formulas::refine_inj_axiom() { for (; i < sz; i++) { expr * n = m_asserted_formulas.get(i); proof * pr = m_asserted_formula_prs.get(i, 0); - expr_ref new_n(m_manager); - if (is_quantifier(n) && simplify_inj_axiom(m_manager, to_quantifier(n), new_n)) { - TRACE("inj_axiom", tout << "simplifying...\n" << mk_pp(n, m_manager) << "\n" << mk_pp(new_n, m_manager) << "\n";); + expr_ref new_n(m); + if (is_quantifier(n) && simplify_inj_axiom(m, to_quantifier(n), new_n)) { + TRACE("inj_axiom", tout << "simplifying...\n" << mk_pp(n, m) << "\n" << mk_pp(new_n, m) << "\n";); m_asserted_formulas.set(i, new_n); - if (m_manager.proofs_enabled()) { - proof_ref new_pr(m_manager); - new_pr = m_manager.mk_rewrite(n, new_n); - new_pr = m_manager.mk_modus_ponens(pr, new_pr); + if (m.proofs_enabled()) { + proof_ref new_pr(m); + new_pr = m.mk_rewrite(n, new_n); + new_pr = m.mk_modus_ponens(pr, new_pr); m_asserted_formula_prs.set(i, new_pr); } } @@ -797,36 +797,36 @@ void asserted_formulas::refine_inj_axiom() { MK_SIMPLIFIER(apply_bit2int, bit2int& functor = m_bit2int, "bit2int", "propagate-bit-vector-over-integers", true); -MK_SIMPLIFIER(cheap_quant_fourier_motzkin, elim_bounds_star functor(m_manager), "elim_bounds", "cheap-fourier-motzkin", true); - - - -MK_SIMPLIFIER(elim_bvs_from_quantifiers, bv_elim_star functor(m_manager), "bv_elim", "eliminate-bit-vectors-from-quantifiers", true); - -#define LIFT_ITE(NAME, FUNCTOR, MSG) \ -void asserted_formulas::NAME() { \ - IF_IVERBOSE(10, verbose_stream() << "(smt." << MSG << ")\n";); \ - TRACE("lift_ite", display(tout);); \ - FUNCTOR; \ - unsigned i = m_asserted_qhead; \ - unsigned sz = m_asserted_formulas.size(); \ - for (; i < sz; i++) { \ - expr * n = m_asserted_formulas.get(i); \ - proof * pr = m_asserted_formula_prs.get(i, 0); \ - expr_ref new_n(m_manager); \ - proof_ref new_pr(m_manager); \ - functor(n, new_n, new_pr); \ - TRACE("lift_ite_step", tout << mk_pp(n, m_manager) << "\n";); \ - IF_IVERBOSE(10000, verbose_stream() << "lift before: " << get_num_exprs(n) << ", after: " << get_num_exprs(new_n) << "\n";); \ - m_asserted_formulas.set(i, new_n); \ - if (m_manager.proofs_enabled()) { \ - new_pr = m_manager.mk_modus_ponens(pr, new_pr); \ - m_asserted_formula_prs.set(i, new_pr); \ - } \ - } \ - TRACE("lift_ite", display(tout);); \ - reduce_and_solve(); \ -} +MK_SIMPLIFIER(cheap_quant_fourier_motzkin, elim_bounds_star functor(m), "elim_bounds", "cheap-fourier-motzkin", true); + + + +MK_SIMPLIFIER(elim_bvs_from_quantifiers, bv_elim_star functor(m), "bv_elim", "eliminate-bit-vectors-from-quantifiers", true); + +#define LIFT_ITE(NAME, FUNCTOR, MSG) \ + void asserted_formulas::NAME() { \ + IF_IVERBOSE(10, verbose_stream() << "(smt." << MSG << ")\n";); \ + TRACE("lift_ite", display(tout);); \ + FUNCTOR; \ + unsigned i = m_asserted_qhead; \ + unsigned sz = m_asserted_formulas.size(); \ + for (; i < sz; i++) { \ + expr * n = m_asserted_formulas.get(i); \ + proof * pr = m_asserted_formula_prs.get(i, 0); \ + expr_ref new_n(m); \ + proof_ref new_pr(m); \ + functor(n, new_n, new_pr); \ + TRACE("lift_ite_step", tout << mk_pp(n, m) << "\n";); \ + IF_IVERBOSE(10000, verbose_stream() << "lift before: " << get_num_exprs(n) << ", after: " << get_num_exprs(new_n) << "\n";); \ + m_asserted_formulas.set(i, new_n); \ + if (m.proofs_enabled()) { \ + new_pr = m.mk_modus_ponens(pr, new_pr); \ + m_asserted_formula_prs.set(i, new_pr); \ + } \ + } \ + TRACE("lift_ite", display(tout);); \ + reduce_and_solve(); \ + } LIFT_ITE(lift_ite, push_app_ite functor(m_simplifier, m_params.m_lift_ite == LI_CONSERVATIVE), "lifting ite"); LIFT_ITE(ng_lift_ite, ng_push_app_ite functor(m_simplifier, m_params.m_ng_lift_ite == LI_CONSERVATIVE), "lifting ng ite"); @@ -848,12 +848,12 @@ void asserted_formulas::max_bv_sharing() { for (; i < sz; i++) { expr * n = m_asserted_formulas.get(i); proof * pr = m_asserted_formula_prs.get(i, 0); - expr_ref new_n(m_manager); - proof_ref new_pr(m_manager); + expr_ref new_n(m); + proof_ref new_pr(m); m_bv_sharing(n, new_n, new_pr); m_asserted_formulas.set(i, new_n); - if (m_manager.proofs_enabled()) { - new_pr = m_manager.mk_modus_ponens(pr, new_pr); + if (m.proofs_enabled()) { + new_pr = m.mk_modus_ponens(pr, new_pr); m_asserted_formula_prs.set(i, new_pr); } } diff --git a/src/smt/asserted_formulas.h b/src/smt/asserted_formulas.h index 9e9ecf33ab0..6ad36cc7030 100644 --- a/src/smt/asserted_formulas.h +++ b/src/smt/asserted_formulas.h @@ -35,7 +35,7 @@ class arith_simplifier_plugin; class bv_simplifier_plugin; class asserted_formulas { - ast_manager & m_manager; + ast_manager & m; smt_params & m_params; simplifier m_pre_simplifier; simplifier m_simplifier; @@ -94,7 +94,7 @@ class asserted_formulas { unsigned get_total_size() const; bool has_bv() const; void max_bv_sharing(); - bool canceled() { return m_manager.canceled(); } + bool canceled() { return m.canceled(); } public: asserted_formulas(ast_manager & m, smt_params & p); @@ -115,7 +115,7 @@ class asserted_formulas { void commit(); void commit(unsigned new_qhead); expr * get_formula(unsigned idx) const { return m_asserted_formulas.get(idx); } - proof * get_formula_proof(unsigned idx) const { return m_manager.proofs_enabled() ? m_asserted_formula_prs.get(idx) : 0; } + proof * get_formula_proof(unsigned idx) const { return m.proofs_enabled() ? m_asserted_formula_prs.get(idx) : 0; } expr * const * get_formulas() const { return m_asserted_formulas.c_ptr(); } proof * const * get_formula_proofs() const { return m_asserted_formula_prs.c_ptr(); } void init(unsigned num_formulas, expr * const * formulas, proof * const * prs); diff --git a/src/smt/cached_var_subst.cpp b/src/smt/cached_var_subst.cpp index 1db3aa0a633..c36eb6dd23c 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/src/smt/params/smt_params_helper.pyg b/src/smt/params/smt_params_helper.pyg index d2addb7dced..6d67bfd194b 100644 --- a/src/smt/params/smt_params_helper.pyg +++ b/src/smt/params/smt_params_helper.pyg @@ -44,6 +44,7 @@ def_module_params(module_name='smt', ('arith.euclidean_solver', BOOL, False, 'eucliean solver for linear integer arithmetic'), ('arith.propagate_eqs', BOOL, True, 'propagate (cheap) equalities'), ('arith.propagation_mode', UINT, 2, '0 - no propagation, 1 - propagate existing literals, 2 - refine bounds'), + ('arith.reflect', BOOL, True, 'reflect arithmetical operators to the congruence closure'), ('arith.branch_cut_ratio', UINT, 2, 'branch/cut ratio for linear integer arithmetic'), ('arith.int_eq_branch', BOOL, False, 'branching using derived integer equations'), ('arith.ignore_int', BOOL, False, 'treat integer variables as real'), diff --git a/src/smt/params/theory_arith_params.cpp b/src/smt/params/theory_arith_params.cpp index 1e3f2914282..944911f9b03 100644 --- a/src/smt/params/theory_arith_params.cpp +++ b/src/smt/params/theory_arith_params.cpp @@ -35,6 +35,7 @@ void theory_arith_params::updt_params(params_ref const & _p) { m_arith_ignore_int = p.arith_ignore_int(); m_arith_bound_prop = static_cast(p.arith_propagation_mode()); m_arith_dump_lemmas = p.arith_dump_lemmas(); + m_arith_reflect = p.arith_reflect(); } @@ -85,4 +86,4 @@ void theory_arith_params::display(std::ostream & out) const { DISPLAY_PARAM(m_nl_arith_branching); DISPLAY_PARAM(m_nl_arith_rounds); DISPLAY_PARAM(m_arith_euclidean_solver); -} \ No newline at end of file +} 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 530d0ec8887..70a3041d2d2 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 129d77c85fe..41a269820e5 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; } }; diff --git a/src/smt/smt_conflict_resolution.cpp b/src/smt/smt_conflict_resolution.cpp index 8d90f958396..ade667e3432 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 65272207edf..20813602e78 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 50b957331e0..4e56d300456 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -3035,7 +3035,7 @@ namespace smt { // not counting any literals that get assigned by this method // this relies on bcp() to give us its old m_qhead and therefore // bcp() should always be called before this method - + unsigned assigned_literal_end = m_assigned_literals.size(); for (; qhead < assigned_literal_end; ++qhead) { literal l = m_assigned_literals[qhead]; @@ -4332,10 +4332,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()); @@ -4346,6 +4345,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_for_each_relevant_expr.cpp b/src/smt/smt_for_each_relevant_expr.cpp index bf039e8a104..84f93dd334c 100644 --- a/src/smt/smt_for_each_relevant_expr.cpp +++ b/src/smt/smt_for_each_relevant_expr.cpp @@ -23,7 +23,7 @@ Revision History: namespace smt { - bool check_at_labels::check(expr* n) { + bool check_at_labels::check(expr* n) { m_first = true; return count_at_labels_pos(n) <= 1; } diff --git a/src/smt/smt_internalizer.cpp b/src/smt/smt_internalizer.cpp index f7936eacd6e..5fbdb2477da 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_model_checker.cpp b/src/smt/smt_model_checker.cpp index 279ea20cf4c..b50527acf80 100644 --- a/src/smt/smt_model_checker.cpp +++ b/src/smt/smt_model_checker.cpp @@ -279,7 +279,7 @@ namespace smt { m_aux_context->pop(1); return r == l_false; // quantifier is satisfied by m_curr_model } - + model_ref complete_cex; m_aux_context->get_model(complete_cex); @@ -425,7 +425,7 @@ namespace smt { ptr_vector::const_iterator end = m_qm->end_quantifiers(); for (; it != end; ++it) { quantifier * q = *it; - if(!m_qm->mbqi_enabled(q)) continue; + if(!m_qm->mbqi_enabled(q)) continue; TRACE("model_checker", tout << "Check: " << mk_pp(q, m) << "\n"; tout << m_context->get_assignment(q) << "\n";); diff --git a/src/smt/smt_quantifier.cpp b/src/smt/smt_quantifier.cpp index 10e2df988c2..1c8f94edf97 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 6dcf20583e0..96af9909aa4 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 b7525bda846..6187f9c18a1 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 9e3eddafae0..64bae0a487b 100644 --- a/src/smt/tactic/smt_tactic.cpp +++ b/src/smt/tactic/smt_tactic.cpp @@ -253,7 +253,7 @@ class smt_tactic : public tactic { 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 54b617152a6..f94de7ebaae 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 5c652414a1a..bee744c3497 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 e6e9e863c8c..ca3a485c627 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_array_base.cpp b/src/smt/theory_array_base.cpp index fa48fea577c..6c47bf8558b 100644 --- a/src/smt/theory_array_base.cpp +++ b/src/smt/theory_array_base.cpp @@ -426,19 +426,19 @@ namespace smt { ptr_buffer to_unmark; unsigned num_vars = get_num_vars(); for (unsigned i = 0; i < num_vars; i++) { - enode * n = get_enode(i); + enode * n = get_enode(i); if (ctx.is_relevant(n)) { - enode * r = n->get_root(); - if (!r->is_marked()){ - if(is_array_sort(r) && ctx.is_shared(r)) { - TRACE("array_shared", tout << "new shared var: #" << r->get_owner_id() << "\n";); - theory_var r_th_var = r->get_th_var(get_id()); - SASSERT(r_th_var != null_theory_var); - result.push_back(r_th_var); - } - r->set_mark(); - to_unmark.push_back(r); - } + enode * r = n->get_root(); + if (!r->is_marked()){ + if(is_array_sort(r) && ctx.is_shared(r)) { + TRACE("array_shared", tout << "new shared var: #" << r->get_owner_id() << "\n";); + theory_var r_th_var = r->get_th_var(get_id()); + SASSERT(r_th_var != null_theory_var); + result.push_back(r_th_var); + } + r->set_mark(); + to_unmark.push_back(r); + } } } unmark_enodes(to_unmark.size(), to_unmark.c_ptr()); diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index a075f3072fd..e9bb13b8e39 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)]; + } + else { + w = m_var_index2theory_var[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); + 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 3f88455467b..832995994a3 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); + 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); - dependency* deps = 0; expr_dep ed; - if (m_rep.find_cache(e0, ed)) { - eqs = m_dm.mk_join(eqs, ed.second); + if (m_rep.find_cache(e, ed)) { + if (e != ed.first) { + eqs = m_dm.mk_join(eqs, ed.second); + } result = ed.first; - return result; } + 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 e145d30772e..f7212e60815 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 62846e7098a..2e928af376d 100644 --- a/src/smt/theory_str.cpp +++ b/src/smt/theory_str.cpp @@ -21,13 +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), @@ -98,7 +98,7 @@ namespace smt { if (defaultCharset) { // valid C strings can't contain the null byte ('\0') charSetSize = 255; - char_set = alloc_svect(char, charSetSize); + char_set.resize(256, 0); int idx = 0; // small letters for (int i = 97; i < 123; i++) { @@ -157,8 +157,7 @@ namespace smt { } else { const char setset[] = { 'a', 'b', 'c' }; int fSize = sizeof(setset) / sizeof(char); - - char_set = alloc_svect(char, fSize); + char_set.resize(fSize, 0); charSetSize = fSize; for (int i = 0; i < charSetSize; i++) { char_set[i] = setset[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,12 +487,12 @@ 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;); sort * string_sort = u.str.mk_string_sort(); app * a = mk_fresh_const(name.c_str(), string_sort); + m_trail.push_back(a); TRACE("str", tout << "a->get_family_id() = " << a->get_family_id() << std::endl << "this->get_family_id() = " << this->get_family_id() << std::endl;); @@ -505,9 +504,8 @@ 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;); - m_trail.push_back(a); variable_set.insert(a); internal_variable_set.insert(a); track_variable_scope(a); @@ -517,19 +515,18 @@ 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); + m_trail.push_back(a); ctx.internalize(a, false); SASSERT(ctx.get_enode(a) != NULL); 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;); - m_trail.push_back(a); variable_set.insert(a); //internal_variable_set.insert(a); regex_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)); @@ -1988,7 +1984,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 +2052,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 +2123,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 +4495,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 +4506,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,7 +4652,7 @@ namespace smt { } } - bool theory_str::get_value(expr* e, rational& val) const { + bool theory_str::get_arith_value(expr* e, rational& val) const { if (opt_DisableIntegerTheoryIntegration) { TRACE("str", tout << "WARNING: integer theory integration disabled" << std::endl;); return false; @@ -4785,7 +4781,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 +4804,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 +4872,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 +5009,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;); } @@ -5563,7 +5558,7 @@ namespace smt { if (arg0VecSize > 0 && arg1VecSize > 0 && u.str.is_string(arg0_grdItor->first[arg0VecSize - 1]) && u.str.is_string(arg1_grdItor->first[0])) { ndVec.pop_back(); ndVec.push_back(mk_concat(arg0_grdItor->first[arg0VecSize - 1], arg1_grdItor->first[0])); - for (int i = 1; i < arg1VecSize; i++) { + for (size_t i = 1; i < arg1VecSize; i++) { ndVec.push_back(arg1_grdItor->first[i]); } } else { @@ -5625,8 +5620,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 +5628,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; ); @@ -5666,7 +5660,7 @@ namespace smt { if (subStrCnt == 1) { zstring subStrVal; if (u.str.is_string(subStrVec[0], subStrVal)) { - for (int i = 0; i < strCnt; i++) { + for (size_t i = 0; i < strCnt; i++) { zstring strVal; if (u.str.is_string(strVec[i], strVal)) { if (strVal.contains(subStrVal)) { @@ -5675,7 +5669,7 @@ namespace smt { } } } else { - for (int i = 0; i < strCnt; i++) { + for (size_t i = 0; i < strCnt; i++) { if (strVec[i] == subStrVec[0]) { return true; } @@ -5683,7 +5677,7 @@ namespace smt { } return false; } else { - for (int i = 0; i <= (strCnt - subStrCnt); i++) { + for (size_t i = 0; i <= (strCnt - subStrCnt); i++) { // The first node in subStrVect should be // * constant: a suffix of a note in strVec[i] // * variable: @@ -5712,7 +5706,7 @@ namespace smt { // middle nodes bool midNodesOK = true; - for (int j = 1; j < subStrCnt - 1; j++) { + for (size_t j = 1; j < subStrCnt - 1; j++) { if (subStrVec[j] != strVec[i + j]) { midNodesOK = false; break; @@ -6927,16 +6921,16 @@ namespace smt { ast_manager & m = get_manager(); if (lenTester_fvar_map.contains(lenTester)) { expr * fVar = lenTester_fvar_map[lenTester]; - expr * toAssert = gen_len_val_options_for_free_var(fVar, lenTester, lenTesterValue); + expr_ref toAssert(gen_len_val_options_for_free_var(fVar, lenTester, lenTesterValue), m); TRACE("str", tout << "asserting more length tests for free variable " << mk_ismt2_pp(fVar, m) << std::endl;); - if (toAssert != NULL) { + if (toAssert) { assert_axiom(toAssert); } } } 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 +6985,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,9 +7295,10 @@ 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) { + } else if (ex_sort == bool_sort && !is_quantifier(ex)) { TRACE("str", tout << "setting up axioms for " << mk_ismt2_pp(ex, get_manager()) << ": expr is of sort Bool" << std::endl;); // set up axioms for boolean terms @@ -7351,7 +7345,7 @@ namespace smt { // if expr is an application, recursively inspect all arguments if (is_app(ex)) { - app * term = (app*)ex; + app * term = to_app(ex); unsigned num_args = term->get_num_args(); for (unsigned i = 0; i < num_args; i++) { set_up_axioms(term->get_arg(i)); @@ -7388,7 +7382,6 @@ namespace smt { } void theory_str::init_search_eh() { - ast_manager & m = get_manager(); context & ctx = get_context(); TRACE("str", @@ -7396,7 +7389,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 +7404,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 +7439,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 +7506,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 +7514,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 +7538,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 +8440,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 +8611,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 +8648,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 +8821,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 +8829,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 +9064,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 +9072,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; @@ -9123,7 +9081,7 @@ namespace smt { zstring theory_str::gen_val_string(int len, int_vector & encoding) { SASSERT(charSetSize > 0); - SASSERT(char_set != NULL); + SASSERT(!char_set.empty()); std::string re(len, char_set[0]); for (int i = 0; i < (int) encoding.size() - 1; i++) { @@ -9173,7 +9131,7 @@ namespace smt { } } - expr * theory_str::gen_val_options(expr * freeVar, expr * len_indicator, expr * val_indicator, + expr* theory_str::gen_val_options(expr * freeVar, expr * len_indicator, expr * val_indicator, zstring lenStr, int tries) { ast_manager & m = get_manager(); context & ctx = get_context(); @@ -9194,7 +9152,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 +9175,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,11 +9197,10 @@ namespace smt { ); // ---------------------------------------------------------------------------------------- - - ptr_vector orList; - ptr_vector andList; - for (long long i = l; i < h; i++) { + expr_ref_vector orList(m), andList(m); + + 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); @@ -9262,7 +9219,7 @@ namespace smt { } else { strAst = mk_string(aStr); } - andList.push_back(m.mk_eq(orList[orList.size() - 1], m.mk_eq(freeVar, strAst))); + andList.push_back(m.mk_eq(orList[orList.size() - 1].get(), m.mk_eq(freeVar, strAst))); } if (!coverAll) { orList.push_back(m.mk_eq(val_indicator, mk_string("more"))); @@ -9273,21 +9230,8 @@ namespace smt { } } - expr ** or_items = alloc_svect(expr*, orList.size()); - expr ** and_items = alloc_svect(expr*, andList.size() + 1); - - for (int i = 0; i < (int) orList.size(); i++) { - or_items[i] = orList[i]; - } - if (orList.size() > 1) - and_items[0] = m.mk_or(orList.size(), or_items); - else - and_items[0] = or_items[0]; - - for (int i = 0; i < (int) andList.size(); i++) { - and_items[i + 1] = andList[i]; - } - expr * valTestAssert = m.mk_and(andList.size() + 1, and_items); + andList.push_back(mk_or(orList)); + expr_ref valTestAssert = mk_and(andList); // --------------------------------------- // If the new value tester is $$_val_x_16_i @@ -9300,20 +9244,9 @@ namespace smt { if (vTester != val_indicator) andList.push_back(m.mk_eq(vTester, mk_string("more"))); } - expr * assertL = NULL; - if (andList.size() == 1) { - assertL = andList[0]; - } else { - expr ** and_items = alloc_svect(expr*, andList.size()); - for (int i = 0; i < (int) andList.size(); i++) { - and_items[i] = andList[i]; - } - assertL = m.mk_and(andList.size(), and_items); - } - + expr_ref assertL = mk_and(andList); // (assertL => valTestAssert) <=> (!assertL OR valTestAssert) - valTestAssert = m.mk_or(m.mk_not(assertL), valTestAssert); - return valTestAssert; + return m.mk_or(m.mk_not(assertL), valTestAssert); } expr * theory_str::gen_free_var_options(expr * freeVar, expr * len_indicator, @@ -9371,21 +9304,20 @@ 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;); refresh_theory_var(aTester); - expr * makeupAssert = gen_val_options(freeVar, len_indicator, aTester, len_valueStr, i); + expr_ref makeupAssert(gen_val_options(freeVar, len_indicator, aTester, len_valueStr, i), m); TRACE("str", tout << "var: " << mk_ismt2_pp(freeVar, m) << std::endl << 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;); } } @@ -9400,8 +9332,7 @@ namespace smt { fvar_valueTester_map[freeVar][len].push_back(std::make_pair(sLevel, valTester)); print_value_tester_list(fvar_valueTester_map[freeVar][len]); } - expr * nextAssert = gen_val_options(freeVar, len_indicator, valTester, len_valueStr, i + 1); - return nextAssert; + return gen_val_options(freeVar, len_indicator, valTester, len_valueStr, i + 1); } return NULL; @@ -9540,8 +9471,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; @@ -9549,7 +9480,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() : "?") @@ -10292,7 +10223,7 @@ namespace smt { } else { tout << "no eqc string constant"; } - tout << std::endl;); + tout << std::endl;); (void)effectiveInScope; if (effectiveLenInd == lenTesterInCbEq) { effectiveLenIndiStr = lenTesterValue; } else { @@ -10377,7 +10308,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; @@ -10404,8 +10334,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 4752e8a1b9e..7f39efa707c 100644 --- a/src/smt/theory_str.h +++ b/src/smt/theory_str.h @@ -219,7 +219,7 @@ class theory_str : public theory { /* * 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. * @@ -330,9 +330,9 @@ class theory_str : public theory { std::map regex_nfa_cache; // Regex term --> NFA - char * char_set; - std::map charSetLookupTable; - int charSetSize; + svector char_set; + std::map charSetLookupTable; + int charSetSize; obj_pair_map concat_astNode_map; @@ -464,7 +464,7 @@ class theory_str : public theory { 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); @@ -553,7 +553,7 @@ class theory_str : public theory { expr * gen_len_test_options(expr * freeVar, expr * indicator, int tries); expr * gen_free_var_options(expr * freeVar, expr * len_indicator, zstring len_valueStr, expr * valTesterInCbEq, zstring valTesterValueStr); - expr * gen_val_options(expr * freeVar, expr * len_indicator, expr * val_indicator, + expr* gen_val_options(expr * freeVar, expr * len_indicator, expr * val_indicator, zstring lenStr, int tries); void print_value_tester_list(svector > & testerList); bool get_next_val_encode(int_vector & base, int_vector & next); 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/src/solver/smt_logics.cpp b/src/solver/smt_logics.cpp index c4ead74dfcc..2bb364b6a8a 100644 --- a/src/solver/smt_logics.cpp +++ b/src/solver/smt_logics.cpp @@ -153,5 +153,5 @@ bool smt_logics::logic_has_pb(symbol const& s) { } bool smt_logics::logic_has_datatype(symbol const& s) { - return s == "QF_FD"; + return s == "QF_FD" || s == "ALL"; } 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 324d8089be4..e7cfdb64424 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 1e1a0d26690..51ea9b6d3a1 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 cdc42367a2b..33502083899 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 1aef52d78f2..e00b1e9c049 100644 --- a/src/tactic/arith/elim01_tactic.cpp +++ b/src/tactic/arith/elim01_tactic.cpp @@ -169,7 +169,7 @@ class elim01_tactic : public tactic { 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 4c2e0deadc8..8f37a8d5e32 100644 --- a/src/tactic/arith/lia2card_tactic.cpp +++ b/src/tactic/arith/lia2card_tactic.cpp @@ -176,7 +176,7 @@ class lia2card_tactic : public tactic { 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 90ed65e3fd3..e9f0927d5bb 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 1b324b2eb80..94c9935b953 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 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier { 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 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier { 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 2b9cfb7f355..3ae72215f1c 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 fcd26bd8438..1f766bd4766 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 ea59641c956..483b59776c4 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 8e8879fef9b..3b820de7a16 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 @@ class collect_statistics_tactic : public tactic { 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 @@ class collect_statistics_tactic : public tactic { g->inc_depth(); result.push_back(g.get()); - } + } virtual void cleanup() {} @@ -98,11 +98,12 @@ class collect_statistics_tactic : public tactic { 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 @@ class collect_statistics_tactic : public tactic { 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 @@ class collect_statistics_tactic : public tactic { 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 @@ class collect_statistics_tactic : public tactic { 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 d93cd5b821d..a5421223595 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 b14d2676c61..a3cac9e2e2d 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 e28b1196651..ccfc0e3efac 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 c6f621f25fe..a8a9b2bbaed 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 83693abbacd..e293ade173a 100644 --- a/src/tactic/portfolio/bounded_int2bv_solver.cpp +++ b/src/tactic/portfolio/bounded_int2bv_solver.cpp @@ -168,7 +168,7 @@ class bounded_int2bv_solver : public solver_na2as { // 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; @@ -228,7 +228,7 @@ class bounded_int2bv_solver : public solver_na2as { 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 35601f374b0..8c9ff122dd0 100644 --- a/src/tactic/portfolio/enum2bv_solver.cpp +++ b/src/tactic/portfolio/enum2bv_solver.cpp @@ -116,7 +116,7 @@ class enum2bv_solver : public solver_na2as { // 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)); } @@ -128,7 +128,7 @@ class enum2bv_solver : public solver_na2as { // 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 8b720b333dc..436b1742fc0 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 840dd008a7c..c90fd746837 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/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp index 918e0fc6db4..ca6390c9c90 100644 --- a/src/tactic/smtlogics/qfbv_tactic.cpp +++ b/src/tactic/smtlogics/qfbv_tactic.cpp @@ -103,7 +103,7 @@ static tactic * mk_qfbv_tactic(ast_manager& m, params_ref const & p, tactic* sat tactic * st = main_p(and_then(preamble_st, // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function // symbols. In this case, we should not use the `sat', but instead `smt'. Alternatively, - // the UFs can be eliminated by eager ackermannization in the preamble. + // the UFs can be eliminated by eager ackermannization in the preamble. cond(mk_is_qfbv_eq_probe(), and_then(mk_bv1_blaster_tactic(m), using_params(smt, solver_p)), 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 c1d6daaaa18..511dc2b2d0d 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/bit_vector.cpp b/src/test/bit_vector.cpp index 7d3f96ae44c..6f83bb32824 100644 --- a/src/test/bit_vector.cpp +++ b/src/test/bit_vector.cpp @@ -48,7 +48,7 @@ static void tst1() { SASSERT(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) { diff --git a/src/test/bv_simplifier_plugin.cpp b/src/test/bv_simplifier_plugin.cpp index dc930bb82db..69b97a9cc1e 100644 --- a/src/test/bv_simplifier_plugin.cpp +++ b/src/test/bv_simplifier_plugin.cpp @@ -133,7 +133,7 @@ class tst_bv_simplifier_plugin_cls { 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); @@ -163,11 +163,11 @@ class tst_bv_simplifier_plugin_cls { 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 @@ class tst_bv_simplifier_plugin_cls { 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/check_assumptions.cpp b/src/test/check_assumptions.cpp index fa8327cd4af..918513ca04b 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 14fc594b607..3fdf96f8735 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/dl_context.cpp b/src/test/dl_context.cpp index ac09722ac69..8a62dcb7def 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); @@ -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_query.cpp b/src/test/dl_query.cpp index ae7313e4138..e69f1fb13d3 100644 --- a/src/test/dl_query.cpp +++ b/src/test/dl_query.cpp @@ -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()); diff --git a/src/test/ext_numeral.cpp b/src/test/ext_numeral.cpp index 0e2b691c926..6f92b1372c8 100644 --- a/src/test/ext_numeral.cpp +++ b/src/test/ext_numeral.cpp @@ -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) 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/heap.cpp b/src/test/heap.cpp index e745463ff3c..17f9cfaa03a 100644 --- a/src/test/heap.cpp +++ b/src/test/heap.cpp @@ -47,12 +47,13 @@ static void tst1() { for (; it != end; ++it) { SASSERT(h.contains(*it)); } - int last = -1; while (!h.empty()) { int m1 = h.min_value(); int m2 = h.erase_min(); + (void)m1; + (void)m2; SASSERT(m1 == m2); - SASSERT(last < m2); + SASSERT(-1 < m2); } } @@ -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; diff --git a/src/test/hwf.cpp b/src/test/hwf.cpp index be32b54008f..7a030a4520d 100644 --- a/src/test/hwf.cpp +++ b/src/test/hwf.cpp @@ -44,19 +44,19 @@ 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); diff --git a/src/test/karr.cpp b/src/test/karr.cpp index c5581cc665c..c69932e228f 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; diff --git a/src/test/list.cpp b/src/test/list.cpp index 5672f42460b..a7ad76972de 100644 --- a/src/test/list.cpp +++ b/src/test/list.cpp @@ -35,6 +35,7 @@ static void tst1() { 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 00000000000..6683a1758a5 --- /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 706167f4990..9590baf7b9a 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 3f9e2a4ceee..d402d4ff78d 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() { @@ -1159,12 +1159,14 @@ void solve_mps_double(std::string file_name, bool look_for_min, unsigned max_ite lp_solver * solver = reader.create_solver(dual); setup_solver(max_iterations, time_limit, look_for_min, args_parser, solver); - int begin = get_millisecond_count(); + stopwatch sw; + sw.start(); if (dual) { std::cout << "solving for dual" << std::endl; } solver->find_maximal_solution(); - int span = get_millisecond_span(begin); + sw.stop(); + double span = sw.get_seconds(); std::cout << "Status: " << lp_status_to_string(solver->get_status()) << std::endl; if (solver->get_status() == lp_status::OPTIMAL) { if (reader.column_names().size() < 20) { @@ -1198,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); } } } @@ -1208,12 +1210,13 @@ 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); setup_solver(max_iterations, time_limit, look_for_min, args_parser, solver); - int begin = get_millisecond_count(); + stopwatch sw; + sw.start(); solver->find_maximal_solution(); std::cout << "Status: " << lp_status_to_string(solver->get_status()) << std::endl; @@ -1221,13 +1224,13 @@ 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; } std::cout << "cost = " << cost.get_double() << std::endl; } - std::cout << "processed in " << get_millisecond_span(begin) / 1000.0 << " seconds, running for " << solver->m_total_iterations << " iterations" << std::endl; + std::cout << "processed in " << sw.get_current_seconds() / 1000.0 << " seconds, running for " << solver->m_total_iterations << " iterations" << std::endl; delete solver; } else { std::cout << "cannot process " << file_name << std::endl; @@ -1259,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); @@ -1271,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 { @@ -1315,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); @@ -1338,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 @@ -1367,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) { @@ -1378,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) { @@ -1463,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) { @@ -1653,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; @@ -1663,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; @@ -1673,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) { @@ -1703,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])); - } - - 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); + 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"] = 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)); } } @@ -1802,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); } @@ -1826,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)); } } @@ -1854,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); } } } @@ -1958,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; @@ -1968,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; @@ -2017,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); @@ -2025,7 +2028,7 @@ void test_stacked_set() { s.push(); s.insert(4); s.pop(3); - lean_assert(s() == scopy); + lp_assert(s() == scopy); #endif } @@ -2394,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()); @@ -2422,19 +2425,20 @@ 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; } - int begin = get_millisecond_count(); + stopwatch sw; + sw.start(); lp_status status = solver->solve(); - std::cout << "status is " << lp_status_to_string(status) << ", processed for " << get_millisecond_span(begin) / 1000.0 <<" seconds, and " << solver->get_total_iterations() << " iterations" << std::endl; - if (solver->get_status() == INFEASIBLE) { - vector> evidence; + 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() == 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; } @@ -2463,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; @@ -2474,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; @@ -2520,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) { @@ -2562,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); @@ -2590,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") @@ -2603,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; @@ -2643,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 } @@ -2713,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); @@ -2741,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() { /* @@ -2937,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(); @@ -2958,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); } @@ -3222,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(); @@ -3239,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 a301f38c685..450664fd0d0 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 dd38c6bcd1d..a2ee0f27164 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 c7a9e3b8bbb..5daeb21b60b 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/model_based_opt.cpp b/src/test/model_based_opt.cpp index 64b2df28543..5ee671a4ac8 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 0b509fba622..00048b2304a 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/mpff.cpp b/src/test/mpff.cpp index 44930f2bdb6..ca2354b8b9c 100644 --- a/src/test/mpff.cpp +++ b/src/test/mpff.cpp @@ -435,7 +435,7 @@ static void tst_limits(unsigned prec) { 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)); diff --git a/src/test/mpz.cpp b/src/test/mpz.cpp index ee7cf39f113..02627e8424a 100644 --- a/src/test/mpz.cpp +++ b/src/test/mpz.cpp @@ -147,6 +147,7 @@ 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); m.del(x); @@ -174,6 +175,7 @@ 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); m.del(x); diff --git a/src/test/nlsat.cpp b/src/test/nlsat.cpp index 27a0aa1da87..df25db92777 100644 --- a/src/test/nlsat.cpp +++ b/src/test/nlsat.cpp @@ -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 << " "; diff --git a/src/test/object_allocator.cpp b/src/test/object_allocator.cpp index 16b9331e240..cca42cf6f7c 100644 --- a/src/test/object_allocator.cpp +++ b/src/test/object_allocator.cpp @@ -61,6 +61,7 @@ static void tst1() { m.recycle(c1); cell * c3 = m.allocate(); + (void)c3; SASSERT(c3->m_coeff.is_zero()); } diff --git a/src/test/old_interval.cpp b/src/test/old_interval.cpp index 92064c03e33..12a45555df4 100644 --- a/src/test/old_interval.cpp +++ b/src/test/old_interval.cpp @@ -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))); } diff --git a/src/test/pb2bv.cpp b/src/test/pb2bv.cpp index c114997c5f4..fcc30988341 100644 --- a/src/test/pb2bv.cpp +++ b/src/test/pb2bv.cpp @@ -83,10 +83,10 @@ 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/polynorm.cpp b/src/test/polynorm.cpp index a8f4ab861a9..987d8e13b92 100644 --- a/src/test/polynorm.cpp +++ b/src/test/polynorm.cpp @@ -88,6 +88,8 @@ class polynorm { expr_ref_vector& factors = poly.factors(); expr_ref_vector& coefficients = poly.coefficients(); expr_ref& coefficient = poly.coefficient(); + (void) coefficient; + (void) coefficients; m_rw(term); @@ -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); diff --git a/src/test/proof_checker.cpp b/src/test/proof_checker.cpp index 7f9827187bf..035326b26c5 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 a73f7ed3807..a52c02ecba8 100644 --- a/src/test/qe_arith.cpp +++ b/src/test/qe_arith.cpp @@ -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/rational.cpp b/src/test/rational.cpp index 834aab92f55..ac478af9822 100644 --- a/src/test/rational.cpp +++ b/src/test/rational.cpp @@ -196,7 +196,7 @@ static void tst2() { // 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); diff --git a/src/test/sat_user_scope.cpp b/src/test/sat_user_scope.cpp index aa717f371b1..a271ce6bbb7 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); diff --git a/src/test/simple_parser.cpp b/src/test/simple_parser.cpp index a5d4d8def20..934552711e7 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/small_object_allocator.cpp b/src/test/small_object_allocator.cpp index 1ecf865dd28..5ae2836d0c3 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 81340651abb..87cc05375f4 100644 --- a/src/test/sorting_network.cpp +++ b/src/test/sorting_network.cpp @@ -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/substitution.cpp b/src/test/substitution.cpp index cdc7f20803c..5609225c663 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/upolynomial.cpp b/src/test/upolynomial.cpp index e7dcf2719ca..43aefed9910 100644 --- a/src/test/upolynomial.cpp +++ b/src/test/upolynomial.cpp @@ -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"; @@ -164,7 +164,7 @@ static void check_roots(mpbq_vector const & roots, mpbq_vector const & lowers, m for (unsigned j = 0; j < roots.size(); j++) { if (to_rational(roots[j]) == r) { SASSERT(!visited[j]); - SASSERT(!found); + VERIFY(!found); found = true; visited[j] = true; } @@ -172,7 +172,7 @@ 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); + VERIFY(!found); SASSERT(!visited[j_prime]); found = true; visited[j_prime] = true; @@ -499,7 +499,7 @@ 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"; 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 b76f909d06f..7ed68c89ffd 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/hwf.cpp b/src/util/hwf.cpp index e577e15dfea..a522c9a41b6 100644 --- a/src/util/hwf.cpp +++ b/src/util/hwf.cpp @@ -29,7 +29,7 @@ Revision History: #include #endif -#if defined(__x86_64__) || defined(_M_X64) || \ +#if defined(__x86_64__) || defined(_M_X64) || \ defined(__i386) || defined(_M_IX86) #define USE_INTRINSICS #endif 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 e33764f69a3..72c2482bb6c 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 a6206948ca7..04faefd5b6d 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 @@ class binary_heap_priority_queue { /// 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 440b45b0228..d6d9a535834 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 567494d6f0f..12b853fc883 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 26cfd553281..ec7f4e85f22 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 a48bdb5b73c..2a162fa0685 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 4c4603110c0..d315e9bdab4 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 508692e5a89..45f5288b16d 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 0d58ec2beb5..cfb3aa68f3e 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 92523d75fd6..2ef0856fd3a 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 @@ class bound_propagator { 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 e5454db0ef8..ff3a03e9461 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 56e75a1fbf2..02c2f638ba3 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 @@ class column_info { } 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 @@ class column_info { } 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 1a10a5a23f0..66b6a55dbe7 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 @@ class column_namer { 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 bff2ad56371..cd857748358 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 2a3a14b31e7..cf4caf19dbc 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 786b8b3a1c9..8890f8c2084 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 cfa72f72559..e3801228cff 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 233f7401642..6f2f54338dc 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 @@ class dense_matrix: public matrix { 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 e42d9e3a45e..8850d4f747f 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 1e931211dd4..418e2f2e089 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 51b015066c9..cfcd11256d3 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 @@ class eta_matrix 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 142a408d1f2..dc1ba9ce5ea 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 d57d43fed58..470a1680063 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 6fe31d5cd20..3d2457a5caa 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 9583e3cd87c..45911476fc5 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 7963dfdf9b4..08a821d1038 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 6e6a6009b2e..6c0c32414a4 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 @@ class indexed_vector { } 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 64e329adcf7..ff3effeb505 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 6f17a894f18..0d6f8c5d2e2 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 0619facd8d9..931125ab562 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 @@ class int_set { 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 e7ea24a6f9f..90dfef76768 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 b74a25855ed..104e9b32125 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 @@ class int_solver { // 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 @@ class int_solver { // 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 215514b392f..a3875deef89 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 532b626179a..253661c3877 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 1a9381a702c..cfd0feba465 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 96a1a8cf36c..d5f42340bca 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 3dd217103b5..3210b1c27b8 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 ee0864a4ebf..bd11896fb07 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 @@ class lar_constraint : public lar_base_constraint { : 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 71d69c3a465..01afc866c94 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 @@ class lar_core_solver { } 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { // 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { } 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { #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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 @@ class lar_core_solver { case column_type::fixed: return true; default: - lean_assert(false); + lp_assert(false); } return false; } @@ -744,20 +744,20 @@ class lar_core_solver { 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 @@ class lar_core_solver { 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 a6dd7e3e011..6f7f7e72044 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 2c4169c81f1..6c8598a7315 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 882ce229eff..e7ef4f7487c 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; } -} // namespace lean + +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); + } +} + + +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 02ded6a724e..e584c2f2603 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 @@ class lar_solver : public column_namer { 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 @@ class lar_solver : public column_namer { 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 @@ class lar_solver : public column_namer { 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 @@ class lar_solver : public column_namer { void clear(); - lar_solver(); void set_propagate_bounds_on_pivoted_rows_mode(bool v); @@ -215,7 +223,7 @@ class lar_solver : public column_namer { 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 @@ class lar_solver : public column_namer { 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 @@ class lar_solver : public column_namer { 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 @@ class lar_solver : public column_namer { 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 @@ class lar_solver : public column_namer { 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 @@ class lar_solver : public column_namer { 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 @@ class lar_solver : public column_namer { 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 @@ class lar_solver : public column_namer { 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(); + } + + 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); } - inline bool column_is_real(unsigned j) const { return !column_is_integer(j); } - final_check_status check_int_feasibility(); + bool has_int_var() const; }; } diff --git a/src/util/lp/lar_solver_instances.cpp b/src/util/lp/lar_solver_instances.cpp index ccde7e57469..602df032670 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 0e715ad0bd3..10e58dafab7 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 634accfd476..d8a67f1b81b 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 a12b7b5d202..0a07055a421 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 @@ class lp_core_solver_base { 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 @@ class lp_core_solver_base { 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 @@ class lp_core_solver_base { 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 @@ class lp_core_solver_base { } 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 @@ class lp_core_solver_base { case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); break; } return false; @@ -429,6 +445,7 @@ class lp_core_solver_base { 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 @@ class lp_core_solver_base { } 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 @@ class lp_core_solver_base { } 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 @@ class lp_core_solver_base { case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); break; } return true; @@ -566,10 +584,10 @@ class lp_core_solver_base { 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 @@ class lp_core_solver_base { 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 @@ class lp_core_solver_base { 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 a0dba9de769..5ac6c4c224a 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; - - 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) + for (; i < m_basis.size(); i++) { + unsigned basic_j = m_basis[i]; + + 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 17dcb87db17..1f9d459bfb6 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 b873cb711a1..71a00c2680e 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 6565331b343..1b6e696d723 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 8016088f8f4..9484d34a304 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 4dff2a4f164..58d9b72401b 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 5047e117fa4..7f6f686ca88 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 6610814d80b..a79a93748f9 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 3fada1e5d00..7577516d2e6 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 @@ class lp_primal_core_solver:public lp_core_solver_base { // 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { default: return -1; } - lean_assert(false); // unreachable + lp_assert(false); // unreachable return 0; } @@ -159,7 +159,7 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { default: return false; } - lean_assert(false); // unreachable + lp_assert(false); // unreachable return false; } @@ -329,24 +329,24 @@ class lp_primal_core_solver:public lp_core_solver_base { } 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { // } 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { } 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 @@ class lp_primal_core_solver:public lp_core_solver_base { } 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 @@ class lp_primal_core_solver:public lp_core_solver_base { } } 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 @@ class lp_primal_core_solver:public lp_core_solver_base { } 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 @@ class lp_primal_core_solver:public lp_core_solver_base { break; default: - lean_unreachable(); + lp_unreachable(); } if (!unlimited && theta < zero_of_type()) { theta = zero_of_type(); @@ -778,7 +779,7 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 @@ class lp_primal_core_solver:public lp_core_solver_base { case column_type::free_column: return 0; default: - lean_assert(false); + lp_assert(false); } return 0; } @@ -837,7 +838,7 @@ class lp_primal_core_solver:public lp_core_solver_base { return -1; break; default: - lean_assert(false); + lp_assert(false); } return 0; @@ -863,7 +864,7 @@ class lp_primal_core_solver:public lp_core_solver_base { // 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 @@ class lp_primal_core_solver:public lp_core_solver_base { } else { m_converted_harris_eps = zero_of_type(); } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } // constructor @@ -942,7 +943,7 @@ class lp_primal_core_solver:public lp_core_solver_base { 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 47eec468a1f..27c92e5e035 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 ca231fd34e4..8e5890bf528 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 0c09c22c9b3..867c321bacd 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 fcddb4eb1ff..b55fecdcdeb 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; @@ -55,10 +55,6 @@ class lp_primal_simplex: public lp_solver { void set_core_solver_bounds(); - void update_time_limit_from_starting_time(int start_time) { - this->m_settings.time_limit -= (get_millisecond_span(start_time) / 1000.); - } - void find_maximal_solution(); void fill_A_x_and_basis_for_stage_one_total_inf(); diff --git a/src/util/lp/lp_primal_simplex.hpp b/src/util/lp/lp_primal_simplex.hpp index 9e1af2bbe25..75909535531 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; @@ -152,7 +152,6 @@ template void lp_primal_simplex::set_core_solver_ template void lp_primal_simplex::find_maximal_solution() { - int preprocessing_start_time = get_millisecond_count(); if (this->problem_is_empty()) { this->m_status = lp_status::EMPTY; return; @@ -169,7 +168,6 @@ template void lp_primal_simplex::find_maximal_sol fill_acceptable_values_for_x(); this->count_slacks_and_artificials(); set_core_solver_bounds(); - update_time_limit_from_starting_time(preprocessing_start_time); solve_with_total_inf(); } @@ -179,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(); @@ -211,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(); @@ -283,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 << ") "; @@ -331,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 37b63948928..249be218cdd 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 3f082ab1019..895d6e6781d 100644 --- a/src/util/lp/lp_settings.h +++ b/src/util/lp/lp_settings.h @@ -8,32 +8,25 @@ #include #include #include -#include #include #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, @@ -80,21 +73,20 @@ enum non_basic_column_value_position { at_low_bound, at_upper_bound, at_fixed, f template bool is_epsilon_small(const X & v, const double& eps); // forward definition -int get_millisecond_count(); -int get_millisecond_span(int start_time); - - class lp_resource_limit { public: virtual bool get_cancel_flag() = 0; }; 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)); } }; @@ -103,12 +95,13 @@ struct lp_settings { private: class default_lp_resource_limit : public lp_resource_limit { lp_settings& m_settings; - int m_start_time; + stopwatch m_sw; public: - default_lp_resource_limit(lp_settings& s): m_settings(s), m_start_time(get_millisecond_count()) {} + default_lp_resource_limit(lp_settings& s): m_settings(s) { + m_sw.start(); + } virtual bool get_cancel_flag() { - int span_in_mills = get_millisecond_span(m_start_time); - return (span_in_mills / 1000.0 > m_settings.time_limit); + return (m_sw.get_current_seconds() > m_settings.time_limit); } }; @@ -212,7 +205,8 @@ struct lp_settings { 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; } @@ -292,13 +286,13 @@ struct lp_settings { 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 { @@ -319,6 +313,7 @@ struct lp_settings { 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 @@ -380,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 b57a3acda49..fd5d8d8eacc 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,22 +49,9 @@ 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 } -int get_millisecond_count() { - timeb tb; - ftime(&tb); - return tb.millitm + (tb.time & 0xfffff) * 1000; -} - -int get_millisecond_span(int start_time) { - int span = get_millisecond_count() - start_time; - if (span < 0) - span += 0x100000 * 1000; - return span; -} - template diff --git a/src/util/lp/lp_settings_instances.cpp b/src/util/lp/lp_settings_instances.cpp index e9a3888ba7b..9e809e7c6fb 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 1bfe7dcdc9c..6c878c68708 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 135616a6932..3c7f35587b5 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 5df490caefb..dce86914cd3 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 8cb98974e40..7d5f46f2d6a 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 2be15d79aab..e1d5c5b8a91 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 0d8163a1475..ff95fe25813 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 @@ class one_elem_on_diag: public tail_matrix { 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 @@ class lu { 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 @@ class lu { 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 @@ class lu { 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 2d2c7c7c4f9..64ac8efe22b 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 c8ff7b2f47f..97fa3eed908 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 63fd5c01ef5..fb177551e38 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 27cdabd3e7e..45e4c3da2f8 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()) @@ -58,8 +58,8 @@ unsigned get_width_of_column(unsigned j, vector> & A) { unsigned r = 0; for (unsigned i = 0; i < A.size(); i++) { vector & t = A[i]; - std::string str= t[j]; - unsigned s = str.size(); + std::string str = t[j]; + unsigned s = static_cast(str.size()); if (r < s) { r = s; } @@ -69,8 +69,8 @@ unsigned get_width_of_column(unsigned j, vector> & A) { void print_matrix_with_widths(vector> & A, vector & ws, std::ostream & out) { for (unsigned i = 0; i < A.size(); i++) { - for (unsigned j = 0; j < A[i].size(); j++) { - print_blanks(ws[j] - A[i][j].size(), out); + for (unsigned j = 0; j < static_cast(A[i].size()); j++) { + print_blanks(ws[j] - static_cast(A[i][j].size()), out); out << A[i][j] << " "; } out << std::endl; diff --git a/src/util/lp/matrix_instances.cpp b/src/util/lp/matrix_instances.cpp index aeee6278692..ae37a2e69df 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 eb83735ca9b..257cf63e260 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 48d957aab44..dd5d970bf92 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; - - 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 + scoped_ptr m_nlsat; + vector m_monomials; + unsigned_vector m_monomials_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; + + nlsat::assumption a = this + idx; switch (k) { - case lean::lconstraint_kind::LE: - lit = ~m_nlsat.mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even); + case lp::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); + case lp::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); + case lp::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); + case lp::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); + case lp::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); + 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 cc09e24d6fa..70e614e910b 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 84c99b3b18e..b41f6b56597 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 4bdd57f25d7..e0a3ac4c19a 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 ec9af5a50bf..a379e1ab28a 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 91473fabc2a..756ce432552 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 df409240e19..53c7ecfca37 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 9faa5f41c7e..952199f8575 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 8cb9740eae6..68b14c9716f 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 7c6a0539f74..ced6a3767a4 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 90acb89f3c9..60adb23aefd 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 @@ class row_eta_matrix } 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 5758abeb81c..11f8f4913a5 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 c3202316495..7ccedf8449c 100644 --- a/src/util/lp/row_eta_matrix_instances.cpp +++ b/src/util/lp/row_eta_matrix_instances.cpp @@ -6,7 +6,7 @@ #include #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 33c5a6cc414..61869f0828a 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 @@ class scaler { 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 69427eea008..482441d7fbf 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 f97e8098f8c..de1c2b7aa64 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 a22c188b4b8..6a0b4115f77 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 7256004dad5..17f9ed7e0ef 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 @@ class sparse_matrix 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 @@ class sparse_matrix // 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 @@ class sparse_matrix 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 ff6ac999726..a26f36ae9eb 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 @@ -1050,12 +1050,12 @@ bool sparse_matrix::get_pivot_for_column(unsigned &i, unsigned &j, int c_p if (i_inv < k) continue; unsigned j_inv = adjust_column_inverse(j); if (j_inv < k) continue; - int small = elem_is_too_small(i, j, c_partial_pivoting); - if (!small) { + int _small = elem_is_too_small(i, j, c_partial_pivoting); + if (!_small) { #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); @@ -1063,7 +1063,7 @@ bool sparse_matrix::get_pivot_for_column(unsigned &i, unsigned &j, int c_p j = j_inv; return true; } - if (small != 2) { // 2 means that the pair is not in the matrix + if (_small != 2) { // 2 means that the pair is not in the matrix pivots_candidates_that_are_too_small.push_back(std::make_pair(i, j)); } } @@ -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 f80b603653e..80a9b8ef500 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 975cb7f288c..65bd6d3f3c9 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 @@ class sparse_vector { } #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 019497aa5df..c5aa1fa97d3 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 @@ class square_dense_submatrix : public tail_matrix { 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 @@ class square_dense_submatrix : public tail_matrix { } } } - 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 @@ class square_dense_submatrix : public tail_matrix { } } #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 @@ class square_dense_submatrix : public tail_matrix { } } 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 365c9d7f047..809d5c5a686 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 7d45aaaa102..7283bb3da2e 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 4692540dd6f..1c55b9f9f0c 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 @@ class stacked_map { 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 @@ class stacked_map { 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 @@ class stacked_map { 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 @@ class stacked_map { 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 69c4cf03bf7..88bb3160c86 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 @@ template -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 3f39dd346d8..4ed6f44d900 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 @@ template < typename B> class stacked_vector { 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 @@ template < typename B> class stacked_vector { 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 @@ template < typename B> class stacked_vector { 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 @@ template < typename B> class stacked_vector { /* 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 @@ template < typename B> class stacked_vector { 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 @@ template < typename B> class stacked_vector { } 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 @@ template < typename B> class stacked_vector { 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 @@ template < typename B> class stacked_vector { } 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 5ef4b449f9b..74bcf17cfc4 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 @@ class static_matrix 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 @@ class static_matrix 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 @@ class static_matrix 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 @@ class static_matrix } 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 @@ class static_matrix // 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 @@ class static_matrix 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 @@ class static_matrix 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 fb12da8c43b..1a88b567d74 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 d0e2045c0ce..263021239e5 100644 --- a/src/util/lp/static_matrix_instances.cpp +++ b/src/util/lp/static_matrix_instances.cpp @@ -2,8 +2,8 @@ Copyright (c) 2017 Microsoft Corporation Author: Lev Nachmanson */ -#include "util/vector.h" #include +#include "util/vector.h" #include #include #include "util/lp/static_matrix.hpp" @@ -13,7 +13,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 +23,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 +60,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 c337b09335a..0e9c6320aee 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 262c610c70a..43ba244dc00 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 2e77a7db01f..1df20aa5691 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 474d38802f4..11e17bbf9ef 100644 --- a/src/util/mpq.h +++ b/src/util/mpq.h @@ -176,7 +176,7 @@ class mpq_manager : public mpz_manager { 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 @@ class mpq_manager : public mpz_manager { 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 67947b6027f..c02ac7c3670 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 383ecaeb3e9..2720f1b002b 100644 --- a/src/util/obj_hashtable.h +++ b/src/util/obj_hashtable.h @@ -70,6 +70,7 @@ class obj_map { 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 @@ class obj_map { 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 4fa3382ecbe..26ef7dbb194 100644 --- a/src/util/rational.h +++ b/src/util/rational.h @@ -68,6 +68,8 @@ class rational { 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 bacfbac890c..f62fbc8a6eb 100644 --- a/src/util/scoped_vector.h +++ b/src/util/scoped_vector.h @@ -91,6 +91,31 @@ class scoped_vector { 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 b1f6bba03c0..7a9066030d4 100644 --- a/src/util/stopwatch.h +++ b/src/util/stopwatch.h @@ -43,6 +43,8 @@ class stopwatch } ~stopwatch() {}; + + void add (const stopwatch &s) {/* TODO */} void reset() { m_elapsed.QuadPart = 0; } @@ -90,6 +92,8 @@ class stopwatch { ~stopwatch() {} + void add (const stopwatch &s) {m_time += s.m_time;} + void reset() { m_time = 0ull; } @@ -141,6 +145,8 @@ class stopwatch { ~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 7238a5ef9c7..6fda881108a 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/trace.cpp b/src/util/trace.cpp index 72984d808e0..05a3e49bd83 100644 --- a/src/util/trace.cpp +++ b/src/util/trace.cpp @@ -52,7 +52,7 @@ void disable_trace(const char * tag) { bool is_trace_enabled(const char * tag) { return g_enable_all_trace_tags || - (g_enabled_trace_tags && get_enabled_trace_tags().contains(const_cast(tag))); + (g_enabled_trace_tags && get_enabled_trace_tags().contains(const_cast(tag))); } void close_trace() { diff --git a/src/util/uint_map.h b/src/util/uint_map.h index 13e0a9db323..0344de322b8 100644 --- a/src/util/uint_map.h +++ b/src/util/uint_map.h @@ -38,6 +38,11 @@ class uint_map { 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); diff --git a/src/util/warning.cpp b/src/util/warning.cpp index ed4cd872512..9c6a285b9e7 100644 --- a/src/util/warning.cpp +++ b/src/util/warning.cpp @@ -115,22 +115,22 @@ void format2ostream(std::ostream & out, char const* msg, va_list args) { while (true) { int nc = VPRF(buff.c_ptr(), buff.size(), msg, args); #if !defined(_WINDOWS) && defined(_AMD64_) - // For some strange reason, on Linux 64-bit version, va_list args is reset by vsnprintf. - // Z3 crashes when trying to use va_list args again. + // For some strange reason, on Linux 64-bit version, va_list args is reset by vsnprintf. + // Z3 crashes when trying to use va_list args again. // Hack: I truncate the message instead of expanding the buffer to make sure that // va_list args is only used once. - END_ERR_HANDLER(); - if (nc < 0) { - // vsnprintf didn't work, so we just print the msg - out << msg; - return; - } - if (nc >= static_cast(buff.size())) { + END_ERR_HANDLER(); + if (nc < 0) { + // vsnprintf didn't work, so we just print the msg + out << msg; + return; + } + if (nc >= static_cast(buff.size())) { // truncate the message buff[buff.size() - 1] = 0; - } + } out << buff.c_ptr(); - return; + return; #else if (nc >= 0 && nc < static_cast(buff.size())) break; // success